Example #1
0
void bdb_blockchain::do_fetch_outputs(const payment_address& address,
    fetch_handler_outputs handle_fetch)
{
    // Associated outputs
    message::output_point_list assoc_outs;
    txn_guard_ptr txn = std::make_shared<txn_guard>(env_);
    Dbc* cursor;
    db_address_->cursor(txn->get(), &cursor, 0);
    BITCOIN_ASSERT(cursor != nullptr);
    readable_data_type key;
    // version byte + hash for key
    serializer serial;
    serial.write_byte(address.version());
    serial.write_short_hash(address.hash());
    key.set(serial.data());
    writable_data_type value;
    int ret = cursor->get(key.get(), value.get(), DB_SET);
    while (ret != DB_NOTFOUND)
    {
        message::output_point outpoint;
        // We need a copy not a temporary
        data_chunk raw_outpoint(value.data());
        // Then read the value off
        deserializer deserial(raw_outpoint);
        outpoint.hash = deserial.read_hash();
        outpoint.index = deserial.read_4_bytes();
        assoc_outs.push_back(outpoint);
        ret = cursor->get(key.get(), value.get(), DB_NEXT_DUP);
    }
    cursor->close();
    txn->commit();
    handle_fetch(std::error_code(), assoc_outs);
}
Example #2
0
void subscribe_manager::post_updates(const payment_address& address,
    size_t height, const bc::hash_digest& block_hash,
    const bc::transaction_type& tx)
{
    auto range = subs_.equal_range(address);
    // Avoid expensive serialization if not needed.
    if (range.first == range.second)
        return;
    // [ addr,version ] (1 byte)
    // [ addr.hash ] (20 bytes)
    // [ height ] (4 bytes)
    // [ block_hash ] (32 bytes)
    // [ tx ]
    constexpr size_t info_size = 1 + short_hash_size + 4 + hash_size;
    data_chunk data(info_size + satoshi_raw_size(tx));
    auto serial = make_serializer(data.begin());
    serial.write_byte(address.version());
    serial.write_short_hash(address.hash());
    serial.write_4_bytes(height);
    serial.write_hash(block_hash);
    BITCOIN_ASSERT(serial.iterator() == data.begin() + info_size);
    // Now write the tx part.
    auto rawtx_end_it = satoshi_save(tx, serial.iterator());
    BITCOIN_ASSERT(rawtx_end_it == data.end());
    // Send the result to everyone interested.
    for (auto it = range.first; it != range.second; ++it)
    {
        const subscription& sub_detail = it->second;
        outgoing_message update(
            sub_detail.client_origin, "address.update", data);
        sub_detail.queue_send(update);
    }
}
 void set_raw_address(const payment_address& address)
 {
     BITCOIN_ASSERT(raw_address_.size() == 1 + short_hash_size);
     auto serial = make_serializer(raw_address_.begin());
     serial.write_byte(address.version());
     serial.write_short_hash(address.hash());
     BITCOIN_ASSERT(
         std::distance(raw_address_.begin(), serial.iterator()) ==
         1 + short_hash_size);
 }
Example #4
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());
}
Example #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;
}
Example #6
0
void address_subscriber::subscribe(const payment_address& address,
    update_handler handle_update, subscribe_handler handle_subscribe)
{
    data_chunk data(1 + short_hash_size);
    auto serial = make_serializer(data.begin());
    serial.write_byte(address.version());
    serial.write_short_hash(address.hash());
    BITCOIN_ASSERT(serial.iterator() == data.end());
    backend_.request("address.subscribe", data,
        strand_.wrap(&address_subscriber::receive_subscribe_result,
            this, _1, _2, address, handle_update, handle_subscribe));
}
BC_API void obelisk_codec::address_fetch_history(error_handler&& on_error,
    fetch_history_handler&& on_reply,
    const payment_address& address, size_t from_height)
{
    auto data = build_data({
        to_byte(address.version()),
        reverse(address.hash()),
        to_little_endian<uint32_t>(from_height)
    });

    send_request("address.fetch_history", data, std::move(on_error),
        std::bind(decode_fetch_history, _1, std::move(on_reply)));
}
Example #8
0
bool build_output_script(
    script_type& out_script, const payment_address& payaddr)
{
    switch (payaddr.version())
    {
        case payment_address::pubkey_version:
            out_script = build_pubkey_hash_script(payaddr.hash());
            return true;

        case payment_address::script_version:
            out_script = build_script_hash_script(payaddr.hash());
            return true;
    }
    return false;
}
static void display_history(const std::error_code& code,
    const history_list& history, const payment_address& address,
    std::ostream& output)
{
    const auto encoded_address = address.encoded();

    if (code)
    {
        output << format(BN_FETCH_HISTORY_FAIL) % encoded_address %
            code.message();
        return;
    }

    output << format(BN_FETCH_HISTORY_SUCCESS) % encoded_address;

    for (const auto& row: history)
    {
        const auto hash = bc::encode_hash(row.point.hash);
        if (row.id == point_ident::output)
            output << format(BN_FETCH_HISTORY_OUTPUT) % hash %
                row.point.index % row.height % row.value;
        else
            output << format(BN_FETCH_HISTORY_INPUT) % hash %
                row.point.index % row.height % row.value;
    }
}
Example #10
0
void add_stealth_info(const data_chunk& stealth_data,
    const payment_address& address, const hash_digest& tx_hash,
    stealth_database& db)
{
    const stealth_bitfield bitfield = calculate_bitfield(stealth_data);
    const data_chunk ephemkey = read_ephemkey(stealth_data);
    auto write_func = [&](uint8_t *it)
    {
        auto serial = make_serializer(it);
        serial.write_uint_auto(bitfield);
        serial.write_data(ephemkey);
        serial.write_byte(address.version());
        serial.write_short_hash(address.hash());
        serial.write_hash(tx_hash);
        BITCOIN_ASSERT(serial.iterator() == it + bitfield_size + 33 + 21 + 32);
    };
    db.store(write_func);
}
Example #11
0
bool payaddr_from_stdin(payment_address& payaddr)
{
    if (!payaddr.set_encoded(read_stdin()))
    {
        std::cerr << "balance: Invalid address." << std::endl;
        return false;
    }
    return true;
}
Example #12
0
void bdb_blockchain::fetch_outputs(const payment_address& address,
    fetch_handler_outputs handle_fetch)
{
    if (address.type() != payment_type::pubkey_hash)
        handle_fetch(error::unsupported_payment_type,
            message::output_point_list());
    else
        queue(
            std::bind(&bdb_blockchain::do_fetch_outputs,
                this, address, handle_fetch));
}
Example #13
0
File: history.cpp Project: veox/sx
void json_history_fetched(const payment_address& payaddr,
                          const std::error_code& ec, const blockchain::history_list& history)
{
    if (ec)
    {
        std::cerr << "history: Failed to fetch history: "
                  << ec.message() << std::endl;
        return;
    }
    bool is_first = true;
    for (const auto& row: history)
    {
        // Put commas between each array item in json output.
        if (is_first)
            is_first = false;
        else
            std::cout << "," << std::endl;
        // Actual row data.
        std::cout << "{" << std::endl;
        std::cout << "  \"address\": \"" << payaddr.encoded()
                  << "\"," << std::endl;
        std::cout << "  \"output\": \"" << row.output
                  << "\"," << std::endl;
        std::cout << "  \"output_height\": ";
        if (!row.output_height)
            std::cout << "\"Pending\"";
        else
            std::cout << row.output_height;
        std::cout << "," << std::endl;
        std::cout << "  \"value\":  \"" << row.value << "\"," << std::endl;
        if (row.spend.hash == null_hash)
        {
            std::cout << "  \"spend\": \"Unspent\"," << std::endl;
            std::cout << "  \"spend_height\": \"Unspent\"" << std::endl;
        }
        else
        {
            std::cout << "  \"spend\": \"" << row.spend << "\"," << std::endl;
            std::cout << "  \"spend_height\": ";
            if (!row.spend_height)
                std::cout << "\"Pending\"";
            else
                std::cout << "\"" << row.spend_height << "\"";
        }
        std::cout << "}";
    }
    std::lock_guard<std::mutex> lock(mutex);
    BITCOIN_ASSERT(remaining_count != std::numeric_limits<int>::max());
    --remaining_count;
    condition.notify_one();
    if (remaining_count > 0)
        std::cout << ",";
    std::cout << std::endl;
}
void blockchain_impl::fetch_history(const payment_address& address,
    fetch_handler_history handle_fetch, const uint64_t limit, 
    const uint64_t from_height)
{
    const auto do_fetch = [=](size_t slock)
    {
        const auto history = interface_.history.get(
            address.hash(), limit, from_height);
        return finish_fetch(slock, handle_fetch, std::error_code(), history);
    };
    fetch(do_fetch);
}
Example #15
0
void json_history_fetched(const payment_address& payaddr,
    const std::error_code& ec, const blockchain::history_list& history)
{
    if (ec)
    {
        std::cerr << "balance: Failed to fetch history: "
            << ec.message() << std::endl;
        return;
    }
    bool is_first = true;
    uint64_t total_recv = 0, balance = 0, pending_balance = 0;
    for (const auto& row: history)
    {
        uint64_t value = row.value;
        BITCOIN_ASSERT(value >= 0);
        total_recv += value;
        // Unconfirmed balance.
        if (row.spend.hash == null_hash)
        {
            pending_balance += value;
        }
        // Confirmed balance.
        if (row.output_height &&
            (row.spend.hash == null_hash || !row.spend_height))
        {
            balance += value;
        }
        BITCOIN_ASSERT(total_recv >= balance);
        BITCOIN_ASSERT(total_recv >= pending_balance);
    }

    // Put commas between each array item in json output.
    if (is_first)
        is_first = false;
    else
        std::cout << "," << std::endl;
    // Actual row data.
    std::cout << "{" << std::endl;
    std::cout << "  \"address\": \"" << payaddr.encoded()
        << "\"," << std::endl;
    std::cout << "  \"paid\":  \"" << balance << "\"," << std::endl;
    std::cout << "  \"pending\":  \"" << pending_balance << "\"," << std::endl;
    std::cout << "  \"received\":  \"" << total_recv << "\"" << std::endl;
    std::cout << "}";
    std::lock_guard<std::mutex> lock(mutex);
    BITCOIN_ASSERT(remaining_count != std::numeric_limits<int>::max());
    --remaining_count;
    condition.notify_one();
    if (remaining_count > 0)
        std::cout << ",";
    std::cout << std::endl;
}
		bool extract(payment_address& address, const script_type& script)
		{
			// Cast a data_chunk to a short_hash and set the address
			auto set_hash_data =
				[&address](uint8_t version, const data_chunk& raw_hash)
			{
				short_hash hash_data;
				BITCOIN_ASSERT(raw_hash.size() == hash_data.size());
				std::copy(raw_hash.begin(), raw_hash.end(), hash_data.begin());
				address.set(version, hash_data);
			};
			const operation_stack& ops = script.operations();
			payment_type pay_type = script.type();
			switch (pay_type)
			{
			case payment_type::pubkey:
				BITCOIN_ASSERT(ops.size() == 2);
				set_public_key(address, ops[0].data);
				return true;

			case payment_type::pubkey_hash:
				BITCOIN_ASSERT(ops.size() == 5);
				set_hash_data(payment_address::pubkey_version, ops[2].data);
				return true;

			case payment_type::script_hash:
				BITCOIN_ASSERT(ops.size() == 3);
				set_hash_data(payment_address::script_version, ops[1].data);
				return true;

			case payment_type::multisig:
				// Unimplemented...
				return false;

			case payment_type::pubkey_hash_sig:
				BITCOIN_ASSERT(ops.size() == 2);
				set_public_key(address, ops[1].data);
				return true;

			case payment_type::script_code_sig:
				// Should have at least 1 sig and the script code.
				BITCOIN_ASSERT(ops.size() > 1);
				set_script_hash(address,
					bitcoin_short_hash(ops.back().data));
				return true;

			default:
				return false;
			}
			// Should never happen!
			return false;
		}
Example #17
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;
}
Example #18
0
bool unwrap_fetch_history_args(
    payment_address& payaddr, uint32_t& from_height,
    const incoming_message& request)
{
    const data_chunk& data = request.data();
    if (data.size() != 1 + short_hash_size + 4)
    {
        log_error(LOG_WORKER)
            << "Incorrect data size for .fetch_history";
        return false;
    }
    auto deserial = make_deserializer(data.begin(), data.end());
    uint8_t version_byte = deserial.read_byte();
    short_hash hash = deserial.read_short_hash();
    from_height = deserial.read_4_bytes();
    BITCOIN_ASSERT(deserial.iterator() == data.end());
    payaddr.set(version_byte, hash);
    return true;
}
Example #19
0
File: history.cpp Project: veox/sx
void history_fetched(const payment_address& payaddr,
                     const std::error_code& ec, const blockchain::history_list& history)
{
    if (ec)
    {
        std::cerr << "history: Failed to fetch history: "
                  << ec.message() << std::endl;
        return;
    }
    for (const auto& row: history)
    {
        std::cout << "Address: " << payaddr.encoded() << std::endl;
        std::cout << "  output: " << row.output << std::endl;
        std::cout << "  output_height: ";
        if (!row.output_height)
            std::cout << "Pending";
        else
            std::cout << row.output_height;
        std::cout << std::endl;
        std::cout << "  value:  " << row.value << std::endl;
        if (row.spend.hash == null_hash)
        {
            std::cout << "  spend: Unspent" << std::endl;
            std::cout << "  spend_height: Unspent" << std::endl;
        }
        else
        {
            std::cout << "  spend: " << row.spend << std::endl;
            std::cout << "  spend_height: ";
            if (!row.spend_height)
                std::cout << "Pending";
            else
                std::cout << row.spend_height;
            std::cout << std::endl;
        }
        std::cout << std::endl;
    }
    std::lock_guard<std::mutex> lock(mutex);
    BITCOIN_ASSERT(remaining_count != std::numeric_limits<int>::max());
    --remaining_count;
    condition.notify_one();
}
Example #20
0
void history_fetched(const payment_address& payaddr,
    const std::error_code& ec, const blockchain::history_list& history)
{
    if (ec)
    {
        std::cerr << "history: Failed to fetch history: "
            << ec.message() << std::endl;
        return;
    }
    for (const auto& row: history)
    {
        std::cout << "Address: " << payaddr.encoded() << std::endl;
        std::cout << "  output: " << row.output << std::endl;
        std::cout << "  output_height: ";
        if (!row.output_height)
            std::cout << "Pending";
        else
            std::cout << row.output_height;
        std::cout << std::endl;
        std::cout << "  value:  " << row.value << std::endl;
        if (row.spend.hash == null_hash)
        {
            std::cout << "  spend: Unspent" << std::endl;
            std::cout << "  spend_height: Unspent" << std::endl;
        }
        else
        {
            std::cout << "  spend: " << row.spend << std::endl;
            std::cout << "  spend_height: ";
            if (!row.spend_height)
                std::cout << "Pending";
            else
                std::cout << row.spend_height;
            std::cout << std::endl;
        }
        std::cout << std::endl;
    }
    --remaining_count;
}
Example #21
0
void history_fetched(const payment_address& payaddr,
    const std::error_code& ec, const blockchain::history_list& history)
{
    if (ec)
    {
        std::cerr << "balance: Failed to fetch history: "
            << ec.message() << std::endl;
        return;
    }
    uint64_t total_recv = 0, balance = 0, pending_balance = 0;
    for (const auto& row: history)
    {
        uint64_t value = row.value;
        BITCOIN_ASSERT(value >= 0);
        total_recv += value;
        // Unconfirmed balance.
        if (row.spend.hash == null_hash)
        {
            pending_balance += value;
        }
        // Confirmed balance.
        if (row.output_height &&
            (row.spend.hash == null_hash || !row.spend_height))
        {
            balance += value;
        }
        BITCOIN_ASSERT(total_recv >= balance);
        BITCOIN_ASSERT(total_recv >= pending_balance);
    }
    std::cout << "Address: " << payaddr.encoded() << std::endl;
    std::cout << "  Paid balance:    " << balance << std::endl;
    std::cout << "  Pending balance: " << pending_balance << std::endl;
    std::cout << "  Total received:  " << total_recv << std::endl;
    std::cout << std::endl;
    std::lock_guard<std::mutex> lock(mutex);
    BITCOIN_ASSERT(remaining_count != std::numeric_limits<int>::max());
    --remaining_count;
    condition.notify_one();
}
Example #22
0
static hash_digest address_hash(const payment_address& address)
{
    return bitcoin_hash(to_chunk(address.encoded()));
}
Example #23
0
bool set_public_key(payment_address& address, const data_chunk& public_key)
{
    return address.set(payment_type::pubkey_hash,
        generate_ripemd_hash(public_key));
}
Example #24
0
bool set_script_hash(payment_address& address,
    const short_hash& script_hash)
{
    return address.set(payment_type::script_hash, script_hash);
}
Example #25
0
bool set_script(payment_address& address, const script& eval_script)
{
    return address.set(payment_type::script_hash,
        generate_ripemd_hash(save_script(eval_script)));
}
		void set_script(payment_address& address, const script_type& eval_script)
		{
			address.set(payment_address::script_version,
				bitcoin_short_hash(save_script(eval_script)));
		}
		void set_public_key(payment_address& address, const data_chunk& public_key)
		{
			address.set(payment_address::pubkey_version,
				bitcoin_short_hash(public_key));
		}
		void set_script_hash(payment_address& address,
			const short_hash& script_hash)
		{
			address.set(payment_address::script_version, script_hash);
		}
		void set_public_key_hash(payment_address& address,
			const short_hash& pubkey_hash)
		{
			address.set(payment_address::pubkey_version, pubkey_hash);
		}
		bool operator==(const payment_address& lhs, const payment_address& rhs)
		{
			return lhs.hash() == rhs.hash() && lhs.version() == rhs.version();
		}