Exemplo n.º 1
0
void receive_history_result(const data_chunk& data,
    blockchain::fetch_handler_history handle_fetch)
{
    BITCOIN_ASSERT(data.size() >= 4);
    std::error_code ec;
    auto deserial = make_deserializer(data.begin(), data.end());
    if (!read_error_code(deserial, data.size(), ec))
        return;
    BITCOIN_ASSERT(deserial.iterator() == data.begin() + 4);
    size_t row_size = 36 + 4 + 8 + 36 + 4;
    if ((data.size() - 4) % row_size != 0)
    {
        log_error() << "Malformed response for *.fetch_history";
        return;
    }
    size_t number_rows = (data.size() - 4) / row_size;
    blockchain::history_list history(number_rows);
    for (size_t i = 0; i < history.size(); ++i)
    {
        blockchain::history_row& row = history[i];
        row.output.hash = deserial.read_hash();
        row.output.index = deserial.read_4_bytes();
        row.output_height = deserial.read_4_bytes();
        row.value = deserial.read_8_bytes();
        row.spend.hash = deserial.read_hash();
        row.spend.index = deserial.read_4_bytes();
        row.spend_height = deserial.read_4_bytes();
    }
    BITCOIN_ASSERT(deserial.iterator() == data.end());
    handle_fetch(ec, history);
}
BC_API void obelisk_codec::message(const data_chunk& data, bool more)
{
    switch (next_part_)
    {
        case command_part:
            wip_message_.command = std::string(data.begin(), data.end());
            break;

        case id_part:
            if (4 != data.size())
            {
                next_part_ = error_part;
                break;
            }
            wip_message_.id = from_little_endian<uint32_t>(data.begin(), data.end());
            break;

        case payload_part:
            wip_message_.payload = data;
            break;

        case error_part:
            break;
    }
    if (!more)
    {
        if (next_part_ == payload_part)
            receive(wip_message_);
        else
            on_unknown_(wip_message_.command);
        next_part_ = command_part;
    }
    else if (next_part_ < error_part)
        next_part_ = static_cast<message_part>(next_part_ + 1);
}
Exemplo n.º 3
0
void address_subscriber::decode_reply(
    const data_chunk& data, const worker_uuid& worker,
    subscribe_handler handle_subscribe)
{
    std::error_code ec;
    BITCOIN_ASSERT(data.size() == 4);
    auto deserial = make_deserializer(data.begin(), data.end());
    if (!read_error_code(deserial, data.size(), ec))
        return;
    BITCOIN_ASSERT(deserial.iterator() == data.end());
    handle_subscribe(ec, worker);
}
Exemplo n.º 4
0
void receive_transaction_result(const data_chunk& data,
    blockchain::fetch_handler_transaction handle_fetch)
{
    std::error_code ec;
    auto deserial = make_deserializer(data.begin(), data.end());
    if (!read_error_code(deserial, data.size(), ec))
        return;
    BITCOIN_ASSERT(deserial.iterator() == data.begin() + 4);
    transaction_type tx;
    satoshi_load(deserial.iterator(), data.end(), tx);
    handle_fetch(ec, tx);
}
Exemplo n.º 5
0
		std::string encode_base58(const data_chunk& unencoded)
		{
			size_t leading_zeros = count_leading_zeros(unencoded);

			// size = log(256) / log(58), rounded up.
			const size_t number_nonzero = unencoded.size() - leading_zeros;
			const size_t indexes_size = number_nonzero * 138 / 100 + 1;
			// Allocate enough space in big-endian base58 representation.
			data_chunk indexes(indexes_size);

			// Process the bytes.
			for (auto it = unencoded.begin() + leading_zeros;
				it != unencoded.end(); ++it)
			{
				pack_value(indexes, *it);
			}

			// Skip leading zeroes in base58 result.
			auto first_nonzero = search_first_nonzero(indexes);

			// Translate the result into a string.
			std::string encoded;
			const size_t estimated_size =
				leading_zeros + (indexes.end() - first_nonzero);
			encoded.reserve(estimated_size);
			encoded.assign(leading_zeros, '1');
			// Set actual main bytes.
			for (auto it = first_nonzero; it != indexes.end(); ++it)
			{
				const size_t index = *it;
				encoded += base58_chars[index];
			}
			return encoded;
		}
Exemplo n.º 6
0
bool validate_block::coinbase_height_match()
{
    // There are old blocks with version incorrectly set to 2. Ignore them.
    if (height_ < 237370)
        return true;
    // Checks whether the block height is in the coinbase
    // transaction input script.
    // Version 2 blocks and onwards.
    BITCOIN_ASSERT(current_block_.header.version >= 2);
    BITCOIN_ASSERT(current_block_.transactions.size() > 0);
    BITCOIN_ASSERT(current_block_.transactions[0].inputs.size() > 0);
    // First get the serialized coinbase input script as a series of bytes.
    const script_type& coinbase_script =
        current_block_.transactions[0].inputs[0].script;
    const data_chunk raw_coinbase = save_script(coinbase_script);
    // Try to recreate the expected bytes.
    big_number expect_number;
    expect_number.set_int64(height_);
    script_type expect_coinbase;
    expect_coinbase.push_operation({opcode::special, expect_number.data()});
    // Save the expected coinbase script.
    const data_chunk expect = save_script(expect_coinbase);
    // Perform comparison of the first bytes with raw_coinbase.
    BITCOIN_ASSERT(expect.size() <= raw_coinbase.size());
    return std::equal(expect.begin(), expect.end(), raw_coinbase.begin());
}
Exemplo n.º 7
0
script parse_script(const data_chunk& raw_script)
{
    script script_object;
    for (auto it = raw_script.begin(); it != raw_script.end(); ++it)
    {
        byte raw_byte = *it;
        operation op;
        op.code = static_cast<opcode>(raw_byte);
        // raw_byte is unsigned so it's always >= 0
        if (raw_byte <= 75)
            op.code = opcode::special;
        size_t read_n_bytes = number_of_bytes_from_opcode(op.code, raw_byte);

        for (size_t byte_count = 0; byte_count < read_n_bytes; ++byte_count)
        {
            ++it;
            if (it == raw_script.cend())
            {
                log_warning() << "Premature end of script.";
                return script();
            }
            op.data.push_back(*it);
        }

        script_object.push_operation(op);

    }
    return script_object;
}
Exemplo n.º 8
0
void wrap_fetch_transaction_args(data_chunk& data, const hash_digest& tx_hash)
{
    data.resize(hash_digest_size);
    auto serial = make_serializer(data.begin());
    serial.write_hash(tx_hash);
    BITCOIN_ASSERT(serial.iterator() == data.end());
}
Exemplo n.º 9
0
BCW_API bool hd_private_key::set_serialized(std::string encoded)
{
    if (!is_base58(encoded))
        return false;
    const data_chunk decoded = decode_base58(encoded);
    if (decoded.size() != serialized_length)
        return false;
    if (!verify_checksum(decoded))
        return false;

    auto ds = make_deserializer(decoded.begin(), decoded.end());
    auto prefix = ds.read_big_endian<uint32_t>();
    if (prefix != mainnet_private_prefix && prefix != testnet_private_prefix)
        return false;

    valid_ = true;
    lineage_.testnet = prefix == testnet_private_prefix;
    lineage_.depth = ds.read_byte();
    lineage_.parent_fingerprint = ds.read_little_endian<uint32_t>();
    lineage_.child_number = ds.read_big_endian<uint32_t>();
    c_ = ds.read_bytes<chain_code_size>();
    ds.read_byte();
    k_ = ds.read_bytes<ec_secret_size>();
    K_ = secret_to_public_key(k_);
    return true;
}
Exemplo n.º 10
0
bool deserialize_address(payment_address& addr, const data_chunk& data)
{
    auto deserial = make_deserializer(data.begin(), data.end());
    try
    {
        uint8_t version_byte = deserial.read_byte();
        short_hash hash = deserial.read_short_hash();
        addr.set(version_byte, hash);
    }
    catch (end_of_stream)
    {
        return false;
    }
    if (deserial.iterator() != data.end())
        return false;
    return true;
}
Exemplo n.º 11
0
data_chunk read_ephemkey(const data_chunk& stealth_data)
{
    // Read ephemkey
    BITCOIN_ASSERT(stealth_data.size() == 1 + 4 + 33);
    data_chunk ephemkey(stealth_data.begin() + 5, stealth_data.end());
    BITCOIN_ASSERT(ephemkey.size() == 33);
    return ephemkey;
}
Exemplo n.º 12
0
void BIO::Write(const data_chunk& data2wr) const
{
	unsigned int written = 0;
	do {
		data_chunk tmp;
		tmp.insert(tmp.end(), data2wr.begin() + written, data2wr.end());
		written += doWrite(tmp, written);
	} while(written < data2wr.size());
}
Exemplo n.º 13
0
bool VerifyChecksum(const data_chunk& data)
{
    if (data.size() < 4)
        return false;
    
    uint32_t checksum = from_little_endian<uint32_t>(data.end() - 4);
    
    return BitcoinChecksum((uint8_t*)&data[0], data.size()-4) == checksum;
};
Exemplo n.º 14
0
bool read_hash(hash_digest& hash, const data_chunk& raw_hash)
{
    if (raw_hash.size() != hash.size())
    {
        log_warning(LOG_SUBSCRIBER) << "Wrong size for hash. Dropping.";
        return false;
    }
    std::copy(raw_hash.begin(), raw_hash.end(), hash.begin());
    return true;
}
Exemplo n.º 15
0
record_type get_record(htdb_record_header& header, record_allocator& alloc,
    const data_chunk& key_data)
{
    typedef byte_array<N> hash_type;
    htdb_record<hash_type> ht(header, alloc, "test");
    hash_type key;
    BITCOIN_ASSERT(key.size() == key_data.size());
    std::copy(key_data.begin(), key_data.end(), key.begin());
    return ht.get(key);
}
Exemplo n.º 16
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());
}
Exemplo n.º 17
0
bool payment_address::set_encoded(const std::string& encoded_address)
{
    const data_chunk decoded_address = decode_base58(encoded_address);
    // version + 20 bytes short hash + 4 bytes checksum
    if (decoded_address.size() != 25)
        return false;
    const uint8_t version = decoded_address[0];
    if (!set_version(version))
        return false;
    const data_chunk checksum_bytes(
        decoded_address.end() - 4, decoded_address.end());
    // version + short hash
    const data_chunk main_body(
        decoded_address.begin(), decoded_address.end() - 4);
    // verify checksum bytes
    if (generate_sha256_checksum(main_body) !=
            cast_chunk<uint32_t>(checksum_bytes))
        return false;
    std::copy(main_body.begin() + 1, main_body.end(), hash_.begin());
    return true;
}
Exemplo n.º 18
0
void BIO::WriteWithRetry(const data_chunk& data2wr) const
{
	unsigned int written = 0;
	do {
		try {
			data_chunk tmp;
			tmp.insert(tmp.end(), data2wr.begin() + written, data2wr.end());
			written += doWrite(tmp, written);
		} catch (RecoverableException& ex) {

		}
	} while (written < data2wr.size());
}
Exemplo n.º 19
0
HashType generate_hmac(const data_chunk& key, const data_chunk& data,
    std::function<HashType (const data_chunk&)> hash_func)
{
    typedef typename HashType::value_type hash_char;
    std::array<hash_char, block_size> fixed_key;
    // Zero out
    std::fill(fixed_key.begin(), fixed_key.end(), 0);
    // Now copy key or hash into zeroed out buffer
    if (key.size() <= block_size)
    {
        std::copy(key.begin(), key.end(), fixed_key.begin());
    }
    else
    {
        HashType fixed_key_digest = hash_func(key);
        BITCOIN_ASSERT(fixed_key.size() >= fixed_key_digest.size());
        std::copy(fixed_key_digest.begin(), fixed_key_digest.end(),
            fixed_key.begin());
    }
    // hash(o_key_pad + hash(i_key_pad + data))
    // Work on inner section first
    data_chunk inner_data(fixed_key.size() + data.size());
    // xor each digit of key...
    std::transform(fixed_key.begin(), fixed_key.end(), inner_data.begin(),
        [](hash_char digit) { return digit ^ 0x36; });
    // ... and append the data.
    std::copy(data.begin(), data.end(),
        inner_data.begin() + fixed_key.size());
    HashType inner_hash = hash_func(inner_data);
    // Work on outer section
    data_chunk outer_data(fixed_key.size() + inner_hash.size());
    // xor each digit of key...
    std::transform(fixed_key.begin(), fixed_key.end(), outer_data.begin(),
        [](hash_char digit) { return digit ^ 0x5c; });
    // ... and combine with inner_hash to get outer_data.
    std::copy(inner_hash.begin(), inner_hash.end(),
        outer_data.begin() + fixed_key.size());
    return hash_func(outer_data);
}
Exemplo n.º 20
0
 void attempt_load(const data_chunk& stream) const
 {
     Message result;
     try
     {
         satoshi_load(stream.begin(), stream.end(), result);
         handle_load_(std::error_code(), result);
     }
     catch (end_of_stream)
     {
         handle_load_(error::bad_stream, Message());
     }
 }
Exemplo n.º 21
0
int mmr_lookup(const data_chunk& key_data, const size_t value_size,
    const std::string& map_filename, const std::string& rows_filename)
{
    typedef byte_array<KeySize> hash_type;

    hash_type key;
    BITCOIN_ASSERT(key.size() == key_data.size());
    std::copy(key_data.begin(), key_data.end(), key.begin());

    memory_map ht_file(map_filename);
    BITCOIN_ASSERT(ht_file.open());

    record_hash_table_header header(ht_file, buckets);
    auto result = header.start();
    BITCOIN_ASSERT(result);

    const auto record_size = hash_table_multimap_record_size<hash_type>();
    BITCOIN_ASSERT(record_size == KeySize + 4 + 4);
    const auto header_size = record_hash_table_header_size(header.size());
    const file_offset records_start = header_size;

    record_manager ht_manager(ht_file, records_start, record_size);
    result = ht_manager.start();
    BITCOIN_ASSERT(result);

    memory_map lrs_file(rows_filename);
    BITCOIN_ASSERT(lrs_file.open());

    const auto lrs_record_size = record_list_offset + value_size;
    record_manager lrs_manager(lrs_file, 0, lrs_record_size);
    result = lrs_manager.start();
    BITCOIN_ASSERT(result);

    record_list lrs(lrs_manager);
    record_hash_table<hash_type> ht(header, ht_manager);
    record_multimap<hash_type> multimap(ht, lrs);
    record_multimap_iterable container(lrs, multimap.lookup(key));

    for (const array_index index: container)
    {
        std::cout << "Index: " << index << std::endl;
        const auto memory = lrs_manager.get(index);
        const auto record = REMAP_ADDRESS(memory) + record_list_offset;
        const data_chunk data(record, record + value_size);
        std::cout << encode_base16(data) << std::endl;
        std::cout << std::endl;
    }

    return 0;
}
 void attempt_load(const data_chunk& stream) const
 {
     Message result;
     try
     {
         satoshi_load(stream.begin(), stream.end(), result);
         handle_load_(error::success, result);
     }
     catch (bc::end_of_stream)
     {
         // This doesn't invalidate the channel (unlike the invalid header).
         handle_load_(bc::error::bad_stream, Message());
     }
 }
Exemplo n.º 23
0
void AppendChecksum(data_chunk& data)
{
    uint32_t checksum = BitcoinChecksum(&data[0], data.size());
    
    // -- to_little_endian
    std::vector<uint8_t> tmp(4);
    
    //memcpy(&tmp[0], &checksum, 4);
    for (int i = 0; i < 4; ++i)
    {
        tmp[i] = checksum & 0xFF;
        checksum >>= 8;
    };
    
    data.insert(data.end(), tmp.begin(), tmp.end());
};
Exemplo n.º 24
0
T cast_chunk(data_chunk chunk, bool reverse=false)
{
    #ifdef BOOST_LITTLE_ENDIAN
        reverse = !reverse;
    #elif BOOST_BIG_ENDIAN
        // do nothing
    #else
        #error "Endian isn't defined!"
    #endif

    if (reverse)
        std::reverse(chunk.begin(), chunk.end());

    T val = 0;
    for (size_t i = 0; i < sizeof(T); ++i)
        val += static_cast<T>(chunk[i]) << (i*8);
    return val;
}
Exemplo n.º 25
0
void StringMessage::doDeserializeChunk(const data_chunk& data)
{
	this->append(data.begin(), data.end());
	size_t found = this->find(itsTerminator);

	if (std::string::npos != found) {
		// Terminator was found in data
		size_t remains_pos = found + itsTerminator.size();
		data_chunk remains(this->begin() + remains_pos, this->end());
		this->erase(this->begin() + remains_pos, this->end());
		DeserializingComplete(remains);
		DBG << "Completed string with " << this->size()
			<< "B (" << found << " + " << itsTerminator.size() << ")" << std::endl;
	} else {
		// Terminator was not found in data
		DBG << "Continuing, " << this->size() << "B so far" << std::endl;
	}
}
Exemplo n.º 26
0
void address_subscriber::receive_update(
    const data_chunk& data, const worker_uuid& worker)
{
    // Deserialize data -> address, height, block hash, tx
    constexpr size_t info_size = 1 + short_hash_size + 4 + hash_digest_size;
    auto deserial = make_deserializer(data.begin(), data.begin() + info_size);
    // [ addr,version ] (1 byte)
    uint8_t version_byte = deserial.read_byte();
    // [ addr.hash ] (20 bytes)
    short_hash addr_hash = deserial.read_short_hash();
    payment_address address(version_byte, addr_hash);
    // [ height ] (4 bytes)
    uint32_t height = deserial.read_4_bytes();
    // [ block_hash ] (32 bytes)
    const hash_digest blk_hash = deserial.read_hash();
    // [ tx ]
    BITCOIN_ASSERT(deserial.iterator() == data.begin() + info_size);
    transaction_type tx;
    satoshi_load(deserial.iterator(), data.end(), tx);
    post_updates(address, worker, height, blk_hash, tx);
}
Exemplo n.º 27
0
bool leveldb_common::fetch_spend(const output_point& spent_output,
    input_point& input_spend)
{
    data_chunk spent_key = create_spent_key(spent_output);
    std::string raw_spend;
    leveldb::Status status = db_.spend->Get(
        leveldb::ReadOptions(), slice(spent_key), &raw_spend);
    if (status.IsNotFound())
        return false;
    else if (!status.ok())
    {
        log_fatal(LOG_BLOCKCHAIN) << "fetch_spend: " << status.ToString();
        return false;
    }
    const data_chunk raw_spend_data(raw_spend.begin(), raw_spend.end());
    auto deserial = make_deserializer(
        raw_spend_data.begin(), raw_spend_data.end());
    input_spend.hash = deserial.read_hash();
    input_spend.index = deserial.read_4_bytes();
    return true;
}
Exemplo n.º 28
0
std::string encode_base58(const data_chunk& unencoded_data)
{                                                                                
    std::string encoded_data;
    // Expected size increase from base58 conversion is approximately 137%
    // use 138% to be safe
    encoded_data.reserve((unencoded_data.size() - 1) * 138 / 100 + 1);

    // Convert big endian data to little endian
    // Extra zero at the end make sure bignum will interpret
    // as a positive number
    data_chunk tmp_data(unencoded_data.size() + 1, 0);
    std::reverse_copy(unencoded_data.begin(), unencoded_data.end(),
        tmp_data.begin());

    big_number long_value;
    long_value.set_data(tmp_data);
    while (long_value > 0)
    {                                                                            
        auto result = divmod(long_value, 58);
        long_value = result.first;
        size_t remainder = result.second.uint32();
        encoded_data += base58_chars[remainder];
    }                                                                            
                                                                                 
    // Leading zeroes encoded as base58 zeros                                    
    for (const uint8_t unencoded_byte: unencoded_data)
    {
        if (unencoded_byte != 0)
            break;
        encoded_data += base58_chars[0];
    }

    // Convert little endian std::string to big endian
    reverse(encoded_data.begin(), encoded_data.end());
    return encoded_data;
}                                                                                
Exemplo n.º 29
0
 // Construct from a stream object
 explicit shared_const_buffer(const data_chunk& user_data)
   : data(new std::vector<char>(user_data.begin(), user_data.end())),
     buffer(boost::asio::buffer(*data))
 {
 }
Exemplo n.º 30
0
bool verify_checksum(const data_chunk& data)
{
    data_chunk body(data.begin(), data.end() - 4);
    auto checksum = from_little_endian<uint32_t>(data.end() - 4);
    return bitcoin_checksum(body) == checksum;
}