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 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); }
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()); }
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); }
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 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))); }
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; }
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); }
bool operator==(const payment_address& lhs, const payment_address& rhs) { return lhs.hash() == rhs.hash() && lhs.version() == rhs.version(); }