Exemplo n.º 1
0
std::unique_ptr<IMainChainStorage> createVectorMainChainStorage(const Currency& currency) {
  std::unique_ptr<IMainChainStorage> storage(new VectorMainChainStorage());

  RawBlock genesis;
  genesis.block = toBinaryArray(currency.genesisBlock());
  storage->pushBlock(genesis);

  return std::move(storage);
}
FusionTransactionBuilder::FusionTransactionBuilder(const Currency& currency, uint64_t amount) :
  m_currency(currency),
  m_amount(amount),
  m_firstInput(0),
  m_firstOutput(0),
  m_fee(0),
  m_extraSize(0),
  m_inputCount(currency.fusionTxMinInputCount()) {
}
Exemplo n.º 3
0
std::string to_string(Currency const& currency)
{
    static Currency const sIsoBits ("FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFF");

    // Characters we are willing to allow in the ASCII representation of a
    // three-letter currency code.
    static std::string const allowed_characters =
        "abcdefghijklmnopqrstuvwxyz"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "0123456789"
        "<>(){}[]|?!@#$%^&*";

    if (currency == zero)
        return systemCurrencyCode();

	if (currency == vbcCurrency())
		return systemCurrencyCodeVBC();

    if (currency == noCurrency())
        return "1";

    if ((currency & sIsoBits).isZero ())
    {
        // The offset of the 3 character ISO code in the currency descriptor
        int const isoOffset = 12;

        std::string const iso(
            currency.data () + isoOffset,
            currency.data () + isoOffset + 3);

        // Specifying the system currency code using ISO-style representation
        // is not allowed.
		if ((iso != systemCurrencyCode()) && (iso != systemCurrencyCodeVBC()) &&
            (iso.find_first_not_of (allowed_characters) == std::string::npos))
        {
            return iso;
        }
    }

    return strHex (currency.begin (), currency.size ());
}
bool
AllowTrustOpFrame::doCheckValid()
{
    if (mAllowTrust.currency.type() != CURRENCY_TYPE_ALPHANUM)
    {
        innerResult().code(ALLOW_TRUST_MALFORMED);
        return false;
    }
    Currency ci;
    ci.type(CURRENCY_TYPE_ALPHANUM);
    ci.alphaNum().currencyCode = mAllowTrust.currency.currencyCode();
    ci.alphaNum().issuer = getSourceID();

    if (!isCurrencyValid(ci))
    {
        innerResult().code(ALLOW_TRUST_MALFORMED);
        return false;
    }

    return true;
}
Exemplo n.º 5
0
void TransactionDialog::changeCurrency(QComboBox *control, int index)
{
    Account* acc = accounts->at(index);

    QList<Currency*>* currency = acc->getCurrencyList();

    control->clear();

    QList<Currency*>::iterator i = currency->begin();

    while(i != currency->end())
    {
        Currency *cur = (*i);
        if (cur->isDisplay())
        {
            control->addItem(cur->getShortName(), cur->getId());
        }

        i++;
    }
}
bool
AllowTrustOpFrame::doApply(LedgerDelta& delta, LedgerManager& ledgerManager)
{
    if (!(mSourceAccount->getAccount().flags & AUTH_REQUIRED_FLAG))
    { // this account doesn't require authorization to hold credit
        innerResult().code(ALLOW_TRUST_TRUST_NOT_REQUIRED);
        return false;
    }

    if (!(mSourceAccount->getAccount().flags & AUTH_REVOCABLE_FLAG) &&
        !mAllowTrust.authorize)
    {
        innerResult().code(ALLOW_TRUST_CANT_REVOKE);
        return false;
    }

    Currency ci;
    ci.type(CURRENCY_TYPE_ALPHANUM);
    ci.alphaNum().currencyCode = mAllowTrust.currency.currencyCode();
    ci.alphaNum().issuer = getSourceID();

    Database& db = ledgerManager.getDatabase();
    TrustFrame::pointer trustLine;
    trustLine = TrustFrame::loadTrustLine(mAllowTrust.trustor, ci, db);

    if (!trustLine)
    {
        innerResult().code(ALLOW_TRUST_NO_TRUST_LINE);
        return false;
    }

    innerResult().code(ALLOW_TRUST_SUCCESS);

    trustLine->setAuthorized(mAllowTrust.authorize);

    trustLine->storeChange(delta, db);

    return true;
}
Exemplo n.º 7
0
    void TradeHandler::ValidateAndAcknowledgeTrade(
    	AcceptCommit accept_commit)
    {
        uint160 accept_commit_hash = accept_commit.GetHash160();
    	uint160 commit_hash = accept_commit.order_commit_hash;
        OrderCommit commit = msgdata[commit_hash]["commit"];
        AcceptOrder accept;
        accept = msgdata[commit.accept_order_hash]["accept_order"];
        Order order = msgdata[accept.order_hash]["order"];

        Currency currency = flexnode.currencies[order.currency];
        vch_t payer_data, payee_data;

        if (order.side == ASK)
        {
            payer_data = order.auxiliary_data;
            payee_data = accept.auxiliary_data;
        }
        else
        {
            payee_data = order.auxiliary_data;
            payer_data = accept.auxiliary_data;
        }
        if (!currency.ValidateProposedFiatTransaction(accept_commit_hash,
                                                      payer_data, 
                                                      payee_data, 
                                                      order.size))
        {
            log_ << "Could not validate fiat transaction!\n";
            return;
        }
        
        tradedata[accept_commit_hash]["ttp_validated"] = true;
        ThirdPartyTransactionAcknowledgement ack(accept_commit_hash);
        ack.Sign();
        uint160 ack_hash = ack.GetHash160();
        tradedata[accept_commit_hash]["acknowledgement"] = ack_hash;
        BroadcastMessage(ack);
    }
Exemplo n.º 8
0
SLE::pointer
getLedgerEntryRippleState(Ledger::pointer ledger,
    TestAccount const& account1, TestAccount const& account2,
    Currency currency)
{
    auto uNodeIndex = getRippleStateIndex(
        account1.pk.getAccountID(), account2.pk.getAccountID(),
        to_currency(currency.getCurrency()));

    if (!uNodeIndex.isNonZero())
        throw std::runtime_error(
        "!uNodeIndex.isNonZero()");

    return ledger->getSLEi(uNodeIndex);
}
Exemplo n.º 9
0
bool to_currency(Currency& currency, std::string const& code)
{
    if (code.empty () || !code.compare (systemCurrencyCode()))
    {
        currency = zero;
        return true;
    }

	if (code.empty() || !code.compare(systemCurrencyCodeVBC()))
	{
		currency = vbcCurrency();
		return true;
	}

    static const int CURRENCY_CODE_LENGTH = 3;
    if (code.size () == CURRENCY_CODE_LENGTH)
    {
        Blob codeBlob (CURRENCY_CODE_LENGTH);

        std::transform (code.begin (), code.end (), codeBlob.begin (), ::toupper);

        Serializer  s;

        s.addZeros (96 / 8);
        s.addRaw (codeBlob);
        s.addZeros (16 / 8);
        s.addZeros (24 / 8);

        s.get160 (currency, 0);
        return true;
    }

    if (40 == code.size ())
        return currency.SetHex (code);

    return false;
}
Exemplo n.º 10
0
int PathRequest::parseJson (Json::Value const& jvParams, bool complete)
{
    int ret = PFR_PJ_NOCHANGE;

    if (jvParams.isMember (jss::source_account))
    {
        raSrcAccount = parseBase58<AccountID>(
            jvParams[jss::source_account].asString());
        if (! raSrcAccount)
        {
            jvStatus = rpcError (rpcSRC_ACT_MALFORMED);
            return PFR_PJ_INVALID;
        }
    }
    else if (complete)
    {
        jvStatus = rpcError (rpcSRC_ACT_MISSING);
        return PFR_PJ_INVALID;
    }

    if (jvParams.isMember (jss::destination_account))
    {
        raDstAccount = parseBase58<AccountID>(
            jvParams[jss::destination_account].asString());
        if (! raDstAccount)
        {
            jvStatus = rpcError (rpcDST_ACT_MALFORMED);
            return PFR_PJ_INVALID;
        }
    }
    else if (complete)
    {
        jvStatus = rpcError (rpcDST_ACT_MISSING);
        return PFR_PJ_INVALID;
    }

    if (jvParams.isMember (jss::destination_amount))
    {
        if (! amountFromJsonNoThrow (
                saDstAmount, jvParams[jss::destination_amount]) ||
            (saDstAmount.getCurrency ().isZero () &&
             saDstAmount.getIssuer ().isNonZero ()) ||
            (saDstAmount.getCurrency () == badCurrency ()) ||
            saDstAmount <= zero)
        {
            jvStatus = rpcError (rpcDST_AMT_MALFORMED);
            return PFR_PJ_INVALID;
        }
    }
    else if (complete)
    {
        jvStatus = rpcError (rpcDST_ACT_MISSING);
        return PFR_PJ_INVALID;
    }

    if (jvParams.isMember (jss::source_currencies))
    {
        Json::Value const& jvSrcCur = jvParams[jss::source_currencies];

        if (!jvSrcCur.isArray ())
        {
            jvStatus = rpcError (rpcSRC_CUR_MALFORMED);
            return PFR_PJ_INVALID;
        }

        sciSourceCurrencies.clear ();

        for (unsigned i = 0; i < jvSrcCur.size (); ++i)
        {
            Json::Value const& jvCur = jvSrcCur[i];
            Currency uCur;
            AccountID uIss;

            if (!jvCur.isObject() || !jvCur.isMember (jss::currency) ||
                !to_currency (uCur, jvCur[jss::currency].asString ()))
            {
                jvStatus = rpcError (rpcSRC_CUR_MALFORMED);
                return PFR_PJ_INVALID;
            }

            if (jvCur.isMember (jss::issuer) &&
                !to_issuer (uIss, jvCur[jss::issuer].asString ()))
            {
                jvStatus = rpcError (rpcSRC_ISR_MALFORMED);
            }

            if (uCur.isZero () && uIss.isNonZero ())
            {
                jvStatus = rpcError (rpcSRC_CUR_MALFORMED);
                return PFR_PJ_INVALID;
            }

            if (uCur.isNonZero() && uIss.isZero())
            {
                uIss = *raSrcAccount;
            }

            sciSourceCurrencies.insert ({uCur, uIss});
        }
    }

    if (jvParams.isMember ("id"))
        jvId = jvParams["id"];

    return ret;
}
Exemplo n.º 11
0
void BudgetBalancer::processItem(LedgerBudget const& budget)
{
   // if there is a budget period, process recorded items until we are within
   // range of this budget command
   advancePeriodToDate(budget.date());

   // if the current period started before today, or if it already has recorded
   // commands, then end the period today and process what we have
   if (m_period.startDate() != budget.date() || m_numRecords != 0)
   {
      m_period = DateRange(m_period.startDate(), budget.date());
      allocateCategories();
      processRecords();
   }

   // remove categories that are not in this budget command, or that have
   // changed, and allocate their funds to the available category
   auto categories = budget.categories();
   for (auto it = m_categories.cbegin(); it != m_categories.cend(); ++it)
   {
      if (!categories.contains(it.key()) ||
          categories[it.key()].type != it->type)
      {
         switch (it->type)
         {
            case LedgerBudget::Category::Type::GOAL:
               // nothing to do for goals
               break;
            case LedgerBudget::Category::Type::INCOME:
               // nothing to do for income type
               break;
            case LedgerBudget::Category::Type::RESERVE_AMOUNT:
            {
               Currency amount = m_reserveAmountAllocator.deallocate(it.key());
               if (!amount.isZero())
               {
                  emit message(budget,
                               QString("Reserve category '%1' was closed with "
                                       "a balance of %2.  Those funds are "
                                       "available again.")
                               .arg(it.key())
                               .arg(amount.toString()));
               }
               m_available += amount;
               break;
            }
            case LedgerBudget::Category::Type::RESERVE_PERCENT:
            {
               Currency amount = m_reservePercentAllocator.deallocate(it.key());
               if (!amount.isZero())
               {
                  emit message(budget,
                               QString("Reserve category '%1' was closed with "
                                       "a balance of %2.  Those funds are "
                                       "available again.")
                               .arg(it.key())
                               .arg(amount.toString()));
               }
               m_available += amount;
               break;
            }
            case LedgerBudget::Category::Type::ROUTINE:
               m_routineAllocator.deallocate(it.key());
               break;
         }
      }
   }

   // configure new and changed budget categories
   for (auto it = categories.cbegin(); it != categories.cend(); ++it)
   {
      switch (it->type)
      {
         case LedgerBudget::Category::Type::GOAL:
            m_goalAllocator.budget(budget.date());
            break;
         case LedgerBudget::Category::Type::INCOME:
            // nothing to do for income
            break;
         case LedgerBudget::Category::Type::RESERVE_AMOUNT:
            m_reserveAmountAllocator.budget(budget.date(), it.key(), it->amount,
                                            it->interval);
            break;
         case LedgerBudget::Category::Type::RESERVE_PERCENT:
            m_reservePercentAllocator.budget(it.key(), it->percentage);
            break;
         case LedgerBudget::Category::Type::ROUTINE:
            // nothing to do for routine expenses
            break;
      }
   }
   m_categories = categories;

   // reset the dates for the new period
   m_period = DateRange(budget.date(), budget.interval());
}
Exemplo n.º 12
0
// work backward to determine how much they need to send to get the
// specified amount of currency to the recipient
bool
PaymentOpFrame::sendNoCreate(AccountFrame& destination, LedgerDelta& delta,
                             LedgerManager& ledgerManager)
{
    Database& db = ledgerManager.getDatabase();

    bool multi_mode = mPayment.path.size() != 0;
    if (multi_mode)
    {
        innerResult().code(PAYMENT_SUCCESS_MULTI);
    }
    else
    {
        innerResult().code(PAYMENT_SUCCESS);
    }

    // tracks the last amount that was traded
    int64_t curBReceived = mPayment.amount;
    Currency curB = mPayment.currency;

    // update balances, walks backwards

    // update last balance in the chain
    {

        if (curB.type() == CURRENCY_TYPE_NATIVE)
        {
            destination.getAccount().balance += curBReceived;
            destination.storeChange(delta, db);
        }
        else
        {
            TrustFrame destLine;

            if (!TrustFrame::loadTrustLine(destination.getID(), curB, destLine,
                                           db))
            {
                innerResult().code(PAYMENT_NO_TRUST);
                return false;
            }

            if (!destLine.isAuthorized())
            {
                innerResult().code(PAYMENT_NOT_AUTHORIZED);
                return false;
            }

            if (!destLine.addBalance(curBReceived))
            {
                innerResult().code(PAYMENT_LINE_FULL);
                return false;
            }

            destLine.storeChange(delta, db);
        }

        if (multi_mode)
        {
            innerResult().multi().last =
                SimplePaymentResult(destination.getID(), curB, curBReceived);
        }
    }

    if (multi_mode)
    {
        // now, walk the path backwards
        for (int i = (int)mPayment.path.size() - 1; i >= 0; i--)
        {
            int64_t curASent, actualCurBReceived;
            Currency const& curA = mPayment.path[i];

            OfferExchange oe(delta, ledgerManager);

            // curA -> curB
            OfferExchange::ConvertResult r =
                oe.convertWithOffers(curA, INT64_MAX, curASent, curB,
                                     curBReceived, actualCurBReceived, nullptr);
            switch (r)
            {
            case OfferExchange::eFilterStop:
                assert(false); // no filter -> should not happen
                break;
            case OfferExchange::eOK:
                if (curBReceived == actualCurBReceived)
                {
                    break;
                }
            // fall through
            case OfferExchange::ePartial:
                innerResult().code(PAYMENT_TOO_FEW_OFFERS);
                return false;
            }
            assert(curBReceived == actualCurBReceived);
            curBReceived = curASent; // next round, we need to send enough
            curB = curA;

            // add offers that got taken on the way
            // insert in front to match the path's order
            auto& offers = innerResult().multi().offers;
            offers.insert(offers.begin(), oe.getOfferTrail().begin(),
                          oe.getOfferTrail().end());
        }
    }

    // last step: we've reached the first account in the chain, update its
    // balance

    int64_t curBSent;

    curBSent = curBReceived;

    if (curBSent > mPayment.sendMax)
    { // make sure not over the max
        innerResult().code(PAYMENT_OVER_SENDMAX);
        return false;
    }

    if (curB.type() == CURRENCY_TYPE_NATIVE)
    {
        int64_t minBalance = mSourceAccount->getMinimumBalance(ledgerManager);

        if (mSourceAccount->getAccount().balance < (minBalance + curBSent))
        { // they don't have enough to send
            innerResult().code(PAYMENT_UNDERFUNDED);
            return false;
        }

        mSourceAccount->getAccount().balance -= curBSent;
        mSourceAccount->storeChange(delta, db);
    }
    else
    {
        AccountFrame issuer;
        if (!AccountFrame::loadAccount(curB.alphaNum().issuer, issuer, db))
        {
            throw std::runtime_error("sendCredit Issuer not found");
        }

        TrustFrame sourceLineFrame;
        if (!TrustFrame::loadTrustLine(getSourceID(), curB, sourceLineFrame,
                                       db))
        {
            innerResult().code(PAYMENT_UNDERFUNDED);
            return false;
        }

        if (!sourceLineFrame.addBalance(-curBSent))
        {
            innerResult().code(PAYMENT_UNDERFUNDED);
            return false;
        }

        sourceLineFrame.storeChange(delta, db);
    }

    return true;
}
Exemplo n.º 13
0
		string ToString() { return CombineString(Currency.ToString(), DespoitType.ToString(),
									date::to_iso_string(Period.begin()), date::to_iso_string(Period.end()),
									date::to_iso_string(LastUpdateDate));
		}
Exemplo n.º 14
0
// This interface is deprecated.
Json::Value doRipplePathFind (RPC::Context& context)
{
    RPC::LegacyPathFind lpf (context.role == Role::ADMIN);
    if (!lpf.isOk ())
        return rpcError (rpcTOO_BUSY);

    context.loadType = Resource::feeHighBurdenRPC;

    RippleAddress raSrc;
    RippleAddress raDst;
    STAmount saDstAmount;
    Ledger::pointer lpLedger;

    Json::Value jvResult;

    if (getConfig().RUN_STANDALONE ||
        context.params.isMember(jss::ledger) ||
        context.params.isMember(jss::ledger_index) ||
        context.params.isMember(jss::ledger_hash))
    {
        // The caller specified a ledger
        jvResult = RPC::lookupLedger (
            context.params, lpLedger, context.netOps);
        if (!lpLedger)
            return jvResult;
    }

    if (!context.params.isMember ("source_account"))
    {
        jvResult = rpcError (rpcSRC_ACT_MISSING);
    }
    else if (!context.params["source_account"].isString ()
             || !raSrc.setAccountID (
                 context.params["source_account"].asString ()))
    {
        jvResult = rpcError (rpcSRC_ACT_MALFORMED);
    }
    else if (!context.params.isMember ("destination_account"))
    {
        jvResult = rpcError (rpcDST_ACT_MISSING);
    }
    else if (!context.params["destination_account"].isString ()
             || !raDst.setAccountID (
                 context.params["destination_account"].asString ()))
    {
        jvResult = rpcError (rpcDST_ACT_MALFORMED);
    }
    else if (
        // Parse saDstAmount.
        !context.params.isMember ("destination_amount")
        || ! amountFromJsonNoThrow(saDstAmount, context.params["destination_amount"])
        || saDstAmount <= zero
        || (!isXRP(saDstAmount.getCurrency ())
            && (!saDstAmount.getIssuer () ||
                noAccount() == saDstAmount.getIssuer ())))
    {
        WriteLog (lsINFO, RPCHandler) << "Bad destination_amount.";
        jvResult    = rpcError (rpcINVALID_PARAMS);
    }
    else if (
        // Checks on source_currencies.
        context.params.isMember ("source_currencies")
        && (!context.params["source_currencies"].isArray ()
            || !context.params["source_currencies"].size ())
        // Don't allow empty currencies.
    )
    {
        WriteLog (lsINFO, RPCHandler) << "Bad source_currencies.";
        jvResult    = rpcError (rpcINVALID_PARAMS);
    }
    else
    {
        context.loadType = Resource::feeHighBurdenRPC;
        RippleLineCache::pointer cache;

        if (lpLedger)
        {
            // The caller specified a ledger
            lpLedger = std::make_shared<Ledger> (std::ref (*lpLedger), false);
            cache = std::make_shared<RippleLineCache>(lpLedger);
        }
        else
        {
            // The closed ledger is recent and any nodes made resident
            // have the best chance to persist
            lpLedger = context.netOps.getClosedLedger();
            cache = getApp().getPathRequests().getLineCache(lpLedger, false);
        }

        Json::Value     jvSrcCurrencies;

        if (context.params.isMember ("source_currencies"))
        {
            jvSrcCurrencies = context.params["source_currencies"];
        }
        else
        {
            auto currencies = accountSourceCurrencies (raSrc, cache, true);
            jvSrcCurrencies = Json::Value (Json::arrayValue);

            for (auto const& uCurrency: currencies)
            {
                Json::Value jvCurrency (Json::objectValue);
                jvCurrency["currency"] = to_string(uCurrency);
                jvSrcCurrencies.append (jvCurrency);
            }
        }

        // Fill in currencies destination will accept
        Json::Value jvDestCur (Json::arrayValue);

        // TODO(tom): this could be optimized the same way that
        // PathRequest::doUpdate() is - if we don't obsolete this code first.
        auto usDestCurrID = accountDestCurrencies (raDst, cache, true);
        for (auto const& uCurrency: usDestCurrID)
                jvDestCur.append (to_string (uCurrency));

        jvResult["destination_currencies"] = jvDestCur;
        jvResult["destination_account"] = raDst.humanAccountID ();

        Json::Value jvArray (Json::arrayValue);

        int level = getConfig().PATH_SEARCH_OLD;
        if ((getConfig().PATH_SEARCH_MAX > level)
            && !getApp().getFeeTrack().isLoadedLocal())
        {
            ++level;
        }

        if (context.params.isMember("search_depth")
            && context.params["search_depth"].isIntegral())
        {
            int rLev = context.params["search_depth"].asInt ();
            if ((rLev < level) || (context.role == Role::ADMIN))
                level = rLev;
        }

        FindPaths fp (
            cache,
            raSrc.getAccountID(),
            raDst.getAccountID(),
            saDstAmount,
            level,
            4); // max paths

        for (unsigned int i = 0; i != jvSrcCurrencies.size (); ++i)
        {
            Json::Value jvSource        = jvSrcCurrencies[i];

            Currency uSrcCurrencyID;
            Account uSrcIssuerID;

            if (!jvSource.isObject ())
                return rpcError (rpcINVALID_PARAMS);

            // Parse mandatory currency.
            if (!jvSource.isMember ("currency")
                || !to_currency (
                    uSrcCurrencyID, jvSource["currency"].asString ()))
            {
                WriteLog (lsINFO, RPCHandler) << "Bad currency.";

                return rpcError (rpcSRC_CUR_MALFORMED);
            }

            if (uSrcCurrencyID.isNonZero ())
                uSrcIssuerID = raSrc.getAccountID ();

            // Parse optional issuer.
            if (jvSource.isMember ("issuer") &&
                ((!jvSource["issuer"].isString () ||
                  !to_issuer (uSrcIssuerID, jvSource["issuer"].asString ())) ||
                 (uSrcIssuerID.isZero () != uSrcCurrencyID.isZero ()) ||
                 (noAccount() == uSrcIssuerID)))
            {
                WriteLog (lsINFO, RPCHandler) << "Bad issuer.";
                return rpcError (rpcSRC_ISR_MALFORMED);
            }

            STPathSet spsComputed;
            if (context.params.isMember("paths"))
            {
                Json::Value pathSet = Json::objectValue;
                pathSet["Paths"] = context.params["paths"];
                STParsedJSONObject paths ("pathSet", pathSet);
                if (paths.object.get() == nullptr)
                    return paths.error;
                else
                {
                    spsComputed = paths.object.get()->getFieldPathSet (sfPaths);
                    WriteLog (lsTRACE, RPCHandler) << "ripple_path_find: Paths: " << spsComputed.getJson (0);
                }
            }

            STPath fullLiquidityPath;
            auto valid = fp.findPathsForIssue (
                {uSrcCurrencyID, uSrcIssuerID},
                spsComputed,
                fullLiquidityPath);
            if (!valid)
            {
                WriteLog (lsWARNING, RPCHandler)
                    << "ripple_path_find: No paths found.";
            }
            else
            {
                auto& issuer =
                    isXRP (uSrcIssuerID) ?
                        isXRP (uSrcCurrencyID) ? // Default to source account.
                            xrpAccount() :
                            Account (raSrc.getAccountID ())
                        : uSrcIssuerID;            // Use specifed issuer.

                STAmount saMaxAmount ({uSrcCurrencyID, issuer}, 1);
                saMaxAmount.negate ();

                LedgerEntrySet lesSandbox (lpLedger, tapNONE);

                auto rc = path::RippleCalc::rippleCalculate (
                    lesSandbox,
                    saMaxAmount,            // --> Amount to send is unlimited
                                            //     to get an estimate.
                    saDstAmount,            // --> Amount to deliver.
                    raDst.getAccountID (),  // --> Account to deliver to.
                    raSrc.getAccountID (),  // --> Account sending from.
                    spsComputed);           // --> Path set.

                WriteLog (lsWARNING, RPCHandler)
                    << "ripple_path_find:"
                    << " saMaxAmount=" << saMaxAmount
                    << " saDstAmount=" << saDstAmount
                    << " saMaxAmountAct=" << rc.actualAmountIn
                    << " saDstAmountAct=" << rc.actualAmountOut;

                if (fullLiquidityPath.size() > 0 &&
                    (rc.result() == terNO_LINE || rc.result() == tecPATH_PARTIAL))
                {
                    WriteLog (lsDEBUG, PathRequest)
                        << "Trying with an extra path element";

                    spsComputed.push_back (fullLiquidityPath);
                    lesSandbox.clear ();
                    rc = path::RippleCalc::rippleCalculate (
                        lesSandbox,
                        saMaxAmount,            // --> Amount to send is unlimited
                        //     to get an estimate.
                        saDstAmount,            // --> Amount to deliver.
                        raDst.getAccountID (),  // --> Account to deliver to.
                        raSrc.getAccountID (),  // --> Account sending from.
                        spsComputed);         // --> Path set.
                    WriteLog (lsDEBUG, PathRequest)
                        << "Extra path element gives "
                        << transHuman (rc.result ());
                }

                if (rc.result () == tesSUCCESS)
                {
                    Json::Value jvEntry (Json::objectValue);

                    STPathSet   spsCanonical;

                    // Reuse the expanded as it would need to be calcuated
                    // anyway to produce the canonical.  (At least unless we
                    // make a direct canonical.)

                    jvEntry["source_amount"] = rc.actualAmountIn.getJson (0);
                    jvEntry["paths_canonical"]  = Json::arrayValue;
                    jvEntry["paths_computed"]   = spsComputed.getJson (0);

                    jvArray.append (jvEntry);
                }
                else
                {
                    std::string strToken;
                    std::string strHuman;

                    transResultInfo (rc.result (), strToken, strHuman);

                    WriteLog (lsDEBUG, RPCHandler)
                        << "ripple_path_find: "
                        << strToken << " "
                        << strHuman << " "
                        << spsComputed.getJson (0);
                }
            }
        }

        // Each alternative differs by source currency.
        jvResult["alternatives"] = jvArray;
    }

    WriteLog (lsDEBUG, RPCHandler)
            << boost::str (boost::format ("ripple_path_find< %s")
                           % jvResult);

    return jvResult;
}
Exemplo n.º 15
0
		string ToString() { return CombineString(Number, Name, Source, Currency.ToString(),
									time::to_iso_string(Time), Description); }
Exemplo n.º 16
0
std::pair<bool, Json::Value>
ripplePathFind(RippleLineCache::pointer const& cache, 
  RippleAddress const& raSrc, RippleAddress const& raDst,
    STAmount const& saDstAmount, Ledger::pointer const& lpLedger, 
      Json::Value const& jvSrcCurrencies, 
        boost::optional<Json::Value> const& contextPaths, int const& level)
{
    FindPaths fp(
        cache,
        raSrc.getAccountID(),
        raDst.getAccountID(),
        saDstAmount,
        level,
        4); // max paths

    Json::Value jvArray(Json::arrayValue);

    for (unsigned int i = 0; i != jvSrcCurrencies.size(); ++i)
    {
        Json::Value jvSource = jvSrcCurrencies[i];

        Currency uSrcCurrencyID;
        Account uSrcIssuerID;

        if (!jvSource.isObject())
            return std::make_pair(false, rpcError(rpcINVALID_PARAMS));

        // Parse mandatory currency.
        if (!jvSource.isMember(jss::currency)
            || !to_currency(
            uSrcCurrencyID, jvSource[jss::currency].asString()))
        {
            WriteLog(lsINFO, RPCHandler) << "Bad currency.";

            return std::make_pair(false, rpcError(rpcSRC_CUR_MALFORMED));
        }

        if (uSrcCurrencyID.isNonZero())
            uSrcIssuerID = raSrc.getAccountID();

        // Parse optional issuer.
        if (jvSource.isMember(jss::issuer) &&
            ((!jvSource[jss::issuer].isString() ||
            !to_issuer(uSrcIssuerID, jvSource[jss::issuer].asString())) ||
            (uSrcIssuerID.isZero() != uSrcCurrencyID.isZero()) ||
            (noAccount() == uSrcIssuerID)))
        {
            WriteLog(lsINFO, RPCHandler) << "Bad issuer.";
            return std::make_pair(false, rpcError(rpcSRC_ISR_MALFORMED));
        }

        STPathSet spsComputed;
        if (contextPaths)
        {
            Json::Value pathSet = Json::objectValue;
            pathSet[jss::Paths] = contextPaths.get();
            STParsedJSONObject paths("pathSet", pathSet);
            if (paths.object.get() == nullptr)
                return std::make_pair(false, paths.error);
            else
            {
                spsComputed = paths.object.get()->getFieldPathSet(sfPaths);
                WriteLog(lsTRACE, RPCHandler) << "ripple_path_find: Paths: " <<
                    spsComputed.getJson(0);
            }
        }

        STPath fullLiquidityPath;
        auto valid = fp.findPathsForIssue(
            { uSrcCurrencyID, uSrcIssuerID },
            spsComputed,
            fullLiquidityPath);
        if (!valid)
        {
            WriteLog(lsWARNING, RPCHandler)
                << "ripple_path_find: No paths found.";
        }
        else
        {
            auto& issuer =
                isXRP(uSrcIssuerID) ?
                isXRP(uSrcCurrencyID) ? // Default to source account.
                xrpAccount() :
                Account(raSrc.getAccountID())
                : uSrcIssuerID;            // Use specifed issuer.

            STAmount saMaxAmount({ uSrcCurrencyID, issuer }, 1);
            saMaxAmount.negate();

            LedgerEntrySet lesSandbox(lpLedger, tapNONE);

            auto rc = path::RippleCalc::rippleCalculate(
                lesSandbox,
                saMaxAmount,            // --> Amount to send is unlimited
                //     to get an estimate.
                saDstAmount,            // --> Amount to deliver.
                raDst.getAccountID(),  // --> Account to deliver to.
                raSrc.getAccountID(),  // --> Account sending from.
                spsComputed);           // --> Path set.

            WriteLog(lsWARNING, RPCHandler)
                << "ripple_path_find:"
                << " saMaxAmount=" << saMaxAmount
                << " saDstAmount=" << saDstAmount
                << " saMaxAmountAct=" << rc.actualAmountIn
                << " saDstAmountAct=" << rc.actualAmountOut;

            if (fullLiquidityPath.size() > 0 &&
                (rc.result() == terNO_LINE || rc.result() == tecPATH_PARTIAL))
            {
                WriteLog(lsDEBUG, PathRequest)
                    << "Trying with an extra path element";

                spsComputed.push_back(fullLiquidityPath);
                lesSandbox.clear();
                rc = path::RippleCalc::rippleCalculate(
                    lesSandbox,
                    saMaxAmount,            // --> Amount to send is unlimited
                    //     to get an estimate.
                    saDstAmount,            // --> Amount to deliver.
                    raDst.getAccountID(),  // --> Account to deliver to.
                    raSrc.getAccountID(),  // --> Account sending from.
                    spsComputed);         // --> Path set.
                WriteLog(lsDEBUG, PathRequest)
                    << "Extra path element gives "
                    << transHuman(rc.result());
            }

            if (rc.result() == tesSUCCESS)
            {
                Json::Value jvEntry(Json::objectValue);

                STPathSet   spsCanonical;

                // Reuse the expanded as it would need to be calcuated
                // anyway to produce the canonical.  (At least unless we
                // make a direct canonical.)

                jvEntry[jss::source_amount] = rc.actualAmountIn.getJson(0);
                jvEntry[jss::paths_canonical] = Json::arrayValue;
                jvEntry[jss::paths_computed] = spsComputed.getJson(0);

                jvArray.append(jvEntry);
            }
            else
            {
                std::string strToken;
                std::string strHuman;

                transResultInfo(rc.result(), strToken, strHuman);

                WriteLog(lsDEBUG, RPCHandler)
                    << "ripple_path_find: "
                    << strToken << " "
                    << strHuman << " "
                    << spsComputed.getJson(0);
            }
        }
    }

    return std::make_pair(true, jvArray);
}
Exemplo n.º 17
0
 inline Money Money::rounded() const {
     return Money(currency_.rounding()(value_), currency_);
 }
Exemplo n.º 18
0
int PathRequest::parseJson (const Json::Value& jvParams, bool complete)
{
    int ret = PFR_PJ_NOCHANGE;

    if (jvParams.isMember ("source_account"))
    {
        if (!raSrcAccount.setAccountID (jvParams["source_account"].asString ()))
        {
            jvStatus = rpcError (rpcSRC_ACT_MALFORMED);
            return PFR_PJ_INVALID;
        }
    }
    else if (complete)
    {
        jvStatus = rpcError (rpcSRC_ACT_MISSING);
        return PFR_PJ_INVALID;
    }

    if (jvParams.isMember ("destination_account"))
    {
        if (!raDstAccount.setAccountID (jvParams["destination_account"].asString ()))
        {
            jvStatus = rpcError (rpcDST_ACT_MALFORMED);
            return PFR_PJ_INVALID;
        }
    }
    else if (complete)
    {
        jvStatus = rpcError (rpcDST_ACT_MISSING);
        return PFR_PJ_INVALID;
    }

    if (jvParams.isMember ("destination_amount"))
    {
        if (!saDstAmount.bSetJson (jvParams["destination_amount"]) ||
                (saDstAmount.getCurrency ().isZero () && saDstAmount.getIssuer ().isNonZero ()) ||
                (saDstAmount.getCurrency () == badCurrency()) ||
                saDstAmount <= zero)
        {
            jvStatus = rpcError (rpcDST_AMT_MALFORMED);
            return PFR_PJ_INVALID;
        }
    }
    else if (complete)
    {
        jvStatus = rpcError (rpcDST_ACT_MISSING);
        return PFR_PJ_INVALID;
    }

    if (jvParams.isMember ("source_currencies"))
    {
        const Json::Value& jvSrcCur = jvParams["source_currencies"];

        if (!jvSrcCur.isArray ())
        {
            jvStatus = rpcError (rpcSRC_CUR_MALFORMED);
            return PFR_PJ_INVALID;
        }

        sciSourceCurrencies.clear ();

        for (unsigned i = 0; i < jvSrcCur.size (); ++i)
        {
            const Json::Value& jvCur = jvSrcCur[i];
            Currency uCur;
            Account uIss;

            if (!jvCur.isObject() || !jvCur.isMember ("currency") ||
                !to_currency (uCur, jvCur["currency"].asString ()))
            {
                jvStatus = rpcError (rpcSRC_CUR_MALFORMED);
                return PFR_PJ_INVALID;
            }

            if (jvCur.isMember ("issuer") &&
                !to_issuer (uIss, jvCur["issuer"].asString ()))
            {
                jvStatus = rpcError (rpcSRC_ISR_MALFORMED);
            }

            if (uCur.isZero () && uIss.isNonZero ())
            {
                jvStatus = rpcError (rpcSRC_CUR_MALFORMED);
                return PFR_PJ_INVALID;
            }

            sciSourceCurrencies.insert ({uCur, uIss});
        }
    }

    if (jvParams.isMember ("id"))
        jvId = jvParams["id"];

    return ret;
}
Exemplo n.º 19
0
bool
PathPaymentOpFrame::doApply(medida::MetricsRegistry& metrics,
                            LedgerDelta& delta, LedgerManager& ledgerManager)
{
    AccountFrame::pointer destination;

    Database& db = ledgerManager.getDatabase();

    destination = AccountFrame::loadAccount(mPathPayment.destination, db);

    if (!destination)
    {
        metrics.NewMeter({"op-path-payment", "failure", "no-destination"},
                         "operation").Mark();
        innerResult().code(PATH_PAYMENT_NO_DESTINATION);
        return false;
    }

    innerResult().code(PATH_PAYMENT_SUCCESS);

    // tracks the last amount that was traded
    int64_t curBReceived = mPathPayment.destAmount;
    Currency curB = mPathPayment.destCurrency;

    // update balances, walks backwards

    // build the full path to the destination, starting with sendCurrency
    std::vector<Currency> fullPath;
    fullPath.emplace_back(mPathPayment.sendCurrency);
    fullPath.insert(fullPath.end(), mPathPayment.path.begin(),
                    mPathPayment.path.end());

    // update last balance in the chain
    {
        if (curB.type() == CURRENCY_TYPE_NATIVE)
        {
            destination->getAccount().balance += curBReceived;
            destination->storeChange(delta, db);
        }
        else
        {
            TrustFrame::pointer destLine;

            destLine =
                TrustFrame::loadTrustLine(destination->getID(), curB, db);
            if (!destLine)
            {
                metrics.NewMeter({"op-path-payment", "failure", "no-trust"},
                                 "operation").Mark();
                innerResult().code(PATH_PAYMENT_NO_TRUST);
                return false;
            }

            if (!destLine->isAuthorized())
            {
                metrics.NewMeter(
                            {"op-path-payment", "failure", "not-authorized"},
                            "operation").Mark();
                innerResult().code(PATH_PAYMENT_NOT_AUTHORIZED);
                return false;
            }

            if (!destLine->addBalance(curBReceived))
            {
                metrics.NewMeter({"op-path-payment", "failure", "line-full"},
                                 "operation").Mark();
                innerResult().code(PATH_PAYMENT_LINE_FULL);
                return false;
            }

            destLine->storeChange(delta, db);
        }

        innerResult().success().last =
            SimplePaymentResult(destination->getID(), curB, curBReceived);
    }

    // now, walk the path backwards
    for (int i = (int)fullPath.size() - 1; i >= 0; i--)
    {
        int64_t curASent, actualCurBReceived;
        Currency const& curA = fullPath[i];

        if (curA == curB)
        {
            continue;
        }

        OfferExchange oe(delta, ledgerManager);

        // curA -> curB
        OfferExchange::ConvertResult r =
            oe.convertWithOffers(curA, INT64_MAX, curASent, curB, curBReceived,
                                 actualCurBReceived, nullptr);
        switch (r)
        {
        case OfferExchange::eFilterStop:
            assert(false); // no filter -> should not happen
            break;
        case OfferExchange::eOK:
            if (curBReceived == actualCurBReceived)
            {
                break;
            }
        // fall through
        case OfferExchange::ePartial:
            metrics.NewMeter({"op-path-payment", "failure", "too-few-offers"},
                             "operation").Mark();
            innerResult().code(PATH_PAYMENT_TOO_FEW_OFFERS);
            return false;
        }
        assert(curBReceived == actualCurBReceived);
        curBReceived = curASent; // next round, we need to send enough
        curB = curA;

        // add offers that got taken on the way
        // insert in front to match the path's order
        auto& offers = innerResult().success().offers;
        offers.insert(offers.begin(), oe.getOfferTrail().begin(),
                      oe.getOfferTrail().end());
    }

    // last step: we've reached the first account in the chain, update its
    // balance

    int64_t curBSent;

    curBSent = curBReceived;

    if (curBSent > mPathPayment.sendMax)
    { // make sure not over the max
        metrics.NewMeter({"op-path-payment", "failure", "over-send-max"},
                         "operation").Mark();
        innerResult().code(PATH_PAYMENT_OVER_SENDMAX);
        return false;
    }

    if (curB.type() == CURRENCY_TYPE_NATIVE)
    {
        int64_t minBalance = mSourceAccount->getMinimumBalance(ledgerManager);

        if ((mSourceAccount->getAccount().balance - curBSent) < minBalance)
        { // they don't have enough to send
            metrics.NewMeter({"op-path-payment", "failure", "underfunded"},
                             "operation").Mark();
            innerResult().code(PATH_PAYMENT_UNDERFUNDED);
            return false;
        }

        mSourceAccount->getAccount().balance -= curBSent;
        mSourceAccount->storeChange(delta, db);
    }
    else
    {
        AccountFrame::pointer issuer;
        issuer = AccountFrame::loadAccount(curB.alphaNum().issuer, db);

        if (!issuer)
        {
            metrics.NewMeter({"op-path-payment", "failure", "no-issuer"},
                             "operation").Mark();
            throw std::runtime_error("sendCredit Issuer not found");
        }

        TrustFrame::pointer sourceLineFrame;
        sourceLineFrame = TrustFrame::loadTrustLine(getSourceID(), curB, db);
        if (!sourceLineFrame)
        {
            metrics.NewMeter({"op-path-payment", "failure", "src-no-trust"},
                             "operation").Mark();
            innerResult().code(PATH_PAYMENT_SRC_NO_TRUST);
            return false;
        }

        if (!sourceLineFrame->isAuthorized())
        {
            metrics.NewMeter(
                        {"op-path-payment", "failure", "src-not-authorized"},
                        "operation").Mark();
            innerResult().code(PATH_PAYMENT_SRC_NOT_AUTHORIZED);
            return false;
        }

        if (!sourceLineFrame->addBalance(-curBSent))
        {
            metrics.NewMeter({"op-path-payment", "failure", "underfunded"},
                             "operation").Mark();
            innerResult().code(PATH_PAYMENT_UNDERFUNDED);
            return false;
        }

        sourceLineFrame->storeChange(delta, db);
    }

    metrics.NewMeter({"op-path-payment", "success", "apply"}, "operation")
        .Mark();

    return true;
}
Exemplo n.º 20
0
double EqonomizeValueEdit::fixup_sub(QString &input, QStringList &errors, bool &calculated) const {
	input = input.trimmed();
	if(input.isEmpty()) {
		return 0.0;
	}
	if(o_currency) {
		input.remove(budget->monetary_group_separator);
		if(!budget->monetary_negative_sign.isEmpty()) input.replace(budget->monetary_negative_sign, "-");
		if(!budget->monetary_positive_sign.isEmpty()) input.replace(budget->monetary_positive_sign, "+");
	} else {
		input.remove(budget->group_separator);
		if(!budget->negative_sign.isEmpty()) input.replace(budget->negative_sign, "-");
		if(!budget->positive_sign.isEmpty()) input.replace(budget->positive_sign, "+");
	}
	input.replace(QLocale().negativeSign(), '-');
	input.replace(QLocale().positiveSign(), '+');
	int i = input.indexOf(')', 1);
	if(i < 1) {
		i = input.indexOf('(', 0);
		if(i == 0) {
			input.remove(0, 1);
			return fixup_sub(input, errors, calculated);
		} else if(i >= 0) {
			input += ')';
			i = input.length() - 1;
		} else {
			i = -1;
		}
	}
	if(i >= 1) {
		int i2 = input.lastIndexOf('(', i - 1);
		if(i2 < 0 || i2 > i) {
			if(i == input.length() - 1) {
				input.chop(1);
				return fixup_sub(input, errors, calculated);
			}
			input.prepend('(');
			i++;
			i2 = 0;
		}
		if(i2 == 0 && i == input.length() - 1) {
			input.remove(0, 1);
			input.chop(1);
			return fixup_sub(input, errors, calculated);
		}
		if(i < input.length() - 1 && (input[i + 1].isNumber() || input[i + 1] == '(')) input.insert(i + 1, '*');
		QString str = input.mid(i2 + 1, i - i2 - 1);
		double v = fixup_sub(str, errors, calculated);
		input.replace(i2, i - i2 + 1, o_currency ? o_currency->formatValue(0.5, decimals() + 2, false, false, true) : budget->formatValue(v, decimals() + 2));
		if(i2 > 0 && (input[i2 - 1].isNumber() || input[i2 - 1] == ')')) input.insert(i2, '*');
		calculated = true;
		return fixup_sub(input, errors, calculated);
	}
	i = input.indexOf(QRegExp("[-+]"), 1);
	if(i >= 1) {
		QStringList terms = input.split(QRegExp("[-+]"));
		i = 0;
		double v = 0.0;
		QList<bool> signs;
		signs << true;
		for(int terms_i = 0; terms_i < terms.size() - 1; terms_i++) {
			i += terms[terms_i].length();
			if(input[i] == '-') signs << false;
			else signs << true;
			i++;
		}
		for(int terms_i = 0; terms_i < terms.size() - 1; terms_i++) {
			if(terms[terms_i].endsWith('*') || terms[terms_i].endsWith('/') || terms[terms_i].endsWith('^')) {
				if(!signs[terms_i + 1]) terms[terms_i] += '-';
				else terms[terms_i] += '+';
				terms[terms_i] += terms[terms_i + 1];
				signs.removeAt(terms_i + 1);
				terms.removeAt(terms_i + 1);
				terms_i--;
			}
		}
		if(terms.size() > 1) {
			for(int terms_i = 0; terms_i < terms.size(); terms_i++) {
				if(terms[terms_i].isEmpty()) {
					if(!signs[terms_i] && terms_i + 1 < terms.size()) {
						signs[terms_i + 1] = !signs[terms_i + 1];
					}
				} else {					
					if(!signs[terms_i]) v -= fixup_sub(terms[terms_i], errors, calculated);
					else v += fixup_sub(terms[terms_i], errors, calculated);
				}
			}			
			calculated = true;
			return v;
		}
	}
	if(input.indexOf("**") >= 0) input.replace("**", "^");
	i = input.indexOf(QRegExp("[*/]"), 0);
	if(i >= 0) {
		QStringList terms = input.split(QRegExp("[*/]"));
		QChar c = '*';
		i = 0;
		double v = 1.0;
		for(int terms_i = 0; terms_i < terms.size(); terms_i++) {
			if(terms[terms_i].isEmpty()) {
				if(c == '/') {
					errors << tr("Empty denominator.");
				} else {
					errors << tr("Empty factor.");
				}
			} else {
				i += terms[terms_i].length();
				if(c == '/') {
					double den = fixup_sub(terms[terms_i], errors, calculated);
					if(den == 0.0) {
						errors << tr("Division by zero.");
					} else {
						v /= den;
					}
				} else {
					v *= fixup_sub(terms[terms_i], errors, calculated);
				}
				if(i < input.length()) c = input[i];
			}
			i++;
		}
		calculated = true;
		return v;
	}
	i = input.indexOf(QLocale().percent());
	if(i >= 0) {
		double v = 0.01;
		if(input.length() > 1) {
			if(i > 0 && i < input.length() - 1) {
				QString str = input.right(input.length() - 1 - i);
				input = input.left(i);
				i = 0;
				v = fixup_sub(str, errors, calculated) * v;
			} else if(i == input.length() - 1) {
				input = input.left(i);
			} else if(i == 0) {
				input = input.right(input.length() - 1);
			}
			v = fixup_sub(input, errors, calculated) * v;
		}
		calculated = true;
		return v;
	}	
	if(o_currency) {
		QString reg_exp_str = "[\\d\\+\\-\\^";
		reg_exp_str += '\\';
		reg_exp_str += budget->monetary_decimal_separator;
		reg_exp_str += '\\';
		reg_exp_str += budget->monetary_group_separator;
		if(budget->monetary_decimal_separator != "." && budget->monetary_group_separator != ".") {
			reg_exp_str += '\\';
			reg_exp_str += '.';
		}
		reg_exp_str += "]";
		int i = input.indexOf(QRegExp(reg_exp_str));
		if(i >= 1) {
			QString scur = input.left(i).trimmed();
			Currency *cur = budget->findCurrency(scur);
			if(!cur && budget->defaultCurrency()->symbol(false) == scur) cur = budget->defaultCurrency();
			if(!cur) cur = budget->findCurrencySymbol(scur, true);
			if(cur) {
				QString value = input.right(input.length() - i);				
				double v = fixup_sub(value, errors, calculated);
				if(cur != o_currency) {
					v = cur->convertTo(v, o_currency);
				}
				calculated = true;
				return v;
			}
			errors << tr("Unknown or ambiguous currency, or unrecognized characters, in expression: %1.").arg(scur);
		}
		if(i >= 0) {
			i = input.lastIndexOf(QRegExp(reg_exp_str));
			if(i >= 0 && i < input.length() - 1) {
				QString scur = input.right(input.length() - (i + 1)).trimmed();
				Currency *cur = budget->findCurrency(scur);
				if(!cur && budget->defaultCurrency()->symbol(false) == scur) cur = budget->defaultCurrency();
				if(!cur) cur = budget->findCurrencySymbol(scur, true);
				if(cur) {
					QString value = input.left(i + 1);
					double v = fixup_sub(value, errors, calculated);
					if(cur != o_currency) {
						v = cur->convertTo(v, o_currency);
					}
					calculated = true;
					return v;
				}
				errors << tr("Unknown or ambiguous currency, or unrecognized characters, in expression: %1.").arg(scur);
			}
		} else {
			Currency *cur = budget->findCurrency(input);
			if(!cur && budget->defaultCurrency()->symbol(false) == input) cur = budget->defaultCurrency();
			if(!cur) cur = budget->findCurrencySymbol(input, true);
			if(cur) {
				double v = 1.0;
				if(cur != o_currency) {
					v = cur->convertTo(v, o_currency);
				}
				calculated = true;
				return v;
			}
			errors << tr("Unknown or ambiguous currency, or unrecognized characters, in expression: %1.").arg(input);
		}
	}
	i = input.indexOf('^', 0);
	if(i >= 0 && i != input.length() - 1) {
		QString base = input.left(i);
		if(base.isEmpty()) {
			errors << tr("Empty base.");
		} else {
			QString exp = input.right(input.length() - (i + 1));
			double v;
			if(exp.isEmpty()) {
				errors << tr("Error"), tr("Empty exponent.");
				v = 1.0;
			} else {
				v = pow(fixup_sub(base, errors, calculated), fixup_sub(exp, errors, calculated));
			}
			calculated = true;
			return v;
		}
	}
	
	if(!o_currency) {
		QString reg_exp_str = "[^\\d\\+\\-";
		reg_exp_str += '\\';
		reg_exp_str += budget->decimal_separator;
		reg_exp_str += '\\';
		reg_exp_str += budget->group_separator;
		if(budget->decimal_separator != "." && budget->group_separator != ".") {
			reg_exp_str += '\\';
			reg_exp_str += '.';
		}
		reg_exp_str += "]";
		i = input.indexOf(QRegExp(reg_exp_str));
		if(i >= 0) {
			errors << tr("Unrecognized characters in expression.");
		}
		input.remove(budget->group_separator);
		input.replace(budget->decimal_separator, ".");
		return input.toDouble();
	}
	input.remove(budget->monetary_group_separator);
	input.replace(budget->monetary_decimal_separator, ".");
	return input.toDouble();
}
Exemplo n.º 21
0
int PathRequest::parseJson (Json::Value const& jvParams)
{
    if (! jvParams.isMember(jss::source_account))
    {
        jvStatus = rpcError(rpcSRC_ACT_MISSING);
        return PFR_PJ_INVALID;
    }

    if (! jvParams.isMember(jss::destination_account))
    {
        jvStatus = rpcError(rpcDST_ACT_MISSING);
        return PFR_PJ_INVALID;
    }

    if (! jvParams.isMember(jss::destination_amount))
    {
        jvStatus = rpcError(rpcDST_AMT_MISSING);
        return PFR_PJ_INVALID;
    }

    raSrcAccount = parseBase58<AccountID>(
        jvParams[jss::source_account].asString());
    if (! raSrcAccount)
    {
        jvStatus = rpcError (rpcSRC_ACT_MALFORMED);
        return PFR_PJ_INVALID;
    }

    raDstAccount = parseBase58<AccountID>(
        jvParams[jss::destination_account].asString());
    if (! raDstAccount)
    {
        jvStatus = rpcError (rpcDST_ACT_MALFORMED);
        return PFR_PJ_INVALID;
    }

    if (! amountFromJsonNoThrow (
        saDstAmount, jvParams[jss::destination_amount]))
    {
        jvStatus = rpcError (rpcDST_AMT_MALFORMED);
        return PFR_PJ_INVALID;
    }

    convert_all_ = saDstAmount == STAmount(saDstAmount.issue(), 1u, 0, true);

    if ((saDstAmount.getCurrency ().isZero () &&
            saDstAmount.getIssuer ().isNonZero ()) ||
        (saDstAmount.getCurrency () == badCurrency ()) ||
        (! convert_all_ && saDstAmount <= zero))
    {
        jvStatus = rpcError (rpcDST_AMT_MALFORMED);
        return PFR_PJ_INVALID;
    }

    if (jvParams.isMember(jss::send_max))
    {
        // Send_max requires destination amount to be -1.
        if (! convert_all_)
        {
            jvStatus = rpcError(rpcDST_AMT_MALFORMED);
            return PFR_PJ_INVALID;
        }

        saSendMax.emplace();
        if (! amountFromJsonNoThrow(
            *saSendMax, jvParams[jss::send_max]) ||
            (saSendMax->getCurrency().isZero() &&
                saSendMax->getIssuer().isNonZero()) ||
            (saSendMax->getCurrency() == badCurrency()) ||
            (*saSendMax <= zero &&
                *saSendMax != STAmount(saSendMax->issue(), 1u, 0, true)))
        {
            jvStatus = rpcError(rpcSENDMAX_MALFORMED);
            return PFR_PJ_INVALID;
        }
    }

    if (jvParams.isMember (jss::source_currencies))
    {
        Json::Value const& jvSrcCurrencies = jvParams[jss::source_currencies];
        if (! jvSrcCurrencies.isArray() || jvSrcCurrencies.size() == 0 ||
            jvSrcCurrencies.size() > RPC::Tuning::max_src_cur)
        {
            jvStatus = rpcError (rpcSRC_CUR_MALFORMED);
            return PFR_PJ_INVALID;
        }

        sciSourceCurrencies.clear ();

        for (auto const& c : jvSrcCurrencies)
        {
            // Mandatory currency
            Currency srcCurrencyID;
            if (! c.isObject() ||
                ! c.isMember(jss::currency) ||
                ! to_currency(srcCurrencyID, c[jss::currency].asString()))
            {
                jvStatus = rpcError (rpcSRC_CUR_MALFORMED);
                return PFR_PJ_INVALID;
            }

            // Optional issuer
            AccountID srcIssuerID;
            if (c.isMember (jss::issuer) &&
                (! c[jss::issuer].isString() ||
                    ! to_issuer(srcIssuerID, c[jss::issuer].asString())))
            {
                jvStatus = rpcError (rpcSRC_ISR_MALFORMED);
                return PFR_PJ_INVALID;
            }

            if (srcCurrencyID.isZero())
            {
                if (srcIssuerID.isNonZero())
                {
                    jvStatus = rpcError(rpcSRC_CUR_MALFORMED);
                    return PFR_PJ_INVALID;
                }
            }
            else if (srcIssuerID.isZero())
            {
                srcIssuerID = *raSrcAccount;
            }

            if (saSendMax)
            {
                // If the currencies don't match, ignore the source currency.
                if (srcCurrencyID == saSendMax->getCurrency())
                {
                    // If neither is the source and they are not equal, then the
                    // source issuer is illegal.
                    if (srcIssuerID != *raSrcAccount &&
                        saSendMax->getIssuer() != *raSrcAccount &&
                            srcIssuerID != saSendMax->getIssuer())
                    {
                        jvStatus = rpcError (rpcSRC_ISR_MALFORMED);
                        return PFR_PJ_INVALID;
                    }

                    // If both are the source, use the source.
                    // Otherwise, use the one that's not the source.
                    if (srcIssuerID != *raSrcAccount)
                    {
                        sciSourceCurrencies.insert(
                            {srcCurrencyID, srcIssuerID});
                    }
                    else if (saSendMax->getIssuer() != *raSrcAccount)
                    {
                        sciSourceCurrencies.insert(
                            {srcCurrencyID, saSendMax->getIssuer()});
                    }
                    else
                    {
                        sciSourceCurrencies.insert(
                            {srcCurrencyID, *raSrcAccount});
                    }
                }
            }
            else
            {
                sciSourceCurrencies.insert({srcCurrencyID, srcIssuerID});
            }
        }
    }

    if (jvParams.isMember ("id"))
        jvId = jvParams["id"];

    return PFR_PJ_NOCHANGE;
}
Exemplo n.º 22
0
 inline bool operator==(const Currency& c1, const Currency& c2) {
     return c1.name() == c2.name();
 }