void StratumConnection::getAddressHistory( const bc::client::obelisk_codec::error_handler &onError, const bc::client::obelisk_codec::fetch_history_handler &onReply, const bc::payment_address &address, size_t fromHeight) { JsonArray params; params.append(json_string(address.encoded().c_str())); auto errorShim = [onError](Status status) { onError(std::make_error_code(std::errc::bad_message)); }; auto decoder = [onReply](JsonPtr payload) -> Status { JsonArray arrayJson(payload); bc::client::history_list history; size_t size = arrayJson.size(); history.reserve(size); for (size_t i = 0; i < size; i++) { struct HistoryJson: public JsonObject { ABC_JSON_CONSTRUCTORS(HistoryJson, JsonObject) ABC_JSON_STRING(txid, "tx_hash", nullptr) ABC_JSON_INTEGER(height, "height", 0) }; HistoryJson json(arrayJson[i]); bc::hash_digest hash; if (!json.txidOk() || !bc::decode_hash(hash, json.txid())) return ABC_ERROR(ABC_CC_Error, "Bad txid"); bc::client::history_row row; row.output.hash = hash; row.output_height = json.height(); row.spend.hash = bc::null_hash; history.push_back(row); } onReply(history); return Status(); };
void TxUpdater::query_address(const bc::payment_address &address, int server_index) { ABC_DebugLevel(2,"query_address ENTER %s", address.encoded().c_str()); std::string servers = ""; std::string maxed_servers = ""; int total_queries = 0; int num_servers = 0; int num_maxed_servers = 0; if (!connections_.size()) { ABC_DebugLevel(2,"query_address connections_ vector empty"); } for (auto &it: connections_) { Connection &bconn = *it; auto idx = bconn.server_index; // If there is a preferred server index to use. Only query that server if (ALL_SERVERS != server_index) { if (bconn.server_index != server_index) continue; } if (bconn.queued_queries_ > max_queries) { if (num_maxed_servers) maxed_servers += " "; maxed_servers += std::to_string(idx); num_maxed_servers++; ABC_DebugLevel(2, "TxUpdater::query_address() idx=%d (queued > max) for address=%s queued_queries=%d", idx, address.encoded().c_str(), bconn.queued_queries_); continue; } if (num_servers) servers += " "; servers += std::to_string(idx); auto on_error = [this, idx, address, &bconn](const std::error_code &error) { ABC_DebugLevel(1,"query_address ON_ERROR idx:%d addr:%s failed:%s", idx, address.encoded().c_str(), error.message().c_str()); addressCache_.checkEnd(address.encoded(), false); failed_ = true; failed_server_idx_ = idx; query_done(idx, bconn); }; auto on_done = [this, idx, address, &bconn](const bc::client::history_list &history) { ABC_DebugLevel(2,"TxUpdater::query_address ENTER ON_DONE idx:%d addr:%s", idx, address.encoded().c_str()); ABC_DebugLevel(2," Looping over address transactions... "); addressCache_.checkEnd(address.encoded(), true); for (auto &row: history) { ABC_DebugLevel(2," Watching output tx=%s", bc::encode_hash(row.output.hash).c_str()); watch_tx(row.output.hash, true, idx, row.output_height); if (row.spend.hash != bc::null_hash) { watch_tx(row.spend.hash, true, idx, 0); ABC_DebugLevel(2," Watching spend tx=%s", bc::encode_hash(row.spend.hash).c_str()); } } query_done(idx, bconn); ABC_DebugLevel(2,"TxUpdater::query_address EXIT ON_DONE idx:%d addr:%s", idx, address.encoded().c_str()); }; bconn.queued_queries_++; num_servers++; total_queries += bconn.queued_queries_; ABC_DebugLevel(2,"TxUpdater::query_address idx=%d queued_queries=%d %s", idx, bconn.queued_queries_, address.encoded().c_str()); if (ConnectionType::libbitcoin == bconn.type) bconn.bc_codec.address_fetch_history(on_error, on_done, address); else if (ConnectionType::stratum == bconn.type) bconn.stratumCodec.getAddressHistory(on_error, on_done, address); } if (num_servers) ABC_DebugLevel(2,"query_address svrs=[%s] maxed_svrs=[%s] avg_q=%.1f addr=%s", servers.c_str(), maxed_servers.c_str(), (float)total_queries/(float)num_servers, address.encoded().c_str()); ABC_DebugLevel(2,"query_address EXIT %s", address.encoded().c_str()); }