Esempio n. 1
0
    /** Returns the hash of the specified ledger.
        @param ledgerIndex The index of the desired ledger.
        @param referenceLedger [out] An optional known good subsequent ledger.
        @return The hash of the ledger. This will be all-bits-zero if not found.
    */
    LedgerHash getHash(
        LedgerIndex const& ledgerIndex,
        std::shared_ptr<ReadView const>& referenceLedger)
    {
        LedgerHash ledgerHash;

        if (!referenceLedger || (referenceLedger->info().seq < ledgerIndex))
        {
            referenceLedger = app_.getLedgerMaster().getValidatedLedger();
            if (!referenceLedger)
            {
                JLOG (j_.warn()) << "No validated ledger";
                return ledgerHash; // Nothing we can do. No validated ledger.
            }
        }

        if (referenceLedger->info().seq >= ledgerIndex)
        {
            // See if the hash for the ledger we need is in the reference ledger
            ledgerHash = getLedgerHash(referenceLedger, ledgerIndex);
            if (ledgerHash.isZero())
            {
                // No. Try to get another ledger that might have the hash we
                // need: compute the index and hash of a ledger that will have
                // the hash we need.
                LedgerIndex refIndex = getCandidateLedger (ledgerIndex);
                LedgerHash refHash = getLedgerHash (referenceLedger, refIndex);

                bool const nonzero (refHash.isNonZero ());
                assert (nonzero);
                if (nonzero)
                {
                    // We found the hash and sequence of a better reference
                    // ledger.
                    referenceLedger =
                        app_.getInboundLedgers().acquire(
                            refHash, refIndex, InboundLedger::fcGENERIC);
                    if (referenceLedger)
                        ledgerHash = getLedgerHash(
                            referenceLedger, ledgerIndex);
                }
            }
        }
        else
            JLOG (j_.warn()) << "Validated ledger is prior to target ledger";

        return ledgerHash;
    }
Esempio n. 2
0
    /** Returns the hash of the specified ledger.
        @param ledgerIndex The index of the desired ledger.
        @param referenceLedger [out] An optional known good subsequent ledger.
        @return The hash of the ledger. This will be all-bits-zero if not found.
    */
    LedgerHash getHash(
        LedgerIndex const& ledgerIndex,
        Ledger::pointer& referenceLedger)
    {
        LedgerHash ledgerHash;

        if (!referenceLedger || (referenceLedger->getLedgerSeq() < ledgerIndex))
        {
            referenceLedger = getApp().getLedgerMaster().getValidatedLedger();
            if (!referenceLedger)
            {
                m_journal.warning << "No validated ledger";
                return ledgerHash; // Nothing we can do. No validated ledger.
            }
        }

        if (referenceLedger->getLedgerSeq() >= ledgerIndex)
        {
            // See if the hash for the ledger we need is in the reference ledger
            ledgerHash = getLedgerHash(referenceLedger, ledgerIndex);
            if (ledgerHash.isZero())
            {
                // No, Try to get another ledger that might have the hash we need
                // Compute the index and hash of a ledger that will have the hash we need
                LedgerIndex refIndex = getCandidateLedger (ledgerIndex);
                LedgerHash refHash = getLedgerHash (referenceLedger, refIndex);

                bool const nonzero (refHash.isNonZero ());
                assert (nonzero);
                if (nonzero)
                {
                    // We found the hash and sequence of a better reference ledger
                    referenceLedger =
                        getApp().getInboundLedgers().acquire(
                            refHash, refIndex, InboundLedger::fcGENERIC);
                    if (referenceLedger)
                        ledgerHash = getLedgerHash(referenceLedger, ledgerIndex);
                }
            }
        }
        else
            m_journal.warning << "Validated ledger is prior to target ledger";

        return ledgerHash;
    }
Esempio n. 3
0
// {
//   ledger_hash : <ledger>
//   ledger_index : <ledger_index>
// }
Json::Value doLedgerRequest (RPC::Context& context)
{
    auto const hasHash = context.params.isMember (jss::ledger_hash);
    auto const hasIndex = context.params.isMember (jss::ledger_index);

    auto& ledgerMaster = getApp().getLedgerMaster();
    LedgerHash ledgerHash;

    if ((hasHash && hasIndex) || !(hasHash || hasIndex))
    {
        return RPC::make_param_error(
            "Exactly one of ledger_hash and ledger_index can be set.");
    }

    if (hasHash)
    {
        auto const& jsonHash = context.params[jss::ledger_hash];
        if (!jsonHash.isString() || !ledgerHash.SetHex (jsonHash.asString ()))
            return RPC::invalid_field_message (jss::ledger_hash);
    } else {
        auto const& jsonIndex = context.params[jss::ledger_index];
        if (!jsonIndex.isNumeric ())
            return RPC::invalid_field_message (jss::ledger_index);

        // We need a validated ledger to get the hash from the sequence
        if (ledgerMaster.getValidatedLedgerAge() > 120)
            return rpcError (rpcNO_CURRENT);

        auto ledgerIndex = jsonIndex.asInt();
        auto ledger = ledgerMaster.getValidatedLedger();

        if (ledgerIndex >= ledger->getLedgerSeq())
            return RPC::make_param_error("Ledger index too large");

        // Try to get the hash of the desired ledger from the validated ledger
        ledgerHash = ledger->getLedgerHash (ledgerIndex);

        if (ledgerHash == zero)
        {
            // Find a ledger more likely to have the hash of the desired ledger
            auto refIndex = (ledgerIndex + 255) & (~255);
            auto refHash = ledger->getLedgerHash (refIndex);
            assert (refHash.isNonZero ());

            ledger = ledgerMaster.getLedgerByHash (refHash);
            if (!ledger)
            {
                // We don't have the ledger we need to figure out which ledger
                // they want. Try to get it.

                if (auto il = getApp().getInboundLedgers().acquire (
                        refHash, refIndex, InboundLedger::fcGENERIC))
                    return getJson (LedgerFill (*il));

                if (auto il = getApp().getInboundLedgers().find (refHash))
                {
                    Json::Value jvResult = il->getJson (0);

                    jvResult[jss::error] = "ledgerNotFound";
                    return jvResult;
                }

                // Likely the app is shutting down
                return Json::Value();
            }

            ledgerHash = ledger->getLedgerHash (ledgerIndex);
            assert (ledgerHash.isNonZero ());
        }
    }

    auto ledger = ledgerMaster.getLedgerByHash (ledgerHash);
    if (ledger)
    {
        // We already have the ledger they want
        Json::Value jvResult;
        jvResult[jss::ledger_index] = ledger->getLedgerSeq();
        addJson (jvResult, {*ledger, 0});
        return jvResult;
    }
    else
    {
        // Try to get the desired ledger
        if (auto il = getApp ().getInboundLedgers ().acquire (
                ledgerHash, 0, InboundLedger::fcGENERIC))
            return getJson (LedgerFill (*il));

        if (auto il = getApp().getInboundLedgers().find (ledgerHash))
            return il->getJson (0);

        return RPC::make_error (
            rpcNOT_READY, "findCreate failed to return an inbound ledger");
    }
}