Ejemplo n.º 1
0
bool RippleCalc::addPathState(STPath const& path, TER& resultCode)
{
    auto pathState = std::make_shared<PathState> (
        saDstAmountReq_, saMaxAmountReq_);

    if (!pathState)
    {
        resultCode = temUNKNOWN;
        return false;
    }

    pathState->expandPath (
        mActiveLedger,
        path,
        uDstAccountID_,
        uSrcAccountID_);

    if (pathState->status() == tesSUCCESS)
        pathState->checkNoRipple (uDstAccountID_, uSrcAccountID_);

    if (pathState->status() == tesSUCCESS)
        pathState->checkFreeze ();

    pathState->setIndex (pathStateList_.size ());

    WriteLog (lsDEBUG, RippleCalc)
        << "rippleCalc: Build direct:"
        << " status: " << transToken (pathState->status());

    // Return if malformed.
    if (isTemMalformed (pathState->status()))
    {
        resultCode = pathState->status();
        return false;
    }

    if (pathState->status () == tesSUCCESS)
    {
        resultCode = pathState->status();
        pathStateList_.push_back (pathState);
    }
    else if (pathState->status () != terNO_LINE)
    {
        resultCode = pathState->status();
    }

    return true;
}
Ejemplo n.º 2
0
// Check a fully-expanded path to make sure it doesn't violate no-Ripple settings
void PathState::checkNoRipple (uint160 const& uDstAccountID, uint160 const& uSrcAccountID)
{

    // There must be at least one node for there to be two consecutive ripple lines
    if (vpnNodes.size() == 0)
       return;

    if (vpnNodes.size() == 1)
    {
        // There's just one link in the path
        // We only need to check source-node-dest
        if (is_bit_set (vpnNodes[0].uFlags, STPathElement::typeAccount) &&
            (vpnNodes[0].uAccountID != uSrcAccountID) &&
            (vpnNodes[0].uAccountID != uDstAccountID))
        {
            if (saInReq.getCurrency() != saOutReq.getCurrency())
                terStatus = terNO_LINE;
            else
                checkNoRipple (uSrcAccountID, vpnNodes[0].uAccountID, uDstAccountID,
                    vpnNodes[0].uCurrencyID);
        }
        return;
    }

    // Check source <-> first <-> second
    if (is_bit_set (vpnNodes[0].uFlags, STPathElement::typeAccount) &&
        is_bit_set (vpnNodes[1].uFlags, STPathElement::typeAccount) &&
        (vpnNodes[0].uAccountID != uSrcAccountID))
    {
        if ((vpnNodes[0].uCurrencyID != vpnNodes[1].uCurrencyID))
        {
            terStatus = terNO_LINE;
            return;
        }
        else
        {
            checkNoRipple (uSrcAccountID, vpnNodes[0].uAccountID, vpnNodes[1].uAccountID,
                vpnNodes[0].uCurrencyID);
            if (tesSUCCESS != terStatus)
                return;
        }
    }

    // Check second_from_last <-> last <-> destination
    size_t s = vpnNodes.size() - 2;
    if (is_bit_set (vpnNodes[s].uFlags, STPathElement::typeAccount) &&
        is_bit_set (vpnNodes[s+1].uFlags, STPathElement::typeAccount) &&
        (uDstAccountID != vpnNodes[s+1].uAccountID))
    {
        if ((vpnNodes[s].uCurrencyID != vpnNodes[s+1].uCurrencyID))
        {
            terStatus = terNO_LINE;
            return;
        }
        else
        {
            checkNoRipple (vpnNodes[s].uAccountID, vpnNodes[s+1].uAccountID, uDstAccountID,
                vpnNodes[s].uCurrencyID);
            if (tesSUCCESS != terStatus)
                return;
        }
    }


    // Loop through all nodes that have a prior node and successor nodes
    // These are the nodes whose no ripple constraints could be violated
    for (int i = 1; i < (vpnNodes.size() - 1); ++i)
    {

        if (is_bit_set (vpnNodes[i-1].uFlags, STPathElement::typeAccount) &&
            is_bit_set (vpnNodes[i].uFlags, STPathElement::typeAccount) &&
            is_bit_set (vpnNodes[i+1].uFlags, STPathElement::typeAccount))
        { // two consecutive account-to-account links

            uint160 const& currencyID = vpnNodes[i].uCurrencyID;
            if ((vpnNodes[i-1].uCurrencyID != currencyID) ||
                (vpnNodes[i+1].uCurrencyID != currencyID))
            {
                terStatus = temBAD_PATH;
                return;
            }
            checkNoRipple (
                vpnNodes[i-1].uAccountID, vpnNodes[i].uAccountID, vpnNodes[i+1].uAccountID,
                    currencyID);
            if (terStatus != tesSUCCESS)
                return;
        }

    }
}
Ejemplo n.º 3
0
// Check a fully-expanded path to make sure it doesn't violate no-Ripple
// settings.
TER PathState::checkNoRipple (
    AccountID const& uDstAccountID,
    AccountID const& uSrcAccountID)
{
    // There must be at least one node for there to be two consecutive ripple
    // lines.
    if (nodes_.size() == 0)
       return terStatus;

    if (nodes_.size() == 1)
    {
        // There's just one link in the path
        // We only need to check source-node-dest
        if (nodes_[0].isAccount() &&
            (nodes_[0].account_ != uSrcAccountID) &&
            (nodes_[0].account_ != uDstAccountID))
        {
            if (saInReq.getCurrency() != saOutReq.getCurrency())
            {
                terStatus = terNO_LINE;
            }
            else
            {
                terStatus = checkNoRipple (
                    uSrcAccountID, nodes_[0].account_, uDstAccountID,
                    nodes_[0].issue_.currency);
            }
        }
        return terStatus;
    }

    // Check source <-> first <-> second
    if (nodes_[0].isAccount() &&
        nodes_[1].isAccount() &&
        (nodes_[0].account_ != uSrcAccountID))
    {
        if ((nodes_[0].issue_.currency != nodes_[1].issue_.currency))
        {
            terStatus = terNO_LINE;
            return terStatus;
        }
        else
        {
            terStatus = checkNoRipple (
                uSrcAccountID, nodes_[0].account_, nodes_[1].account_,
                nodes_[0].issue_.currency);
            if (terStatus != tesSUCCESS)
                return terStatus;
        }
    }

    // Check second_from_last <-> last <-> destination
    size_t s = nodes_.size() - 2;
    if (nodes_[s].isAccount() &&
        nodes_[s + 1].isAccount() &&
        (uDstAccountID != nodes_[s+1].account_))
    {
        if ((nodes_[s].issue_.currency != nodes_[s+1].issue_.currency))
        {
            terStatus = terNO_LINE;
            return terStatus;
        }
        else
        {
            terStatus = checkNoRipple (
                nodes_[s].account_, nodes_[s+1].account_,
                uDstAccountID, nodes_[s].issue_.currency);
            if (tesSUCCESS != terStatus)
                return terStatus;
        }
    }

    // Loop through all nodes that have a prior node and successor nodes
    // These are the nodes whose no ripple constraints could be violated
    for (int i = 1; i < nodes_.size() - 1; ++i)
    {
        if (nodes_[i - 1].isAccount() &&
            nodes_[i].isAccount() &&
            nodes_[i + 1].isAccount())
        { // Two consecutive account-to-account links

            auto const& currencyID = nodes_[i].issue_.currency;
            if ((nodes_[i-1].issue_.currency != currencyID) ||
                (nodes_[i+1].issue_.currency != currencyID))
            {
                terStatus = temBAD_PATH;
                return terStatus;
            }
            terStatus = checkNoRipple (
                nodes_[i-1].account_, nodes_[i].account_, nodes_[i+1].account_,
                currencyID);
            if (terStatus != tesSUCCESS)
                return terStatus;
        }
    }

    return tesSUCCESS;
}