Exemplo n.º 1
0
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();
    };
Exemplo n.º 2
0
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());

}