void block_database::store(const block_type& block)
{
    const uint32_t height = index_.count();
    const auto number_txs = block.transactions.size();
    const uint32_t number_txs32 = static_cast<uint32_t>(number_txs);

    // Write block data.
    const auto write = [&](uint8_t* data)
    {
        satoshi_save(block.header, data);
        auto serial = make_serializer(data + 80);
        serial.write_4_bytes(height);
        serial.write_4_bytes(number_txs32);
        for (const auto& tx: block.transactions)
        {
            const auto tx_hash = hash_transaction(tx);
            serial.write_hash(tx_hash);
        }
    };

    const auto key = hash_block_header(block.header);
    const auto value_size = 80 + 4 + 4 + number_txs * hash_size;
    const auto position = map_.store(key, write, value_size);

    // Write height -> position mapping.
    write_position(position);
}
Esempio n. 2
0
void stealth_database::modify_entries_count()
{
    entries_count_ += entries_written_count_;
    uint8_t* item = file_.data() + 8;
    auto serial = make_serializer(item);
    serial.write_4_bytes(entries_count_);
}
Esempio n. 3
0
data_chunk create_spent_key(const Point& point)
{
    data_chunk spent_key(hash_digest_size + 4);
    auto serial = make_serializer(spent_key.begin());
    serial.write_hash(point.hash);
    serial.write_4_bytes(point.index);
    return spent_key;
}
bool leveldb_common::save_transaction(leveldb_transaction_batch& batch,
    uint32_t block_height, uint32_t tx_index,
    const hash_digest& tx_hash, const transaction_type& block_tx)
{
    if (duplicate_exists(tx_hash, block_height, tx_index))
        return true;
    data_chunk tx_data(8 + satoshi_raw_size(block_tx));
    // Serialize tx.
    auto serial = make_serializer(tx_data.begin());
    serial.write_4_bytes(block_height);
    serial.write_4_bytes(tx_index);
    // Actual tx data.
    auto end_iter = satoshi_save(block_tx, serial.iterator());
    BITCOIN_ASSERT(
        std::distance(tx_data.begin(), end_iter) ==
        8 + satoshi_raw_size(block_tx));
    // Save tx to leveldb
    batch.tx.Put(slice(tx_hash), slice(tx_data));
    // Add inputs to spends database.
    // Coinbase inputs do not spend anything.
    if (!is_coinbase(block_tx))
        for (uint32_t input_index = 0; input_index < block_tx.inputs.size();
            ++input_index)
        {
            const transaction_input_type& input =
                block_tx.inputs[input_index];
            const input_point inpoint{tx_hash, input_index};
            if (!mark_spent_outputs(batch.spend,
                    input.previous_output, inpoint))
                return false;
            if (!add_debit(batch.debit,
                    input, {tx_hash, input_index}, block_height))
                return false;
        }
    // Save address -> output mappings.
    for (uint32_t output_index = 0; output_index < block_tx.outputs.size();
        ++output_index)
    {
        const transaction_output_type& output =
            block_tx.outputs[output_index];
        if (!add_credit(batch.credit,
                output, {tx_hash, output_index}, block_height))
            return false;
    }
    return true;
}
Esempio n. 5
0
void stealth_database::add_header_entry_index(uint32_t block_height)
{
    const uint32_t interval = block_height;
    BITCOIN_ASSERT(interval < max_header_rows_);
    uint64_t offset = header_sector_ + interval * 4;
    uint8_t* iter = file_.data() + offset;
    auto serial = make_serializer(iter);
    serial.write_4_bytes(entries_count_);
}
Esempio n. 6
0
void wrap_fetch_history_args(data_chunk& data,
    const payment_address& address, size_t from_height)
{
    data.resize(1 + short_hash_size + 4);
    auto serial = make_serializer(data.begin());
    serial.write_byte(address.version());
    serial.write_short_hash(address.hash());
    serial.write_4_bytes(from_height);
    BITCOIN_ASSERT(serial.iterator() == data.end());
}
Esempio n. 7
0
uint64_t addr_key_checksum(const output_point& outpoint)
{
    data_chunk checksum_data(hash_digest_size + 4);
    auto serial = make_serializer(checksum_data.begin());
    serial.write_hash(outpoint.hash);
    serial.write_4_bytes(outpoint.index);
    BITCOIN_ASSERT(serial.iterator() == checksum_data.end());
    hash_digest hash = generate_sha256_hash(checksum_data);
    data_chunk raw_checksum(hash.begin(), hash.begin() + 8);
    return cast_chunk<uint64_t>(raw_checksum);
}
uint32_t addr_key_checksum(const output_point& outpoint)
{
    data_chunk chksum_data(hash_digest_size + 4);
    auto serial = make_serializer(chksum_data.begin());
    serial.write_hash(outpoint.hash);
    serial.write_4_bytes(outpoint.index);
    BITCOIN_ASSERT(
        std::distance(chksum_data.begin(), serial.iterator()) ==
        hash_digest_size + 4);
    return generate_sha256_checksum(chksum_data);
}
Esempio n. 9
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;
}
Esempio n. 10
0
bool add_debit(leveldb::WriteBatch& batch,
    const transaction_input_type& input, const input_point& inpoint,
    uint32_t block_height)
{
    payment_address address;
    // Not a Bitcoin address so skip this output.
    if (!extract(address, input.script))
        return true;
    data_chunk addr_key = create_address_key(address, input.previous_output);
    // inpoint
    data_chunk row_info(36 + 4);
    auto serial = make_serializer(row_info.begin());
    // inpoint
    serial.write_hash(inpoint.hash);
    serial.write_4_bytes(inpoint.index);
    // block_height
    serial.write_4_bytes(block_height);
    BITCOIN_ASSERT(
        std::distance(row_info.begin(), serial.iterator()) == 36 + 4);
    batch.Put(slice(addr_key), slice(row_info));
    return true;
}
Esempio n. 11
0
data_chunk create_address_key(
    const payment_address& address, const output_point& outpoint)
{
    data_chunk result(1 + short_hash_size + 4);
    auto serial = make_serializer(result.begin());
    serial.write_byte(address.version());
    serial.write_short_hash(address.hash());
    serial.write_4_bytes(addr_key_checksum(outpoint));
    BITCOIN_ASSERT(
        std::distance(result.begin(), serial.iterator()) ==
        1 + short_hash_size + 4);
    return result;
}
void spend_database::store(const output_point& outpoint,
    const input_point& spend)
{
    const auto write = [&spend](uint8_t* data)
    {
        auto serial = make_serializer(data);
        serial.write_data(spend.hash);
        serial.write_4_bytes(spend.index);
    };

    const auto key = output_to_hash(outpoint);
    map_.store(key, write);
}
void block_database::store(const block_type& block)
{
    const size_t height = index_.size();
    // Write block data.
    const hash_digest key = hash_block_header(block.header);
    const size_t number_txs = block.transactions.size();
    const size_t value_size = 80 + 4 + 4 + number_txs * hash_size;
    auto write = [&](uint8_t* data)
    {
        satoshi_save(block.header, data);
        auto serial = make_serializer(data + 80);
        serial.write_4_bytes(height);
        serial.write_4_bytes(number_txs);
        for (const transaction_type& tx: block.transactions)
        {
            const hash_digest tx_hash = hash_transaction(tx);
            serial.write_hash(tx_hash);
        }
    };
    const position_type position = map_.store(key, value_size, write);
    // Write height -> position mapping.
    write_position(position);
}
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);
}
index_type linked_records::insert(index_type next)
{
    static_assert(sizeof(index_type) == sizeof(uint32_t),
        "index_type incorrect size");

    // Create new record.
    index_type record = allocator_.allocate();
    record_type data = allocator_.get(record);

    // Write next value at first 4 bytes of record.
    auto serial = make_serializer(data);
    serial.write_4_bytes(next);
    return record;
}
Esempio n. 16
0
bool leveldb_common::save_block(
    uint32_t height, const block_type& serial_block)
{
    leveldb_transaction_batch batch;
    // Write block header + tx hashes
    data_chunk raw_block_data(
        80 + 4 + serial_block.transactions.size() * hash_digest_size);
    // Downcast to base header type so serializer selects that.
    auto header_end = satoshi_save(
        serial_block.header, raw_block_data.begin());
    BITCOIN_ASSERT(std::distance(raw_block_data.begin(), header_end) == 80);
    auto serial_hashes = make_serializer(header_end);
    // Write the number of transactions...
    serial_hashes.write_4_bytes(serial_block.transactions.size());
    // ... And now the tx themselves.
    for (uint32_t tx_index = 0;
        tx_index < serial_block.transactions.size(); ++tx_index)
    {
        const transaction_type& block_tx =
            serial_block.transactions[tx_index];
        const hash_digest& tx_hash = hash_transaction(block_tx);
        if (!save_transaction(batch, height, tx_index, tx_hash, block_tx))
        {
            log_fatal(LOG_BLOCKCHAIN) << "Could not save transaction";
            return false;
        }
        serial_hashes.write_hash(tx_hash);
    }
    BITCOIN_ASSERT(serial_hashes.iterator() ==
        raw_block_data.begin() + 80 + 4 +
            serial_block.transactions.size() * hash_digest_size);
    data_chunk raw_height = uncast_type(height);
    hash_digest block_hash = hash_block_header(serial_block.header);
    // Write block header
    batch.block.Put(slice(raw_height), slice(raw_block_data));
    batch.block_hash.Put(slice_block_hash(block_hash), slice(raw_height));
    // Execute batches.
    db_.write(batch);
    // Sync stealth database.
    db_stealth_->sync(height);
    return true;
}
Esempio n. 17
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);
     }
 }
Esempio n. 18
0
void dec_prepare_output_file (FILE *fp)
{
     if(putHeader(input_file_header, fp)){
        ERROR("putHeader");
     }
   
    uint32_t k = 0, **vector = NULL, *size_vector;

    vector = calloc(input_file_header->numChannels, sizeof(uint32_t *));
    size_vector = calloc(input_file_header->numChannels, sizeof(uint32_t));

    for(curr_channel=0; curr_channel<input_file_header->numChannels; curr_channel++) {
        size_vector[curr_channel] = b_to_uint32(&output_buffer[curr_channel], &vector[curr_channel], input_file_header->bitsPerSample, 0);
    }

    for (k=0; k<size_vector[0]; k++){
        for(curr_channel=0; curr_channel<input_file_header->numChannels; curr_channel++) {
            switch (input_file_header->bitsPerSample/8){
            case 1:
                if ( write_1_byte32(fp, &vector[curr_channel][k], input_file_header->endianness)){
                    printf("ERROR: io chunkSize\n");
                }break;
            case 2:
                if (write_2_bytes32(fp, &vector[curr_channel][k], input_file_header->endianness)) {
                    printf("ERROR: io chunkSize\n");
                }break;   
            case 3:
                if (write_3_bytes(fp, &vector[curr_channel][k], input_file_header->endianness)) {
                    printf("ERROR: io chunkSize\n");
                }break;   
            case 4:
                if (write_4_bytes(fp, &vector[curr_channel][k], input_file_header->endianness)) {
                    printf("ERROR: io chunkSize\n");
                }   
            }   
        }
    }

    for(curr_channel=0; curr_channel<input_file_header->numChannels; curr_channel++) {
        
        /*bprint(&output_buffer[curr_channel]);*/
        if(output_vector[curr_channel])
                free(output_vector[curr_channel]);
        if(data_vector[curr_channel])
                free(data_vector[curr_channel]);
        bdestroy(&output_buffer[curr_channel]);
        bdestroy(&data_buffer[curr_channel]);
        if(frequencies && frequencies[curr_channel])
            free(frequencies[curr_channel]);
        if(vector[curr_channel])
            free(vector[curr_channel]);
    }
    free(size_vector);
    free(vector);
    if(nbits_run)
        free(nbits_run);
    if(nbits_code)
        free(nbits_code);
    if(firsts)
        free(firsts);
    if(max_bits)
        free(max_bits);
    if(frequencies)
        free(frequencies);
    free(data_buffer);
    free(data_vector);
    free(output_buffer);
    free(output_vector);
    free(input_file_header);
}
Esempio n. 19
0
bool leveldb_common::save_transaction(leveldb_transaction_batch& batch,
    uint32_t block_height, uint32_t tx_index,
    const hash_digest& tx_hash, const transaction_type& block_tx)
{
    if (is_special_duplicate(block_height, tx_index))
        return true;
    data_chunk tx_data(8 + satoshi_raw_size(block_tx));
    // Serialize tx.
    auto serial = make_serializer(tx_data.begin());
    serial.write_4_bytes(block_height);
    serial.write_4_bytes(tx_index);
    // Actual tx data.
    auto end_iter = satoshi_save(block_tx, serial.iterator());
    BITCOIN_ASSERT(
        tx_data.begin() + 8 + satoshi_raw_size(block_tx) == end_iter);
    // Save tx to leveldb
    batch.tx.Put(slice(tx_hash), slice(tx_data));
    // Add inputs to spends database.
    // Coinbase inputs do not spend anything.
    if (!is_coinbase(block_tx))
        for (uint32_t input_index = 0; input_index < block_tx.inputs.size();
            ++input_index)
        {
            const transaction_input_type& input =
                block_tx.inputs[input_index];
            const input_point inpoint{tx_hash, input_index};
            if (!mark_spent_outputs(batch.spend,
                    input.previous_output, inpoint))
                return false;
            if (!add_debit(batch.debit,
                    input, {tx_hash, input_index}, block_height))
                return false;
        }
    // A stack of size 1. Keep the stealth_data from
    // one iteration to the next.
    data_chunk stealth_data_store;
    auto unload_stealth_store = [&]()
    {
        return std::move(stealth_data_store);
    };
    // Save address -> output mappings.
    for (uint32_t output_index = 0; output_index < block_tx.outputs.size();
        ++output_index)
    {
        const transaction_output_type& output =
            block_tx.outputs[output_index];
        // If a stealth output then skip processing.
        if (process_stealth_output_info(output, stealth_data_store))
            continue;
        data_chunk stealth_data = unload_stealth_store();
        // Try to extract an address.
        payment_address address;
        if (!extract(address, output.script))
            continue;
        // Process this output.
        if (!stealth_data.empty())
            add_stealth_info(stealth_data, address, tx_hash, *db_stealth_);
        if (!add_credit(batch.credit, address, output.value,
                {tx_hash, output_index}, block_height))
            return false;
    }
    return true;
}