diff --git a/Builds/VisualStudio2013/RippleD.vcxproj b/Builds/VisualStudio2013/RippleD.vcxproj index 08916b7fb5..40128c5114 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj +++ b/Builds/VisualStudio2013/RippleD.vcxproj @@ -375,6 +375,8 @@ + + @@ -1517,12 +1519,6 @@ - - True - True - - - @@ -1701,10 +1697,6 @@ - - True - True - @@ -2631,6 +2623,8 @@ True True + + @@ -2645,6 +2639,10 @@ + + True + True + True True @@ -2775,6 +2773,10 @@ True True + + True + True + True True @@ -2883,10 +2885,18 @@ True True + + True + True + + + + + diff --git a/Builds/VisualStudio2013/RippleD.vcxproj.filters b/Builds/VisualStudio2013/RippleD.vcxproj.filters index c401660506..0b97d0865c 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2013/RippleD.vcxproj.filters @@ -271,9 +271,6 @@ {9AD8D049-10A8-704C-D51A-FAD55B1F235F} - - {1025719B-6A8F-D9FB-A6BA-02B93756DE09} - {2E791662-6ED0-D1E1-03A4-0CB35473EC56} @@ -837,6 +834,9 @@ beast\crypto + + beast\crypto + beast\crypto @@ -2253,12 +2253,6 @@ ripple\app\main - - ripple\app\misc - - - ripple\app\misc - ripple\app\misc @@ -2430,9 +2424,6 @@ ripple\app\paths - - ripple\app\paths\tests - ripple\app\paths @@ -3327,6 +3318,9 @@ ripple\peerfinder\tests + + ripple\protocol + ripple\protocol @@ -3348,6 +3342,9 @@ ripple\protocol + + ripple\protocol\impl + ripple\protocol\impl @@ -3447,6 +3444,9 @@ ripple\protocol\impl + + ripple\protocol\impl + ripple\protocol\impl @@ -3579,12 +3579,21 @@ ripple\protocol\tests + + ripple\protocol\tests + + + ripple\protocol + ripple\protocol ripple\protocol + + ripple\protocol + ripple\protocol diff --git a/src/ripple/app/ledger/AcceptedLedgerTx.cpp b/src/ripple/app/ledger/AcceptedLedgerTx.cpp index 373120cc1a..922b67fe42 100644 --- a/src/ripple/app/ledger/AcceptedLedgerTx.cpp +++ b/src/ripple/app/ledger/AcceptedLedgerTx.cpp @@ -24,6 +24,7 @@ #include #include #include +#include namespace ripple { @@ -83,19 +84,17 @@ void AcceptedLedgerTx::buildJson () mJson[jss::result] = transHuman (mResult); - if (!mAffected.empty ()) + if (! mAffected.empty ()) { Json::Value& affected = (mJson[jss::affected] = Json::arrayValue); - for (auto const& ra : mAffected) - { - affected.append (ra.humanAccountID ()); - } + for (auto const& account: mAffected) + affected.append (getApp().accountIDCache().toBase58(account)); } if (mTxn->getTxnType () == ttOFFER_CREATE) { - auto const account (mTxn->getSourceAccount ().getAccountID ()); - auto const amount (mTxn->getFieldAmount (sfTakerGets)); + auto const& account = mTxn->getAccountID(sfAccount); + auto const amount = mTxn->getFieldAmount (sfTakerGets); // If the offer create is not self funded then add the owner balance if (account != amount.issue ().account) diff --git a/src/ripple/app/ledger/AcceptedLedgerTx.h b/src/ripple/app/ledger/AcceptedLedgerTx.h index 557288b850..e91a9cc28e 100644 --- a/src/ripple/app/ledger/AcceptedLedgerTx.h +++ b/src/ripple/app/ledger/AcceptedLedgerTx.h @@ -21,6 +21,7 @@ #define RIPPLE_APP_LEDGER_ACCEPTEDLEDGERTX_H_INCLUDED #include +#include namespace ripple { @@ -63,7 +64,9 @@ public: { return mMeta; } - std::vector const& getAffected () const + + boost::container::flat_set const& + getAffected() const { return mAffected; } @@ -104,7 +107,7 @@ private: STTx::pointer mTxn; TransactionMetaSet::pointer mMeta; TER mResult; - std::vector mAffected; + boost::container::flat_set mAffected; Blob mRawMeta; Json::Value mJson; diff --git a/src/ripple/app/ledger/Ledger.cpp b/src/ripple/app/ledger/Ledger.cpp index 0a63169b59..f8efc70492 100644 --- a/src/ripple/app/ledger/Ledger.cpp +++ b/src/ripple/app/ledger/Ledger.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -65,7 +66,7 @@ makeGenesisAccount (AccountID const& id, std::shared_ptr sle = std::make_shared(ltACCOUNT_ROOT, getAccountRootIndex(id)); - sle->setFieldAccount (sfAccount, id); + sle->setAccountID (sfAccount, id); sle->setFieldAmount (sfBalance, drops); sle->setFieldU32 (sfSequence, 1); return sle; @@ -76,8 +77,10 @@ makeGenesisAccount (AccountID const& id, // other constructor with appropriate parameters, and // then create the master account / flush dirty. // -Ledger::Ledger (RippleAddress const& masterID, std::uint64_t startAmount) - : mTotCoins (startAmount) +// VFALCO Use `AnyPublicKey masterPublicKey` +Ledger::Ledger (RippleAddress const& masterPublicKey, + std::uint64_t balanceInDrops) + : mTotCoins (balanceInDrops) , seq_ (1) // First Ledger , mCloseTime (0) , mParentCloseTime (0) @@ -90,7 +93,8 @@ Ledger::Ledger (RippleAddress const& masterID, std::uint64_t startAmount) getApp().family(), deprecatedLogs().journal("SHAMap"))) { auto sle = makeGenesisAccount( - masterID.getAccountID(), startAmount); + calcAccountID(masterPublicKey), + balanceInDrops); WriteLog (lsTRACE, Ledger) << "root account: " << sle->getJson(0); unchecked_insert(std::move(sle)); @@ -603,7 +607,7 @@ bool Ledger::saveValidatedLedger (bool current) sql.reserve (sql.length () + (accts.size () * 128)); bool first = true; - for (auto const& it : accts) + for (auto const& account : accts) { if (!first) sql += ", ('"; @@ -615,7 +619,7 @@ bool Ledger::saveValidatedLedger (bool current) sql += txnId; sql += "','"; - sql += it.humanAccountID (); + sql += getApp().accountIDCache().toBase58(account); sql += "',"; sql += ledgerSeq; sql += ","; @@ -703,7 +707,6 @@ loadLedgerHelper(std::string const& sqlSuffix) if (!db->got_data ()) { - std::stringstream s; WriteLog (lsINFO, Ledger) << "Ledger not found: " << sqlSuffix; return std::make_tuple (Ledger::pointer (), ledgerSeq, ledgerHash); } @@ -1236,7 +1239,7 @@ bool Ledger::pendSaveValidated (bool isSynchronous, bool isCurrent) void ownerDirDescriber (SLE::ref sle, bool, AccountID const& owner) { - sle->setFieldAccount (sfOwner, owner); + sle->setAccountID (sfOwner, owner); } void @@ -1362,31 +1365,6 @@ cachedRead (Ledger const& ledger, uint256 const& key, return sle; } -AccountState::pointer -getAccountState (Ledger const& ledger, - RippleAddress const& accountID, - SLECache& cache) -{ - auto const sle = cachedRead (ledger, - getAccountRootIndex(accountID.getAccountID()), - cache); - if (!sle) - { - // VFALCO Do we really need to log here? - WriteLog (lsDEBUG, Ledger) << "Ledger:getAccountState:" << - " not found: " << accountID.humanAccountID () << - ": " << to_string (getAccountRootIndex (accountID)); - - return {}; - } - - // VFALCO Does this ever really happen? - if (sle->getType () != ltACCOUNT_ROOT) - return {}; - - return std::make_shared(sle, accountID); -} - boost::optional hashOfSeq (Ledger& ledger, LedgerIndex seq, SLECache& cache, beast::Journal journal) @@ -1459,6 +1437,35 @@ hashOfSeq (Ledger& ledger, LedgerIndex seq, return boost::none; } +void +injectSLE (Json::Value& jv, + SLE const& sle) +{ + jv = sle.getJson(0); + if (sle.getType() == ltACCOUNT_ROOT) + { + if (sle.isFieldPresent(sfEmailHash)) + { + auto const& hash = + sle.getFieldH128(sfEmailHash); + Blob const b (hash.begin(), hash.end()); + std::string md5 = strHex(b); + boost::to_lower(md5); + // VFALCO TODO Give a name and move this constant + // to a more visible location. Also + // shouldn't this be https? + jv[jss::urlgravatar] = str(boost::format( + "http://www.gravatar.com/avatar/%s") % md5); + } + } + else + { + jv[jss::Invalid] = true; + } +} + +//------------------------------------------------------------------------------ + bool getMetaHex (Ledger const& ledger, uint256 const& transID, std::string& hex) diff --git a/src/ripple/app/ledger/Ledger.h b/src/ripple/app/ledger/Ledger.h index faebf53e50..212044d22a 100644 --- a/src/ripple/app/ledger/Ledger.h +++ b/src/ripple/app/ledger/Ledger.h @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -83,9 +82,13 @@ public: Ledger (Ledger const&) = delete; Ledger& operator= (Ledger const&) = delete; - // used for the starting bootstrap ledger - Ledger (RippleAddress const& masterID, - std::uint64_t startAmount); + /** Construct the genesis ledger. + + @param masterPublicKey The public of the account that + will hold `startAmount` XRP in drops. + */ + Ledger (RippleAddress const& masterPublicKey, + std::uint64_t balanceInDrops); // Used for ledgers loaded from JSON files Ledger (uint256 const& parentHash, uint256 const& transHash, @@ -482,14 +485,6 @@ std::shared_ptr cachedRead (Ledger const& ledger, uint256 const& key, SLECache& cache, boost::optional type = boost::none); -// DEPRECATED -// VFALCO This could return by value -// This should take AccountID parameter -AccountState::pointer -getAccountState (Ledger const& ledger, - RippleAddress const& accountID, - SLECache& cache); - /** Return the hash of a ledger by sequence. The hash is retrieved by looking up the "skip list" in the passed ledger. As the skip list is limited @@ -522,6 +517,18 @@ getCandidateLedger (LedgerIndex requested) return (requested + 255) & (~255); } +/** Inject JSON describing ledger entry + + Effects: + Adds the JSON description of `sle` to `jv`. + + If `sle` holds an account root, also adds the + urlgravatar field JSON if sfEmailHash is present. +*/ +void +injectSLE (Json::Value& jv, + SLE const& sle); + //------------------------------------------------------------------------------ // VFALCO Should this take Slice? Should id be called key or hash? Or txhash? diff --git a/src/ripple/app/ledger/MetaView.h b/src/ripple/app/ledger/MetaView.h index 8c19510042..0265b21051 100644 --- a/src/ripple/app/ledger/MetaView.h +++ b/src/ripple/app/ledger/MetaView.h @@ -232,7 +232,7 @@ private: Mods& mods); bool - threadTx (RippleAddress const& to, + threadTx (AccountID const& to, Mods& mods); bool diff --git a/src/ripple/app/ledger/impl/MetaView.cpp b/src/ripple/app/ledger/impl/MetaView.cpp index f14330568a..8f95e4395a 100644 --- a/src/ripple/app/ledger/impl/MetaView.cpp +++ b/src/ripple/app/ledger/impl/MetaView.cpp @@ -29,6 +29,7 @@ #include #include #include +#include namespace ripple { @@ -586,19 +587,21 @@ MetaView::getForMod (uint256 const& key, } bool -MetaView::threadTx (RippleAddress const& to, +MetaView::threadTx (AccountID const& to, Mods& mods) { - auto const sle = getForMod(keylet::account( - to.getAccountID()).key, mods); + auto const sle = getForMod( + keylet::account(to).key, mods); #ifdef META_DEBUG - WriteLog (lsTRACE, View) << "Thread to " << threadTo.getAccountID (); + WriteLog (lsTRACE, View) << + "Thread to " << toBase58(to); #endif + assert(sle); if (! sle) { WriteLog (lsFATAL, View) << - "Threading to non-existent account: " << to.humanAccountID (); - assert (false); + "Threading to non-existent account: " << + toBase58(to); return false; } @@ -630,21 +633,25 @@ MetaView::threadOwners(std::shared_ptr< SLE const> const& sle, Mods& mods) { // thread new or modified sle to owner or owners - if (sle->hasOneOwner()) + // VFALCO Why not isFieldPresent? + if (sle->getType() != ltACCOUNT_ROOT && + sle->getFieldIndex(sfAccount) != -1) { // thread to owner's account #ifdef META_DEBUG WriteLog (lsTRACE, View) << "Thread to single owner"; #endif - return threadTx (sle->getOwner(), mods); + return threadTx (sle->getAccountID(sfAccount), mods); } - else if (sle->hasTwoOwners ()) // thread to owner's accounts + else if (sle->getType() == ltRIPPLE_STATE) { + // thread to owner's accounts #ifdef META_DEBUG WriteLog (lsTRACE, View) << "Thread to two owners"; #endif - return threadTx(sle->getFirstOwner(), mods) && - threadTx(sle->getSecondOwner(), mods); + return + threadTx(sle->getFieldAmount(sfLowLimit).getIssuer(), mods) && + threadTx(sle->getFieldAmount(sfHighLimit).getIssuer(), mods); } return false; } diff --git a/src/ripple/app/ledger/tests/DeferredCredits.test.cpp b/src/ripple/app/ledger/tests/DeferredCredits.test.cpp index 4adf71a173..724a349271 100644 --- a/src/ripple/app/ledger/tests/DeferredCredits.test.cpp +++ b/src/ripple/app/ledger/tests/DeferredCredits.test.cpp @@ -22,6 +22,7 @@ namespace ripple { namespace test { + class DeferredCredits_test : public beast::unit_test::suite { /* @@ -152,8 +153,8 @@ class DeferredCredits_test : public beast::unit_test::suite verifyBalance (ledger, alice, Amount (50, "USD", gw1)); verifyBalance (ledger, alice, Amount (50, "USD", gw2)); - AccountID const gw1Acc (gw1.pk.getAccountID ()); - AccountID const aliceAcc (alice.pk.getAccountID ()); + AccountID const gw1Acc = calcAccountID(gw1.pk); + AccountID const aliceAcc = calcAccountID(alice.pk); ripple::Currency const usd (to_currency ("USD")); ripple::Issue const issue (usd, gw1Acc); STAmount const toCredit (issue, 30); diff --git a/src/ripple/app/ledger/tests/common_ledger.cpp b/src/ripple/app/ledger/tests/common_ledger.cpp index 81ca991f4b..dd999b184e 100644 --- a/src/ripple/app/ledger/tests/common_ledger.cpp +++ b/src/ripple/app/ledger/tests/common_ledger.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -62,7 +63,7 @@ Issuer::Issuer(TestAccount issuer) void Issuer::getJson(Json::Value& tx_json) const { - tx_json[jss::issuer] = issuer_.pk.humanAccountID(); + tx_json[jss::issuer] = toBase58(calcAccountID(issuer_.pk)); } TestAccount const& @@ -213,7 +214,7 @@ Json::Value getCommonTransactionJson(TestAccount& account) { Json::Value tx_json; - tx_json[jss::Account] = account.pk.humanAccountID(); + tx_json[jss::Account] = toBase58(calcAccountID(account.pk)); tx_json[jss::Fee] = std::to_string(10); tx_json[jss::Sequence] = ++account.sequence; return tx_json; @@ -269,7 +270,7 @@ getPaymentJson(TestAccount& from, TestAccount const& to, { Json::Value tx_json = getCommonTransactionJson(from); tx_json[jss::Amount] = amountJson; - tx_json[jss::Destination] = to.pk.humanAccountID(); + tx_json[jss::Destination] = toBase58(calcAccountID(to.pk)); tx_json[jss::TransactionType] = "Payment"; tx_json[jss::Flags] = tfUniversal; return tx_json; @@ -329,10 +330,12 @@ Ledger::pointer const& ledger, bool sign) STPathSet pathSet; STPath fullLiquidityPath; auto stDstAmount = amountFromJson(sfGeneric, amountJson); - Issue srcIssue = Issue(stDstAmount.getCurrency(), from.pk.getAccountID()); + Issue srcIssue = Issue(stDstAmount.getCurrency(), + calcAccountID(from.pk)); - auto found = findPathsForOneIssuer(cache, from.pk.getAccountID(), to.pk.getAccountID(), - srcIssue, stDstAmount, 7, 4, pathSet, fullLiquidityPath); + auto found = findPathsForOneIssuer(cache, + calcAccountID(from.pk), calcAccountID(to.pk), + srcIssue, stDstAmount, 7, 4, pathSet, fullLiquidityPath); if (!found) throw std::runtime_error( "!found"); @@ -421,7 +424,7 @@ trust(TestAccount& from, TestAccount const& issuer, Json::Value tx_json = getCommonTransactionJson(from); Json::Value& limitAmount = tx_json[jss::LimitAmount]; limitAmount[jss::currency] = currency; - limitAmount[jss::issuer] = issuer.pk.humanAccountID(); + limitAmount[jss::issuer] = toBase58(calcAccountID(issuer.pk)); limitAmount[jss::value] = std::to_string(amount); tx_json[jss::TransactionType] = "TrustSet"; tx_json[jss::Flags] = 0; // tfClearNoRipple; @@ -486,8 +489,9 @@ Json::Value findPath(Ledger::pointer ledger, TestAccount const& src, } log << "Source currencies: " << jvSrcCurrencies; - auto result = ripplePathFind(cache, src.pk, dest.pk, saDstAmount, - ledger, jvSrcCurrencies, contextPaths, level); + auto result = ripplePathFind(cache, calcAccountID(src.pk), + calcAccountID(dest.pk), saDstAmount, + ledger, jvSrcCurrencies, contextPaths, level); if(!result.first) throw std::runtime_error( "ripplePathFind find failed"); @@ -501,7 +505,7 @@ getLedgerEntryRippleState(Ledger::pointer ledger, Currency currency) { auto k = keylet::line( - account1.pk.getAccountID(), account2.pk.getAccountID(), + calcAccountID(account1.pk), calcAccountID(account2.pk), to_currency(currency.getCurrency())); if (! k.key.isNonZero()) @@ -525,7 +529,7 @@ verifyBalance(Ledger::pointer ledger, TestAccount const& account, auto high = sle->getFieldAmount(sfHighLimit); auto balance = sle->getFieldAmount(sfBalance); - if (high.getIssuer() == account.pk.getAccountID()) + if (high.getIssuer() == calcAccountID(account.pk)) { balance.negate(); } @@ -537,7 +541,7 @@ verifyBalance(Ledger::pointer ledger, TestAccount const& account, Json::Value pathNode (TestAccount const& acc) { Json::Value result; - result["account"] = acc.pk.humanAccountID(); + result["account"] = toBase58(calcAccountID(acc.pk)); result["type"] = 1; result["type_hex"] = "0000000000000001"; return result; @@ -550,7 +554,7 @@ Json::Value pathNode (OfferPathNode const& offer) result["type"] = 48; result["type_hex"] = "0000000000000030"; if (offer.issuer) - result["issuer"] = offer.issuer->pk.humanAccountID(); + result["issuer"] = toBase58(calcAccountID(offer.issuer->pk)); return result; } diff --git a/src/ripple/app/main/Application.cpp b/src/ripple/app/main/Application.cpp index 19e107f4d4..6e06b817d0 100644 --- a/src/ripple/app/main/Application.cpp +++ b/src/ripple/app/main/Application.cpp @@ -58,6 +58,7 @@ #include #include #include +#include #include #include #include @@ -259,6 +260,7 @@ public: std::unique_ptr m_shaMapStore; std::unique_ptr m_nodeStore; PendingSaves pendingSaves_; + AccountIDCache accountIDCache_; // These are not Stoppable-derived NodeCache m_tempNodeCache; @@ -334,6 +336,8 @@ public: , m_nodeStore (m_shaMapStore->makeDatabase ("NodeStore.main", 4)) + , accountIDCache_(128000) + , m_tempNodeCache ("NodeCache", 16384, 90, get_seconds_clock (), m_logs.journal("TaggedCache")) @@ -598,6 +602,12 @@ public: return pendingSaves_; } + AccountIDCache const& + accountIDCache() const override + { + return accountIDCache_; + } + Overlay& overlay () { return *m_overlay; @@ -904,7 +914,6 @@ public: m_overlay->saveValidatorKeyManifests (getWalletDB ()); - RippleAddress::clearCache (); stopped (); } @@ -1038,11 +1047,12 @@ void ApplicationImp::startNewLedger () // Print enough information to be able to claim root account. m_journal.info << "Root master seed: " << rootSeedMaster.humanSeed (); - m_journal.info << "Root account: " << rootAddress.humanAccountID (); + m_journal.info << "Root account: " << toBase58(calcAccountID(rootAddress)); { Ledger::pointer firstLedger = std::make_shared (rootAddress, SYSTEM_CURRENCY_START); - assert (firstLedger->exists(keylet::account(rootAddress.getAccountID()))); + assert (firstLedger->exists(keylet::account( + calcAccountID(rootAddress)))); // TODO(david): Add any default amendments // TODO(david): Set default fee/reserve firstLedger->getHash(); // updates the hash @@ -1054,7 +1064,8 @@ void ApplicationImp::startNewLedger () secondLedger->setClosed (); secondLedger->setAccepted (); m_ledgerMaster->pushLedger (secondLedger, std::make_shared (true, std::ref (*secondLedger))); - assert (secondLedger->exists(keylet::account(rootAddress.getAccountID()))); + assert (secondLedger->exists(keylet::account( + calcAccountID(rootAddress)))); m_networkOPs->setLastCloseTime (secondLedger->getCloseTimeNC ()); } } diff --git a/src/ripple/app/main/Application.h b/src/ripple/app/main/Application.h index e46764f78a..2490fab0fe 100644 --- a/src/ripple/app/main/Application.h +++ b/src/ripple/app/main/Application.h @@ -27,7 +27,7 @@ #include #include // #include - + namespace boost { namespace asio { class io_service; } } namespace ripple { @@ -58,6 +58,7 @@ class OrderBookDB; class Overlay; class PathRequests; class PendingSaves; +class AccountIDCache; class STLedgerEntry; class TransactionMaster; class Validations; @@ -116,6 +117,7 @@ public: virtual PathRequests& getPathRequests () = 0; virtual SHAMapStore& getSHAMapStore () = 0; virtual PendingSaves& pendingSaves() = 0; + virtual AccountIDCache const& accountIDCache() const = 0; virtual DatabaseCon& getTxnDB () = 0; virtual DatabaseCon& getLedgerDB () = 0; diff --git a/src/ripple/app/misc/AccountState.cpp b/src/ripple/app/misc/AccountState.cpp deleted file mode 100644 index 471643a7e5..0000000000 --- a/src/ripple/app/misc/AccountState.cpp +++ /dev/null @@ -1,73 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2012, 2013 Ripple Labs Inc. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace ripple { - -AccountState::AccountState (std::shared_ptr sle, - RippleAddress const& naAccountID) - : mLedgerEntry (sle) -{ - if (! mLedgerEntry) - return; - - if (mLedgerEntry->getType () != ltACCOUNT_ROOT) - return; - - mValid = true; -} - -// VFALCO TODO Make this a generic utility function of some container class -// -std::string AccountState::createGravatarUrl (uint128 uEmailHash) -{ - Blob vucMD5 (uEmailHash.begin (), uEmailHash.end ()); - std::string strMD5Lower = strHex (vucMD5); - boost::to_lower (strMD5Lower); - - // VFALCO TODO Give a name and move this constant to a more visible location. - // Also shouldn't this be https? - return str (boost::format ("http://www.gravatar.com/avatar/%s") % strMD5Lower); -} - -void AccountState::addJson (Json::Value& val) -{ - val = mLedgerEntry->getJson (0); - - if (mValid) - { - if (mLedgerEntry->isFieldPresent (sfEmailHash)) - val[jss::urlgravatar] = createGravatarUrl (mLedgerEntry->getFieldH128 (sfEmailHash)); - } - else - { - val[jss::Invalid] = true; - } -} - -} // ripple diff --git a/src/ripple/app/misc/AmendmentTableImpl.cpp b/src/ripple/app/misc/AmendmentTableImpl.cpp index dd68446de5..eca3752cc1 100644 --- a/src/ripple/app/misc/AmendmentTableImpl.cpp +++ b/src/ripple/app/misc/AmendmentTableImpl.cpp @@ -557,7 +557,7 @@ AmendmentTableImpl::doVoting (Ledger::ref lastClosedLedger, // Create the transaction to enable the amendment STTx trans (ttAMENDMENT); - trans.setFieldAccount (sfAccount, AccountID ()); + trans.setAccountID (sfAccount, AccountID ()); trans.setFieldH256 (sfAmendment, uAmendment); uint256 txID = trans.getTransactionID (); diff --git a/src/ripple/app/misc/CanonicalTXSet.cpp b/src/ripple/app/misc/CanonicalTXSet.cpp index f5f0cfa353..8fcce4d9cd 100644 --- a/src/ripple/app/misc/CanonicalTXSet.cpp +++ b/src/ripple/app/misc/CanonicalTXSet.cpp @@ -78,7 +78,7 @@ void CanonicalTXSet::push_back (STTx::ref txn) { uint256 effectiveAccount = mSetHash; - effectiveAccount ^= to256 (txn->getSourceAccount ().getAccountID ()); + effectiveAccount ^= to256 (txn->getAccountID(sfAccount)); mMap.insert (std::make_pair ( Key (effectiveAccount, txn->getSequence (), txn->getTransactionID ()), diff --git a/src/ripple/app/misc/FeeVoteImpl.cpp b/src/ripple/app/misc/FeeVoteImpl.cpp index d825f92587..e08db46311 100644 --- a/src/ripple/app/misc/FeeVoteImpl.cpp +++ b/src/ripple/app/misc/FeeVoteImpl.cpp @@ -214,7 +214,7 @@ FeeVoteImpl::doVoting (Ledger::ref lastClosedLedger, "/" << incReserve; STTx trans (ttFEE); - trans.setFieldAccount (sfAccount, AccountID ()); + trans.setAccountID (sfAccount, AccountID ()); trans.setFieldU64 (sfBaseFee, baseFee); trans.setFieldU32 (sfReferenceFeeUnits, 10); trans.setFieldU32 (sfReserveBase, baseReserve); diff --git a/src/ripple/app/misc/NetworkOPs.cpp b/src/ripple/app/misc/NetworkOPs.cpp index f48211d918..4a110aff7d 100644 --- a/src/ripple/app/misc/NetworkOPs.cpp +++ b/src/ripple/app/misc/NetworkOPs.cpp @@ -313,7 +313,7 @@ public: // Json::Value getOwnerInfo ( - Ledger::pointer lpLedger, RippleAddress const& naAccount) override; + Ledger::pointer lpLedger, AccountID const& account) override; // // Book functions. @@ -454,7 +454,7 @@ public: //Helper function to generate SQL query to get transactions. std::string transactionsSQL ( - std::string selection, RippleAddress const& account, + std::string selection, AccountID const& account, std::int32_t minLedger, std::int32_t maxLedger, bool descending, std::uint32_t offset, int limit, bool binary, bool count, bool bAdmin) override; @@ -462,12 +462,12 @@ public: // Client information retrieval functions. using NetworkOPs::AccountTxs; AccountTxs getAccountTxs ( - RippleAddress const& account, + AccountID const& account, std::int32_t minLedger, std::int32_t maxLedger, bool descending, std::uint32_t offset, int limit, bool bAdmin) override; AccountTxs getTxsAccount ( - RippleAddress const& account, std::int32_t minLedger, + AccountID const& account, std::int32_t minLedger, std::int32_t maxLedger, bool forward, Json::Value& token, int limit, bool bAdmin) override; @@ -476,19 +476,16 @@ public: MetaTxsList getAccountTxsB ( - RippleAddress const& account, std::int32_t minLedger, + AccountID const& account, std::int32_t minLedger, std::int32_t maxLedger, bool descending, std::uint32_t offset, int limit, bool bAdmin) override; MetaTxsList getTxsAccountB ( - RippleAddress const& account, std::int32_t minLedger, + AccountID const& account, std::int32_t minLedger, std::int32_t maxLedger, bool forward, Json::Value& token, int limit, bool bAdmin) override; - std::vector getLedgerAffectedAccounts ( - std::uint32_t ledgerSeq) override; - // // Monitoring: publisher side. // @@ -502,17 +499,17 @@ public: // void subAccount ( InfoSub::ref ispListener, - const hash_set& vnaAccountIDs, bool rt) override; + hash_set const& vnaAccountIDs, bool rt) override; void unsubAccount ( InfoSub::ref ispListener, - const hash_set& vnaAccountIDs, + hash_set const& vnaAccountIDs, bool rt); // Just remove the subscription from the tracking // not from the InfoSub. Needed for InfoSub destruction void unsubAccountInternal ( std::uint64_t seq, - const hash_set& vnaAccountIDs, + hash_set const& vnaAccountIDs, bool rt); bool subLedger (InfoSub::ref ispListener, Json::Value& jvResult) override; @@ -562,9 +559,6 @@ private: Ledger::ref lpCurrent); bool haveConsensusObject (); - Json::Value pubBootstrapAccountInfo ( - Ledger::ref lpAccepted, RippleAddress const& naAccountID); - void pubValidatedTransaction ( Ledger::ref alAccepted, const AcceptedLedgerTx& alTransaction); void pubAccountTransaction ( @@ -1311,10 +1305,10 @@ STVector256 NetworkOPsImp::getDirNodeInfo ( // Json::Value NetworkOPsImp::getOwnerInfo ( - Ledger::pointer lpLedger, RippleAddress const& naAccount) + Ledger::pointer lpLedger, AccountID const& account) { Json::Value jvObjects (Json::objectValue); - auto uRootIndex = getOwnerDirIndex (naAccount.getAccountID ()); + auto uRootIndex = getOwnerDirIndex (account); auto sleNode = cachedRead(*lpLedger, uRootIndex, getApp().getSLECache(), ltDIR_NODE); if (sleNode) @@ -1863,7 +1857,7 @@ void NetworkOPsImp::setMode (OperatingMode om) std::string NetworkOPsImp::transactionsSQL ( - std::string selection, RippleAddress const& account, + std::string selection, AccountID const& account, std::int32_t minLedger, std::int32_t maxLedger, bool descending, std::uint32_t offset, int limit, bool binary, bool count, bool bAdmin) @@ -1915,7 +1909,7 @@ NetworkOPsImp::transactionsSQL ( "SELECT %s FROM AccountTransactions " "WHERE Account = '%s' %s %s LIMIT %u, %u;") % selection - % account.humanAccountID () + % getApp().accountIDCache().toBase58(account) % maxClause % minClause % beast::lexicalCastThrow (offset) @@ -1932,7 +1926,7 @@ NetworkOPsImp::transactionsSQL ( "AccountTransactions.TxnSeq %s, AccountTransactions.TransID %s " "LIMIT %u, %u;") % selection - % account.humanAccountID () + % getApp().accountIDCache().toBase58(account) % maxClause % minClause % (descending ? "DESC" : "ASC") @@ -1946,7 +1940,7 @@ NetworkOPsImp::transactionsSQL ( } NetworkOPs::AccountTxs NetworkOPsImp::getAccountTxs ( - RippleAddress const& account, + AccountID const& account, std::int32_t minLedger, std::int32_t maxLedger, bool descending, std::uint32_t offset, int limit, bool bAdmin) { @@ -2009,7 +2003,7 @@ NetworkOPs::AccountTxs NetworkOPsImp::getAccountTxs ( } std::vector NetworkOPsImp::getAccountTxsB ( - RippleAddress const& account, + AccountID const& account, std::int32_t minLedger, std::int32_t maxLedger, bool descending, std::uint32_t offset, int limit, bool bAdmin) { @@ -2059,7 +2053,7 @@ std::vector NetworkOPsImp::getAccountTxsB ( NetworkOPsImp::AccountTxs NetworkOPsImp::getTxsAccount ( - RippleAddress const& account, std::int32_t minLedger, + AccountID const& account, std::int32_t minLedger, std::int32_t maxLedger, bool forward, Json::Value& token, int limit, bool bAdmin) { @@ -2084,7 +2078,7 @@ NetworkOPsImp::getTxsAccount ( NetworkOPsImp::MetaTxsList NetworkOPsImp::getTxsAccountB ( - RippleAddress const& account, std::int32_t minLedger, + AccountID const& account, std::int32_t minLedger, std::int32_t maxLedger, bool forward, Json::Value& token, int limit, bool bAdmin) { @@ -2106,36 +2100,6 @@ NetworkOPsImp::getTxsAccountB ( return ret; } -std::vector -NetworkOPsImp::getLedgerAffectedAccounts (std::uint32_t ledgerSeq) -{ - std::vector accounts; - std::string sql = str (boost::format ( - "SELECT DISTINCT Account FROM AccountTransactions " - "INDEXED BY AcctLgrIndex WHERE LedgerSeq = '%u';") - % ledgerSeq); - RippleAddress acct; - { - auto db = getApp().getTxnDB ().checkoutDb (); - soci::blob accountBlob(*db); - soci::indicator bi; - soci::statement st = (db->prepare << sql, soci::into(accountBlob, bi)); - st.execute (); - std::string accountStr; - while (st.fetch ()) - { - if (soci::i_ok == bi) - convert (accountBlob, accountStr); - else - accountStr.clear (); - - if (acct.setAccountID (accountStr)) - accounts.push_back (acct); - } - } - return accounts; -} - bool NetworkOPsImp::recvValidation ( STValidation::ref val, std::string const& source) { @@ -2336,26 +2300,6 @@ Json::Value NetworkOPsImp::getLedgerFetchInfo () return getApp().getInboundLedgers().getInfo(); } -// -// Monitoring: publisher side -// - -Json::Value NetworkOPsImp::pubBootstrapAccountInfo ( - Ledger::ref lpAccepted, RippleAddress const& naAccountID) -{ - Json::Value jvObj (Json::objectValue); - - jvObj[jss::type] = "accountInfoBootstrap"; - jvObj[jss::account] = naAccountID.humanAccountID (); - jvObj[jss::owner] = getOwnerInfo (lpAccepted, naAccountID); - jvObj[jss::ledger_index] = lpAccepted->getLedgerSeq (); - jvObj[jss::ledger_hash] = to_string (lpAccepted->getHash ()); - jvObj[jss::ledger_time] - = Json::Value::UInt (utFromSeconds (lpAccepted->getCloseTimeNC ())); - - return jvObj; -} - void NetworkOPsImp::pubProposedTransaction ( Ledger::ref lpCurrent, STTx::ref stTxn, TER terResult) { @@ -2492,8 +2436,8 @@ Json::Value NetworkOPsImp::transJson( if (stTxn.getTxnType() == ttOFFER_CREATE) { - auto const account (stTxn.getSourceAccount ().getAccountID ()); - auto const amount (stTxn.getFieldAmount (sfTakerGets)); + auto const account = stTxn.getAccountID(sfAccount); + auto const amount = stTxn.getFieldAmount (sfTakerGets); // If the offer create is not self funded then add the owner balance if (account != amount.issue ().account) @@ -2571,7 +2515,7 @@ void NetworkOPsImp::pubAccountTransaction ( for (auto const& affectedAccount: alTx.getAffected ()) { auto simiIt - = mSubRTAccount.find (affectedAccount.getAccountID ()); + = mSubRTAccount.find (affectedAccount); if (simiIt != mSubRTAccount.end ()) { auto it = simiIt->second.begin (); @@ -2593,7 +2537,7 @@ void NetworkOPsImp::pubAccountTransaction ( if (bAccepted) { - simiIt = mSubAccount.find (affectedAccount.getAccountID ()); + simiIt = mSubAccount.find (affectedAccount); if (simiIt != mSubAccount.end ()) { @@ -2643,14 +2587,14 @@ void NetworkOPsImp::pubAccountTransaction ( void NetworkOPsImp::subAccount ( InfoSub::ref isrListener, - const hash_set& vnaAccountIDs, bool rt) + hash_set const& vnaAccountIDs, bool rt) { SubInfoMapType& subMap = rt ? mSubRTAccount : mSubAccount; for (auto const& naAccountID : vnaAccountIDs) { - m_journal.trace << "subAccount:" - " account: " << naAccountID.humanAccountID (); + if (m_journal.trace) m_journal.trace << + "subAccount: account: " << toBase58(naAccountID); isrListener->insertSubAccountInfo (naAccountID, rt); } @@ -2659,14 +2603,15 @@ void NetworkOPsImp::subAccount ( for (auto const& naAccountID : vnaAccountIDs) { - auto simIterator = subMap.find (naAccountID.getAccountID ()); + auto simIterator = subMap.find (naAccountID); if (simIterator == subMap.end ()) { // Not found, note that account has a new single listner. SubMapType usisElement; usisElement[isrListener->getSeq ()] = isrListener; - subMap.insert (simIterator, make_pair (naAccountID.getAccountID (), - usisElement)); + // VFALCO NOTE This is making a needless copy of naAccountID + subMap.insert (simIterator, + make_pair(naAccountID, usisElement)); } else { @@ -2678,7 +2623,7 @@ void NetworkOPsImp::subAccount ( void NetworkOPsImp::unsubAccount ( InfoSub::ref isrListener, - hash_set const& vnaAccountIDs, + hash_set const& vnaAccountIDs, bool rt) { for (auto const& naAccountID : vnaAccountIDs) @@ -2693,7 +2638,7 @@ void NetworkOPsImp::unsubAccount ( void NetworkOPsImp::unsubAccountInternal ( std::uint64_t uSeq, - hash_set const& vnaAccountIDs, + hash_set const& vnaAccountIDs, bool rt) { ScopedLockType sl (mSubLock); @@ -2702,7 +2647,7 @@ void NetworkOPsImp::unsubAccountInternal ( for (auto const& naAccountID : vnaAccountIDs) { - auto simIterator = subMap.find (naAccountID.getAccountID ()); + auto simIterator = subMap.find (naAccountID); if (simIterator != subMap.end ()) { @@ -2983,7 +2928,7 @@ void NetworkOPsImp::getBookPage ( if (sleOffer) { auto const uOfferOwnerID = - sleOffer->getFieldAccount160 (sfAccount); + sleOffer->getAccountID (sfAccount); auto const& saTakerGets = sleOffer->getFieldAmount (sfTakerGets); auto const& saTakerPays = @@ -3154,7 +3099,7 @@ void NetworkOPsImp::getBookPage ( SLE::pointer sleOffer = obIterator.getCurrentOffer(); if (sleOffer) { - auto const uOfferOwnerID = sleOffer->getFieldAccount160 (sfAccount); + auto const uOfferOwnerID = sleOffer->getAccountID (sfAccount); auto const& saTakerGets = sleOffer->getFieldAmount (sfTakerGets); auto const& saTakerPays = sleOffer->getFieldAmount (sfTakerPays); STAmount saDirRate = obIterator.getCurrentRate (); diff --git a/src/ripple/app/misc/NetworkOPs.h b/src/ripple/app/misc/NetworkOPs.h index 961f8319ed..3ce1012ac8 100644 --- a/src/ripple/app/misc/NetworkOPs.h +++ b/src/ripple/app/misc/NetworkOPs.h @@ -190,7 +190,7 @@ public: // virtual Json::Value getOwnerInfo (Ledger::pointer lpLedger, - RippleAddress const& naAccount) = 0; + AccountID const& account) = 0; //-------------------------------------------------------------------------- // @@ -286,7 +286,7 @@ public: //Helper function to generate SQL query to get transactions virtual std::string transactionsSQL (std::string selection, - RippleAddress const& account, std::int32_t minLedger, std::int32_t maxLedger, + AccountID const& account, std::int32_t minLedger, std::int32_t maxLedger, bool descending, std::uint32_t offset, int limit, bool binary, bool count, bool bAdmin) = 0; @@ -295,29 +295,26 @@ public: using AccountTxs = std::vector; virtual AccountTxs getAccountTxs ( - RippleAddress const& account, + AccountID const& account, std::int32_t minLedger, std::int32_t maxLedger, bool descending, std::uint32_t offset, int limit, bool bAdmin) = 0; virtual AccountTxs getTxsAccount ( - RippleAddress const& account, + AccountID const& account, std::int32_t minLedger, std::int32_t maxLedger, bool forward, Json::Value& token, int limit, bool bAdmin) = 0; using txnMetaLedgerType = std::tuple; using MetaTxsList = std::vector; - virtual MetaTxsList getAccountTxsB (RippleAddress const& account, + virtual MetaTxsList getAccountTxsB (AccountID const& account, std::int32_t minLedger, std::int32_t maxLedger, bool descending, std::uint32_t offset, int limit, bool bAdmin) = 0; - virtual MetaTxsList getTxsAccountB (RippleAddress const& account, + virtual MetaTxsList getTxsAccountB (AccountID const& account, std::int32_t minLedger, std::int32_t maxLedger, bool forward, Json::Value& token, int limit, bool bAdmin) = 0; - virtual std::vector getLedgerAffectedAccounts ( - std::uint32_t ledgerSeq) = 0; - //-------------------------------------------------------------------------- // // Monitoring: publisher side diff --git a/src/ripple/app/misc/UniqueNodeList.cpp b/src/ripple/app/misc/UniqueNodeList.cpp index 60887e7aad..5e489855ec 100644 --- a/src/ripple/app/misc/UniqueNodeList.cpp +++ b/src/ripple/app/misc/UniqueNodeList.cpp @@ -932,7 +932,7 @@ Json::Value UniqueNodeListImp::getUnlJson() { Json::Value node (Json::objectValue); - node["publicKey"] = encodeCredential (key.first, VER_NODE_PUBLIC); + node["publicKey"] = encodeCredential (key.first, TOKEN_NODE_PUBLIC); node["comment"] = key.second; ret.append (node); diff --git a/src/ripple/app/misc/impl/AccountTxPaging.cpp b/src/ripple/app/misc/impl/AccountTxPaging.cpp index e8293dee4b..bda038e216 100644 --- a/src/ripple/app/misc/impl/AccountTxPaging.cpp +++ b/src/ripple/app/misc/impl/AccountTxPaging.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include // #include @@ -67,7 +68,7 @@ accountTxPage ( std::string const&, Blob const&, Blob const&)> const& onTransaction, - RippleAddress const& account, + AccountID const& account, std::int32_t minLedger, std::int32_t maxLedger, bool forward, @@ -132,7 +133,7 @@ accountTxPage ( ORDER BY AccountTransactions.LedgerSeq ASC, AccountTransactions.TxnSeq ASC LIMIT %u;)")) - % account.humanAccountID() + % getApp().accountIDCache().toBase58(account) % minLedger % maxLedger % queryLimit); @@ -149,7 +150,7 @@ accountTxPage ( AccountTransactions.TxnSeq ASC LIMIT %u; )")) - % account.humanAccountID() + % getApp().accountIDCache().toBase58(account) % (findLedger + 1) % maxLedger % findLedger @@ -164,7 +165,7 @@ accountTxPage ( ORDER BY AccountTransactions.LedgerSeq DESC, AccountTransactions.TxnSeq DESC LIMIT %u;)")) - % account.humanAccountID() + % getApp().accountIDCache().toBase58(account) % minLedger % maxLedger % queryLimit); @@ -179,7 +180,7 @@ accountTxPage ( ORDER BY AccountTransactions.LedgerSeq DESC, AccountTransactions.TxnSeq DESC LIMIT %u;)")) - % account.humanAccountID() + % getApp().accountIDCache().toBase58(account) % minLedger % (findLedger - 1) % findLedger diff --git a/src/ripple/app/misc/impl/AccountTxPaging.h b/src/ripple/app/misc/impl/AccountTxPaging.h index 3707baf878..92a574c5f9 100644 --- a/src/ripple/app/misc/impl/AccountTxPaging.h +++ b/src/ripple/app/misc/impl/AccountTxPaging.h @@ -50,7 +50,7 @@ accountTxPage ( std::string const&, Blob const&, Blob const&)> const&, - RippleAddress const& account, + AccountID const& account, std::int32_t minLedger, std::int32_t maxLedger, bool forward, diff --git a/src/ripple/app/misc/tests/AccountTxPaging.test.cpp b/src/ripple/app/misc/tests/AccountTxPaging.test.cpp index 45369dd072..6fb5b67216 100644 --- a/src/ripple/app/misc/tests/AccountTxPaging.test.cpp +++ b/src/ripple/app/misc/tests/AccountTxPaging.test.cpp @@ -18,6 +18,7 @@ //============================================================================== #include #include +#include #include // #include #include @@ -29,7 +30,7 @@ struct AccountTxPaging_test : beast::unit_test::suite { std::unique_ptr db_; NetworkOPs::AccountTxs txs_; - RippleAddress account_; + AccountID account_; void run() override @@ -51,7 +52,8 @@ struct AccountTxPaging_test : beast::unit_test::suite db_ = std::make_unique ( dbConf, "account-tx-transactions.db", nullptr, 0); - account_.setAccountID("rfu6L5p3azwPzQZsbTafuVk884N9YoKvVG"); + account_ = *parseBase58( + "rfu6L5p3azwPzQZsbTafuVk884N9YoKvVG"); testAccountTxPaging(); } diff --git a/src/ripple/app/paths/AccountCurrencies.cpp b/src/ripple/app/paths/AccountCurrencies.cpp index 39026f6e9d..6f4d612d3a 100644 --- a/src/ripple/app/paths/AccountCurrencies.cpp +++ b/src/ripple/app/paths/AccountCurrencies.cpp @@ -22,19 +22,19 @@ namespace ripple { -CurrencySet accountSourceCurrencies ( - RippleAddress const& raAccountID, +hash_set accountSourceCurrencies ( + AccountID const& account, RippleLineCache::ref lrCache, bool includeXRP) { - CurrencySet currencies; + hash_set currencies; // YYY Only bother if they are above reserve if (includeXRP) currencies.insert (xrpCurrency()); // List of ripple lines. - auto& rippleLines (lrCache->getRippleLines (raAccountID.getAccountID ())); + auto& rippleLines = lrCache->getRippleLines (account); for (auto const& item : rippleLines) { @@ -60,19 +60,19 @@ CurrencySet accountSourceCurrencies ( return currencies; } -CurrencySet accountDestCurrencies ( - RippleAddress const& raAccountID, +hash_set accountDestCurrencies ( + AccountID const& account, RippleLineCache::ref lrCache, bool includeXRP) { - CurrencySet currencies; + hash_set currencies; if (includeXRP) currencies.insert (xrpCurrency()); // Even if account doesn't exist // List of ripple lines. - auto& rippleLines (lrCache->getRippleLines (raAccountID.getAccountID ())); + auto& rippleLines = lrCache->getRippleLines (account); for (auto const& item : rippleLines) { diff --git a/src/ripple/app/paths/AccountCurrencies.h b/src/ripple/app/paths/AccountCurrencies.h index 7d082d4f00..8f415f3ecf 100644 --- a/src/ripple/app/paths/AccountCurrencies.h +++ b/src/ripple/app/paths/AccountCurrencies.h @@ -21,18 +21,21 @@ #define RIPPLE_APP_PATHS_ACCOUNTCURRENCIES_H_INCLUDED #include +#include namespace ripple { -CurrencySet accountDestCurrencies - (RippleAddress const& raAccountID, - RippleLineCache::ref cache, - bool includeXRP); +hash_set +accountDestCurrencies( + AccountID const& account, + RippleLineCache::ref cache, + bool includeXRP); -CurrencySet accountSourceCurrencies - (RippleAddress const& raAccountID, - RippleLineCache::ref lrLedger, - bool includeXRP); +hash_set +accountSourceCurrencies( + AccountID const& account, + RippleLineCache::ref lrLedger, + bool includeXRP); } // ripple diff --git a/src/ripple/app/paths/PathRequest.cpp b/src/ripple/app/paths/PathRequest.cpp index e5a19352da..092369613f 100644 --- a/src/ripple/app/paths/PathRequest.cpp +++ b/src/ripple/app/paths/PathRequest.cpp @@ -143,63 +143,62 @@ void PathRequest::updateComplete () bool PathRequest::isValid (RippleLineCache::ref crCache) { ScopedLockType sl (mLock); - bValid = raSrcAccount.isSet () && raDstAccount.isSet () && + bValid = raSrcAccount && raDstAccount && saDstAmount > zero; Ledger::pointer lrLedger = crCache->getLedger (); if (bValid) { - auto asSrc = getAccountState( - *crCache->getLedger(), raSrcAccount, - getApp().getSLECache()); - - if (!asSrc) + if (! crCache->getLedger()->exists( + keylet::account(*raSrcAccount))) { // no source account bValid = false; jvStatus = rpcError (rpcSRC_ACT_NOT_FOUND); } + } + + if (bValid) + { + auto const sleDest = cachedRead(*crCache->getLedger(), + keylet::account(*raDstAccount).key, + getApp().getSLECache(), ltACCOUNT_ROOT); + + Json::Value& jvDestCur = + (jvStatus[jss::destination_currencies] = Json::arrayValue); + + if (!sleDest) + { + // no destination account + jvDestCur.append (Json::Value ("XRP")); + + if (!saDstAmount.native ()) + { + // only XRP can be send to a non-existent account + bValid = false; + jvStatus = rpcError (rpcACT_NOT_FOUND); + } + else if (saDstAmount < STAmount (lrLedger->getReserve (0))) + { + // payment must meet reserve + bValid = false; + jvStatus = rpcError (rpcDST_AMT_MALFORMED); + } + } else { - auto asDst = getAccountState(*lrLedger, - raDstAccount, getApp().getSLECache()); + bool const disallowXRP ( + sleDest->getFlags() & lsfDisallowXRP); - Json::Value& jvDestCur = - (jvStatus[jss::destination_currencies] = Json::arrayValue); + auto usDestCurrID = accountDestCurrencies ( + *raDstAccount, crCache, !disallowXRP); - if (!asDst) - { - // no destination account - jvDestCur.append (Json::Value ("XRP")); + for (auto const& currency : usDestCurrID) + jvDestCur.append (to_string (currency)); - if (!saDstAmount.native ()) - { - // only XRP can be send to a non-existent account - bValid = false; - jvStatus = rpcError (rpcACT_NOT_FOUND); - } - else if (saDstAmount < STAmount (lrLedger->getReserve (0))) - { - // payment must meet reserve - bValid = false; - jvStatus = rpcError (rpcDST_AMT_MALFORMED); - } - } - else - { - bool const disallowXRP ( - asDst->sle().getFlags() & lsfDisallowXRP); - - auto usDestCurrID = accountDestCurrencies ( - raDstAccount, crCache, !disallowXRP); - - for (auto const& currency : usDestCurrID) - jvDestCur.append (to_string (currency)); - - jvStatus["destination_tag"] = - (asDst->sle().getFlags () & lsfRequireDestTag) - != 0; - } + jvStatus["destination_tag"] = + (sleDest->getFlags () & lsfRequireDestTag) + != 0; } } @@ -240,7 +239,7 @@ Json::Value PathRequest::doCreate ( if (bValid) { m_journal.debug << iIdentifier - << " valid: " << raSrcAccount.humanAccountID (); + << " valid: " << toBase58(*raSrcAccount); m_journal.debug << iIdentifier << " Deliver: " << saDstAmount.getFullText (); } @@ -260,7 +259,9 @@ int PathRequest::parseJson (Json::Value const& jvParams, bool complete) if (jvParams.isMember (jss::source_account)) { - if (!raSrcAccount.setAccountID (jvParams[jss::source_account].asString ())) + raSrcAccount = parseBase58( + jvParams[jss::source_account].asString()); + if (! raSrcAccount) { jvStatus = rpcError (rpcSRC_ACT_MALFORMED); return PFR_PJ_INVALID; @@ -274,7 +275,9 @@ int PathRequest::parseJson (Json::Value const& jvParams, bool complete) if (jvParams.isMember (jss::destination_account)) { - if (!raDstAccount.setAccountID (jvParams[jss::destination_account].asString ())) + raDstAccount = parseBase58( + jvParams[jss::destination_account].asString()); + if (! raDstAccount) { jvStatus = rpcError (rpcDST_ACT_MALFORMED); return PFR_PJ_INVALID; @@ -344,7 +347,7 @@ int PathRequest::parseJson (Json::Value const& jvParams, bool complete) if (uCur.isNonZero() && uIss.isZero()) { - uIss = raSrcAccount.getAccountID(); + uIss = *raSrcAccount; } sciSourceCurrencies.insert ({uCur, uIss}); @@ -390,8 +393,8 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast) if (sourceCurrencies.empty ()) { auto usCurrencies = - accountSourceCurrencies (raSrcAccount, cache, true); - bool sameAccount = raSrcAccount == raDstAccount; + accountSourceCurrencies (*raSrcAccount, cache, true); + bool sameAccount = *raSrcAccount == *raDstAccount; for (auto const& c: usCurrencies) { if (!sameAccount || (c != saDstAmount.getCurrency ())) @@ -399,13 +402,13 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast) if (c.isZero ()) sourceCurrencies.insert ({c, xrpAccount()}); else - sourceCurrencies.insert ({c, raSrcAccount.getAccountID ()}); + sourceCurrencies.insert ({c, *raSrcAccount}); } } } - jvStatus[jss::source_account] = raSrcAccount.humanAccountID (); - jvStatus[jss::destination_account] = raDstAccount.humanAccountID (); + jvStatus[jss::source_account] = getApp().accountIDCache().toBase58(*raSrcAccount); + jvStatus[jss::destination_account] = getApp().accountIDCache().toBase58(*raDstAccount); jvStatus[jss::destination_amount] = saDstAmount.getJson (0); if (!jvId.isNull ()) @@ -453,8 +456,8 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast) FindPaths fp ( cache, - raSrcAccount.getAccountID (), - raDstAccount.getAccountID (), + *raSrcAccount, + *raDstAccount, saDstAmount, iLevel, 4); // iMaxPaths @@ -486,7 +489,7 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast) ? currIssuer.account : isXRP (currIssuer.currency) ? xrpAccount() - : raSrcAccount.getAccountID (); + : *raSrcAccount; STAmount saMaxAmount ({currIssuer.currency, sourceAccount}, 1); saMaxAmount.negate (); @@ -496,8 +499,8 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast) sandbox, saMaxAmount, saDstAmount, - raDstAccount.getAccountID (), - raSrcAccount.getAccountID (), + *raDstAccount, + *raSrcAccount, spsPaths); if (!fullLiquidityPath.empty() && @@ -511,8 +514,8 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast) sandbox, saMaxAmount, saDstAmount, - raDstAccount.getAccountID (), - raSrcAccount.getAccountID (), + *raDstAccount, + *raSrcAccount, spsPaths); if (rc.result () != tesSUCCESS) m_journal.warning diff --git a/src/ripple/app/paths/PathRequest.h b/src/ripple/app/paths/PathRequest.h index ac0c28731d..48d053bcc7 100644 --- a/src/ripple/app/paths/PathRequest.h +++ b/src/ripple/app/paths/PathRequest.h @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include @@ -99,8 +101,8 @@ private: Json::Value jvStatus; // Last result // Client request parameters - RippleAddress raSrcAccount; - RippleAddress raDstAccount; + boost::optional raSrcAccount; + boost::optional raDstAccount; STAmount saDstAmount; std::set sciSourceCurrencies; diff --git a/src/ripple/app/paths/cursor/AdvanceNode.cpp b/src/ripple/app/paths/cursor/AdvanceNode.cpp index 1e54c1faa0..5accf0d035 100644 --- a/src/ripple/app/paths/cursor/AdvanceNode.cpp +++ b/src/ripple/app/paths/cursor/AdvanceNode.cpp @@ -195,7 +195,7 @@ TER PathCursor::advanceNode (bool const bReverse) const else { node().offerOwnerAccount_ - = node().sleOffer->getFieldAccount160 (sfAccount); + = node().sleOffer->getAccountID (sfAccount); node().saTakerPays = node().sleOffer->getFieldAmount (sfTakerPays); node().saTakerGets diff --git a/src/ripple/app/paths/tests/Path_test.cpp b/src/ripple/app/paths/tests/Path_test.cpp deleted file mode 100644 index 3c5a2dc859..0000000000 --- a/src/ripple/app/paths/tests/Path_test.cpp +++ /dev/null @@ -1,212 +0,0 @@ -//------------------------------------------------------------------------------ -/* -This file is part of rippled: https://github.com/ripple/rippled -Copyright (c) 2012, 2013 Ripple Labs Inc. - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#include -#include -#include -#include - -// probably going to be moved to common_ledger.h - -namespace ripple { -namespace test { - -class Path_test : public TestSuite -{ - void - test_no_direct_path_no_intermediary_no_alternatives() - { - testcase("no direct path no intermediary no alternatives"); - std::uint64_t const xrp = std::mega::num; - - auto master = createAccount("masterpassphrase", KeyType::ed25519); - - std::shared_ptr LCL; - Ledger::pointer ledger; - std::tie(LCL, ledger) = createGenesisLedger(100000 * xrp, master); - - auto accounts = createAndFundAccounts(master, { "alice", "bob" }, - KeyType::ed25519, 10000 * xrp, ledger); - auto& alice = accounts["alice"]; - auto& bob = accounts["bob"]; - expectNotEquals(alice.pk.humanAccountID(), master.pk.humanAccountID()); - - auto alternatives = findPath(ledger, alice, bob, { Currency("USD") }, - Amount(5, "USD", alice), log.stream()); - log << "ripplePathFind alternatives: " << alternatives; - - expectEquals(alternatives.size(), 0); - } - - void - test_direct_path_no_intermediary() - { - testcase("direct path no intermediary"); - std::uint64_t const xrp = std::mega::num; - - auto master = createAccount("masterpassphrase", KeyType::ed25519); - - std::shared_ptr LCL; - Ledger::pointer ledger; - std::tie(LCL, ledger) = createGenesisLedger(100000 * xrp, master); - - // Create accounts - auto accounts = createAndFundAccounts(master, { "alice", "bob" }, - KeyType::ed25519, 10000 * xrp, ledger); - auto& alice = accounts["alice"]; - auto& bob = accounts["bob"]; - expectNotEquals(alice.pk.humanAccountID(), master.pk.humanAccountID()); - - // Set credit limit - trust(bob, alice, "USD", 700, ledger); - - // Find path from alice to bob - auto alternatives = findPath(ledger, alice, bob, { Currency("USD") }, - Amount(5, "USD", bob), log.stream()); - log << "ripplePathFind alternatives: " << alternatives; - - expectEquals(alternatives.size(), 1); - auto alt = alternatives[0u]; - expectEquals(alt[jss::paths_canonical].size(), 0); - expectEquals(alt[jss::paths_computed].size(), 0); - auto srcAmount = alt[jss::source_amount]; - expectEquals(srcAmount[jss::currency], "USD"); - expectEquals(srcAmount[jss::value], "5"); - expectEquals(srcAmount[jss::issuer], alice.pk.humanAccountID()); - } - - void - test_payment_auto_path_find_using_build_path() - { - testcase("payment auto path find (using build_path)"); - - std::uint64_t const xrp = std::mega::num; - - auto master = createAccount("masterpassphrase", KeyType::ed25519); - - std::shared_ptr LCL; - Ledger::pointer ledger; - std::tie(LCL, ledger) = createGenesisLedger(100000 * xrp, master); - - // Create accounts - auto accounts = createAndFundAccountsWithFlags(master, { "alice", "bob", "mtgox" }, - KeyType::ed25519, 10000 * xrp, ledger, LCL, asfDefaultRipple); - auto& alice = accounts["alice"]; - auto& bob = accounts["bob"]; - auto& mtgox = accounts["mtgox"]; - expectNotEquals(alice.pk.humanAccountID(), master.pk.humanAccountID()); - - // Set credit limits - trust(alice, mtgox, "USD", 600, ledger); - trust(bob, mtgox, "USD", 700, ledger); - - // Distribute funds. - pay(mtgox, alice, "USD", "70", ledger); - - verifyBalance(ledger, alice, Amount(70, "USD", mtgox)); - - // Payment with path. - payWithPath(alice, bob, "USD", "24", ledger); - - // Verify balances - verifyBalance(ledger, alice, Amount(46, "USD", mtgox)); - verifyBalance(ledger, mtgox, Amount(-46, "USD", alice)); - verifyBalance(ledger, mtgox, Amount(-24, "USD", bob)); - verifyBalance(ledger, bob, Amount(24, "USD", mtgox)); - } - - void - test_path_find() - { - testcase("path find"); - - std::uint64_t const xrp = std::mega::num; - - auto master = createAccount("masterpassphrase", KeyType::ed25519); - - std::shared_ptr LCL; - Ledger::pointer ledger; - std::tie(LCL, ledger) = createGenesisLedger(100000 * xrp, master); - - // Create accounts - auto accounts = createAndFundAccountsWithFlags(master, { "alice", "bob", "mtgox" }, - KeyType::ed25519, 10000 * xrp, ledger, LCL, asfDefaultRipple); - auto& alice = accounts["alice"]; - auto& bob = accounts["bob"]; - auto& mtgox = accounts["mtgox"]; - expectNotEquals(alice.pk.humanAccountID(), master.pk.humanAccountID()); - - // Set credit limits - trust(alice, mtgox, "USD", 600, ledger); - trust(bob, mtgox, "USD", 700, ledger); - - // Distribute funds. - pay(mtgox, alice, "USD", "70", ledger); - pay(mtgox, bob, "USD", "50", ledger); - - verifyBalance(ledger, alice, Amount(70, "USD", mtgox)); - verifyBalance(ledger, bob, Amount(50, "USD", mtgox)); - - // Find path from alice to mtgox - auto alternatives = findPath(ledger, alice, bob, { Currency("USD") }, - Amount(5, "USD", mtgox), log.stream()); - log << "Path find alternatives: " << alternatives; - expectEquals(alternatives.size(), 1); - auto alt = alternatives[0u]; - expectEquals(alt["paths_canonical"].size(), 0); - expectEquals(alt["paths_computed"].size(), 0); - /* - // This block represents results old behavior. I'd like (me or someone else) to - // eventually write a test that returns data like this, and then this code can - // be moved/reused. - - expectEquals(alt["paths_computed"].size(), 1); - auto computedPaths = alt["paths_computed"]; - expectEquals(computedPaths.size(), 1); - auto computedPath = computedPaths[0u]; - expectEquals(computedPath.size(), 1); - auto computedPathStep = computedPath[0u]; - expectEquals(computedPathStep[jss::account], - mtgox.pk.humanAccountID()); - expectEquals(computedPathStep[jss::type], 1); - expectEquals(computedPathStep[jss::type_hex], - "0000000000000001"); - */ - auto srcAmount = alt[jss::source_amount]; - expectEquals(srcAmount[jss::currency], "USD"); - expectEquals(srcAmount[jss::value], "5"); - expectEquals(srcAmount[jss::issuer], - alice.pk.humanAccountID()); - } - - -public: - void run() - { - test_no_direct_path_no_intermediary_no_alternatives(); - test_direct_path_no_intermediary(); - test_payment_auto_path_find_using_build_path(); - test_path_find(); - } -}; - -BEAST_DEFINE_TESTSUITE(Path, app, ripple); - -} // test -} // ripple diff --git a/src/ripple/app/tx/Transaction.h b/src/ripple/app/tx/Transaction.h index 8438a01991..1f65982e3c 100644 --- a/src/ripple/app/tx/Transaction.h +++ b/src/ripple/app/tx/Transaction.h @@ -156,7 +156,8 @@ public: private: uint256 mTransactionID; - RippleAddress mAccountFrom; + // VFALCO NOTE This member appears unused + AccountID mAccountFrom; RippleAddress mFromPubKey; // Sign transaction with this. mSignPubKey RippleAddress mSourcePrivate; // Sign transaction with this. diff --git a/src/ripple/app/tx/TransactionMeta.h b/src/ripple/app/tx/TransactionMeta.h index 607de2f0bf..0368e1be14 100644 --- a/src/ripple/app/tx/TransactionMeta.h +++ b/src/ripple/app/tx/TransactionMeta.h @@ -23,6 +23,7 @@ #include #include #include +#include #include namespace ripple { @@ -91,8 +92,10 @@ public: STObject& getAffectedNode (SLE::ref node, SField const& type); // create if needed STObject& getAffectedNode (uint256 const& ); const STObject& peekAffectedNode (uint256 const& ) const; - std::vector getAffectedAccounts (); - + + /** Return a list of accounts affected by this transaction */ + boost::container::flat_set + getAffectedAccounts() const; Json::Value getJson (int p) const { diff --git a/src/ripple/app/tx/impl/CancelTicket.cpp b/src/ripple/app/tx/impl/CancelTicket.cpp index 61722a155e..933fa38db6 100644 --- a/src/ripple/app/tx/impl/CancelTicket.cpp +++ b/src/ripple/app/tx/impl/CancelTicket.cpp @@ -56,14 +56,14 @@ public: return tecNO_ENTRY; auto const ticket_owner = - sleTicket->getFieldAccount160 (sfAccount); + sleTicket->getAccountID (sfAccount); bool authorized = mTxnAccountID == ticket_owner; // The target can also always remove a ticket if (!authorized && sleTicket->isFieldPresent (sfTarget)) - authorized = (mTxnAccountID == sleTicket->getFieldAccount160 (sfTarget)); + authorized = (mTxnAccountID == sleTicket->getAccountID (sfTarget)); // And finally, anyone can remove an expired ticket if (!authorized && sleTicket->isFieldPresent (sfExpiration)) diff --git a/src/ripple/app/tx/impl/Change.cpp b/src/ripple/app/tx/impl/Change.cpp index 6b8dbec66c..70c0a68012 100644 --- a/src/ripple/app/tx/impl/Change.cpp +++ b/src/ripple/app/tx/impl/Change.cpp @@ -56,7 +56,7 @@ public: TER checkSign () override { - if (mTxn.getFieldAccount160 (sfAccount).isNonZero ()) + if (mTxn.getAccountID (sfAccount).isNonZero ()) { m_journal.warning << "Bad source account"; return temBAD_SRC_ACCOUNT; @@ -95,7 +95,7 @@ public: TER preCheck () override { - mTxnAccountID = mTxn.getSourceAccount ().getAccountID (); + mTxnAccountID = mTxn.getAccountID(sfAccount); if (mTxnAccountID.isNonZero ()) { diff --git a/src/ripple/app/tx/impl/CreateOffer.cpp b/src/ripple/app/tx/impl/CreateOffer.cpp index dd4162ae9a..16ea4bccb2 100644 --- a/src/ripple/app/tx/impl/CreateOffer.cpp +++ b/src/ripple/app/tx/impl/CreateOffer.cpp @@ -811,7 +811,7 @@ public: if (result == tesSUCCESS) { auto sleOffer = std::make_shared(ltOFFER, offer_index); - sleOffer->setFieldAccount (sfAccount, mTxnAccountID); + sleOffer->setAccountID (sfAccount, mTxnAccountID); sleOffer->setFieldU32 (sfSequence, uSequence); sleOffer->setFieldH256 (sfBookDirectory, uDirectory); sleOffer->setFieldAmount (sfTakerPays, saTakerPays); diff --git a/src/ripple/app/tx/impl/CreateTicket.cpp b/src/ripple/app/tx/impl/CreateTicket.cpp index 055a7f7ecf..432ed23113 100644 --- a/src/ripple/app/tx/impl/CreateTicket.cpp +++ b/src/ripple/app/tx/impl/CreateTicket.cpp @@ -88,7 +88,7 @@ public: SLE::pointer sleTicket = std::make_shared(ltTICKET, getTicketIndex (mTxnAccountID, mTxn.getSequence ())); - sleTicket->setFieldAccount (sfAccount, mTxnAccountID); + sleTicket->setAccountID (sfAccount, mTxnAccountID); sleTicket->setFieldU32 (sfSequence, mTxn.getSequence ()); if (expiration != 0) sleTicket->setFieldU32 (sfExpiration, expiration); @@ -96,7 +96,7 @@ public: if (mTxn.isFieldPresent (sfTarget)) { - AccountID const target_account (mTxn.getFieldAccount160 (sfTarget)); + AccountID const target_account (mTxn.getAccountID (sfTarget)); SLE::pointer sleTarget = mEngine->view().peek (keylet::account(target_account)); @@ -107,7 +107,7 @@ public: // The issuing account is the default account to which the ticket // applies so don't bother saving it if that's what's specified. if (target_account != mTxnAccountID) - sleTicket->setFieldAccount (sfTarget, target_account); + sleTicket->setAccountID (sfTarget, target_account); } std::uint64_t hint; diff --git a/src/ripple/app/tx/impl/LocalTxs.cpp b/src/ripple/app/tx/impl/LocalTxs.cpp index 1a442c6797..095e796456 100644 --- a/src/ripple/app/tx/impl/LocalTxs.cpp +++ b/src/ripple/app/tx/impl/LocalTxs.cpp @@ -64,7 +64,7 @@ public: : m_txn (txn) , m_expire (index + holdLedgers) , m_id (txn->getTransactionID ()) - , m_account (txn->getSourceAccount ()) + , m_account (txn->getAccountID(sfAccount)) , m_seq (txn->getSequence()) { if (txn->isFieldPresent (sfLastLedgerSequence)) @@ -91,7 +91,7 @@ public: return m_txn; } - RippleAddress const& getAccount () const + AccountID const& getAccount () const { return m_account; } @@ -101,10 +101,12 @@ private: STTx::pointer m_txn; LedgerIndex m_expire; uint256 m_id; - RippleAddress m_account; + AccountID m_account; std::uint32_t m_seq; }; +//------------------------------------------------------------------------------ + class LocalTxsImp : public LocalTxs { public: @@ -127,8 +129,8 @@ public: if (hasTransaction (*ledger, txn.getID ())) return true; auto const sle = cachedRead(*ledger, - getAccountRootIndex(txn.getAccount().getAccountID()), - getApp().getSLECache()); + keylet::account(txn.getAccount()).key, + getApp().getSLECache(), ltACCOUNT_ROOT); if (! sle) return false; if (sle->getFieldU32 (sfSequence) > txn.getSeq ()) diff --git a/src/ripple/app/tx/impl/Offer.h b/src/ripple/app/tx/impl/Offer.h index 4795b3cd6a..a24e723ffa 100644 --- a/src/ripple/app/tx/impl/Offer.h +++ b/src/ripple/app/tx/impl/Offer.h @@ -45,7 +45,7 @@ public: Offer (SLE::pointer const& entry, Quality quality) : m_entry (entry) , m_quality (quality) - , m_account (m_entry->getFieldAccount160 (sfAccount)) + , m_account (m_entry->getAccountID (sfAccount)) , m_amounts ( m_entry->getFieldAmount (sfTakerPays), m_entry->getFieldAmount (sfTakerGets)) diff --git a/src/ripple/app/tx/impl/Payment.cpp b/src/ripple/app/tx/impl/Payment.cpp index 26654e3f0f..e45464f046 100644 --- a/src/ripple/app/tx/impl/Payment.cpp +++ b/src/ripple/app/tx/impl/Payment.cpp @@ -91,7 +91,7 @@ public: if (!isLegalNet (saDstAmount) || !isLegalNet (maxSourceAmount)) return temBAD_AMOUNT; - AccountID const uDstAccountID (mTxn.getFieldAccount160 (sfDestination)); + AccountID const uDstAccountID (mTxn.getAccountID (sfDestination)); if (!uDstAccountID) { @@ -174,7 +174,7 @@ public: bool const defaultPathsAllowed = !(uTxFlags & tfNoRippleDirect); bool const bPaths = mTxn.isFieldPresent (sfPaths); bool const bMax = mTxn.isFieldPresent (sfSendMax); - AccountID const uDstAccountID (mTxn.getFieldAccount160 (sfDestination)); + AccountID const uDstAccountID (mTxn.getAccountID (sfDestination)); STAmount const saDstAmount (mTxn.getFieldAmount (sfAmount)); STAmount maxSourceAmount; if (bMax) @@ -235,7 +235,7 @@ public: // Create the account. sleDst = std::make_shared(k); - sleDst->setFieldAccount (sfAccount, uDstAccountID); + sleDst->setAccountID (sfAccount, uDstAccountID); sleDst->setFieldU32 (sfSequence, 1); mEngine->view().insert(sleDst); } diff --git a/src/ripple/app/tx/impl/SetRegularKey.cpp b/src/ripple/app/tx/impl/SetRegularKey.cpp index 2cc848df8d..286b8a0dc0 100644 --- a/src/ripple/app/tx/impl/SetRegularKey.cpp +++ b/src/ripple/app/tx/impl/SetRegularKey.cpp @@ -21,6 +21,7 @@ #include #include #include +#include namespace ripple { @@ -31,7 +32,7 @@ class SetRegularKey { if ( mTxnAccount && (! (mTxnAccount->getFlags () & lsfPasswordSpent)) - && (mSigningPubKey.getAccountID () == mTxnAccountID)) + && (calcAccountID(mSigningPubKey) == mTxnAccountID)) { // flag is armed and they signed with the right account return 0; @@ -76,8 +77,8 @@ public: if (mTxn.isFieldPresent (sfRegularKey)) { - mTxnAccount->setFieldAccount (sfRegularKey, - mTxn.getFieldAccount160 (sfRegularKey)); + mTxnAccount->setAccountID (sfRegularKey, + mTxn.getAccountID (sfRegularKey)); } else { diff --git a/src/ripple/app/tx/impl/SetSignerList.cpp b/src/ripple/app/tx/impl/SetSignerList.cpp index 5c616b1495..58a11ada30 100644 --- a/src/ripple/app/tx/impl/SetSignerList.cpp +++ b/src/ripple/app/tx/impl/SetSignerList.cpp @@ -321,7 +321,7 @@ SetSignerList::writeSignersToLedger (SLE::pointer ledgerEntry) toLedger.emplace_back(sfSignerEntry); STObject& obj = toLedger.back(); obj.reserve (2); - obj.setFieldAccount (sfAccount, entry.account); + obj.setAccountID (sfAccount, entry.account); obj.setFieldU16 (sfSignerWeight, entry.weight); } diff --git a/src/ripple/app/tx/impl/SignerEntries.cpp b/src/ripple/app/tx/impl/SignerEntries.cpp index cf7a1fadb3..a4e2124a9d 100644 --- a/src/ripple/app/tx/impl/SignerEntries.cpp +++ b/src/ripple/app/tx/impl/SignerEntries.cpp @@ -55,7 +55,7 @@ SignerEntries::deserialize ( } // Extract SignerEntry fields. - AccountID const account = sEntry.getFieldAccount160 (sfAccount); + AccountID const account = sEntry.getAccountID (sfAccount); std::uint16_t const weight = sEntry.getFieldU16 (sfSignerWeight); accountVec.emplace_back (account, weight); } diff --git a/src/ripple/app/tx/impl/Transaction.cpp b/src/ripple/app/tx/impl/Transaction.cpp index df73772b16..8d164b13c9 100644 --- a/src/ripple/app/tx/impl/Transaction.cpp +++ b/src/ripple/app/tx/impl/Transaction.cpp @@ -28,15 +28,15 @@ namespace ripple { -Transaction::Transaction (STTx::ref sit, Validate validate, std::string& reason) +Transaction::Transaction (STTx::ref stx, Validate validate, std::string& reason) noexcept - : mTransaction (sit) + : mTransaction (stx) { try { mFromPubKey.setAccountPublic (mTransaction->getSigningPubKey ()); mTransactionID = mTransaction->getTransactionID (); - mAccountFrom = mTransaction->getSourceAccount (); + mAccountFrom = mTransaction->getAccountID(sfAccount); } catch (std::exception& e) { diff --git a/src/ripple/app/tx/impl/TransactionEngine.cpp b/src/ripple/app/tx/impl/TransactionEngine.cpp index d8255a67bd..7e3e345229 100644 --- a/src/ripple/app/tx/impl/TransactionEngine.cpp +++ b/src/ripple/app/tx/impl/TransactionEngine.cpp @@ -104,7 +104,7 @@ TransactionEngine::applyTransaction ( mLedger->getLedgerSeq(), params); SLE::pointer txnAcct = view().peek( - keylet::account(txn.getSourceAccount())); + keylet::account(txn.getAccountID(sfAccount))); if (!txnAcct) terResult = terNO_ACCOUNT; diff --git a/src/ripple/app/tx/impl/TransactionMeta.cpp b/src/ripple/app/tx/impl/TransactionMeta.cpp index e8a38219b9..0bcd4c67ab 100644 --- a/src/ripple/app/tx/impl/TransactionMeta.cpp +++ b/src/ripple/app/tx/impl/TransactionMeta.cpp @@ -93,21 +93,11 @@ void TransactionMetaSet::setAffectedNode (uint256 const& node, SField const& typ obj.setFieldU16 (sfLedgerEntryType, nodeType); } -static void addIfUnique (std::vector& vector, RippleAddress const& address) +boost::container::flat_set +TransactionMetaSet::getAffectedAccounts() const { - for (auto const& a : vector) - { - if (a == address) - return; - } - - vector.push_back (address); -} - -std::vector TransactionMetaSet::getAffectedAccounts () -{ - std::vector accounts; - accounts.reserve (10); + boost::container::flat_set list; + list.reserve (10); // This code should match the behavior of the JS method: // Meta#getAffectedAccounts @@ -118,15 +108,21 @@ std::vector TransactionMetaSet::getAffectedAccounts () if (index != -1) { const STObject* inner = dynamic_cast (&it.peekAtIndex (index)); - + assert(inner); if (inner) { for (auto const& field : *inner) { - const STAccount* sa = dynamic_cast (&field); + STAccount const* sa = + dynamic_cast (&field); if (sa) - addIfUnique (accounts, sa->getValueNCA ()); + { + AccountID id; + assert(sa->isValueH160()); + if (sa->getValueH160(id)) + list.insert(id); + } else if ((field.getFName () == sfLowLimit) || (field.getFName () == sfHighLimit) || (field.getFName () == sfTakerPays) || (field.getFName () == sfTakerGets)) { @@ -137,11 +133,7 @@ std::vector TransactionMetaSet::getAffectedAccounts () auto issuer = lim->getIssuer (); if (issuer.isNonZero ()) - { - RippleAddress na; - na.setAccountID (issuer); - addIfUnique (accounts, na); - } + list.insert(issuer); } else { @@ -150,11 +142,10 @@ std::vector TransactionMetaSet::getAffectedAccounts () } } } - else assert (false); } } - return accounts; + return list; } STObject& TransactionMetaSet::getAffectedNode (SLE::ref node, SField const& type) diff --git a/src/ripple/app/tx/impl/Transactor.cpp b/src/ripple/app/tx/impl/Transactor.cpp index 58270140f8..5e22b990d5 100644 --- a/src/ripple/app/tx/impl/Transactor.cpp +++ b/src/ripple/app/tx/impl/Transactor.cpp @@ -24,6 +24,7 @@ #include #include #include +#include namespace ripple { @@ -207,7 +208,7 @@ TER Transactor::preCheck () TER Transactor::preCheckAccount () { - mTxnAccountID = mTxn.getSourceAccount ().getAccountID (); + mTxnAccountID = mTxn.getAccountID(sfAccount); if (!mTxnAccountID) { @@ -271,7 +272,7 @@ TER Transactor::apply () { m_journal.trace << "applyTransaction: delay: source account does not exist " << - mTxn.getSourceAccount ().humanAccountID (); + toBase58(mTxn.getAccountID(sfAccount)); return terNO_ACCOUNT; } } @@ -314,9 +315,12 @@ TER Transactor::checkSign () TER Transactor::checkSingleSign () { + // VFALCO NOTE This is needlessly calculating the + // AccountID multiple times. + // Consistency: Check signature // Verify the transaction's signing public key is authorized for signing. - if (mSigningPubKey.getAccountID () == mTxnAccountID) + if (calcAccountID(mSigningPubKey) == mTxnAccountID) { // Authorized to continue. mSigMaster = true; @@ -324,8 +328,8 @@ TER Transactor::checkSingleSign () return tefMASTER_DISABLED; } else if (mHasAuthKey && - (mSigningPubKey.getAccountID () == - mTxnAccount->getFieldAccount160 (sfRegularKey))) + (calcAccountID(mSigningPubKey) == + mTxnAccount->getAccountID (sfRegularKey))) { // Authorized to continue. } @@ -410,8 +414,8 @@ checkSigningAccounts ( auto signerEntriesItr = signerEntries.begin (); for (auto const& signingAccount : signingAccounts) { - AccountID const signingAcctID = - signingAccount.getFieldAccount (sfAccount).getAccountID (); + auto const signingAcctID = + signingAccount.getAccountID(sfAccount); // Attempt to match the SignerEntry with a SigningAccount; while (signerEntriesItr->account < signingAcctID) @@ -445,8 +449,8 @@ checkSigningAccounts ( // need to compute the accountID that is associated with the signer's // public key. AccountID const signingAcctIDFromPubKey = - RippleAddress::createAccountPublic ( - signingAccount.getFieldVL (sfSigningPubKey)).getAccountID (); + calcAccountID(RippleAddress::createAccountPublic ( + signingAccount.getFieldVL (sfSigningPubKey))); // Verify that the signingAcctID and the signingAcctIDFromPubKey // belong together. Here is are the rules: @@ -514,7 +518,7 @@ checkSigningAccounts ( return ret; } if (signingAcctIDFromPubKey != - signersAccountRoot->getFieldAccount160 (sfRegularKey)) + signersAccountRoot->getAccountID (sfRegularKey)) { journal.trace << "applyTransaction: Account doesn't match RegularKey."; @@ -555,10 +559,10 @@ TER Transactor::checkMultiSign () auto signerEntriesItr = outer.signerEntries.begin (); for (auto const& signingFor : multiSigners) { - AccountID const signingForID = - signingFor.getFieldAccount (sfAccount).getAccountID (); + auto const signingForID = + signingFor.getAccountID(sfAccount); - STArray const& signingAccounts = + auto const& signingAccounts = signingFor.getFieldArray (sfSigningAccounts); // There are two possibilities: diff --git a/src/ripple/app/tx/tests/MultiSign.test.cpp b/src/ripple/app/tx/tests/MultiSign.test.cpp index ac74f96e64..4d4f6fff72 100644 --- a/src/ripple/app/tx/tests/MultiSign.test.cpp +++ b/src/ripple/app/tx/tests/MultiSign.test.cpp @@ -19,6 +19,7 @@ #include #include #include +#include namespace ripple { namespace test { @@ -36,7 +37,7 @@ class MultiSign_test : public beast::unit_test::suite UserAccount shade {KeyType::secp256k1, "shade"}; UserAccount spook {KeyType::ed25519, "spook"}; -//------------------------------------------------------------------------------ + //-------------------------------------------------------------------------- void test_singleSig (KeyType kType) { @@ -104,7 +105,7 @@ class MultiSign_test : public beast::unit_test::suite aliceBalanceCheck (1000); } -//------------------------------------------------------------------------------ + //-------------------------------------------------------------------------- void test_noReserve (KeyType kType) { @@ -148,7 +149,7 @@ class MultiSign_test : public beast::unit_test::suite } } -//------------------------------------------------------------------------------ + //-------------------------------------------------------------------------- void test_signerListSet (KeyType kType) { @@ -283,7 +284,7 @@ class MultiSign_test : public beast::unit_test::suite } } -//------------------------------------------------------------------------------ + //-------------------------------------------------------------------------- void test_phantomSigners (KeyType kType) { @@ -397,7 +398,7 @@ class MultiSign_test : public beast::unit_test::suite } } -//------------------------------------------------------------------------------ + //-------------------------------------------------------------------------- void test_masterSigners (KeyType kType) { @@ -492,7 +493,7 @@ class MultiSign_test : public beast::unit_test::suite } } -//------------------------------------------------------------------------------ + //-------------------------------------------------------------------------- void test_regularSigners (KeyType kType) { @@ -613,7 +614,7 @@ class MultiSign_test : public beast::unit_test::suite } } -//------------------------------------------------------------------------------ + //-------------------------------------------------------------------------- void test_heterogeneousSigners (KeyType kType) { @@ -769,7 +770,7 @@ class MultiSign_test : public beast::unit_test::suite } } -//------------------------------------------------------------------------------ + //-------------------------------------------------------------------------- void test_twoLevel(KeyType kType) { @@ -1228,7 +1229,7 @@ class MultiSign_test : public beast::unit_test::suite } } -//------------------------------------------------------------------------------ + //-------------------------------------------------------------------------- // See if every kind of transaction can be successfully multi-signed. void test_txTypes(KeyType kType) @@ -1350,7 +1351,7 @@ class MultiSign_test : public beast::unit_test::suite RippleAddress::createSeedGeneric("BadNewsBears"); KeyPair regular = generateKeysFromSeed (kType, seed); STTx tx = getSetRegularKeyTx ( - alice, regular.publicKey.getAccountID()); + alice, calcAccountID(regular.publicKey)); std::vector multiSigs { {alice, bogie, tx}, @@ -1376,7 +1377,7 @@ class MultiSign_test : public beast::unit_test::suite RippleAddress::createSeedGeneric("alie"); KeyPair regular = generateKeysFromSeed (kType, seed); STTx tx = getSetRegularKeyTx ( - alice, regular.publicKey.getAccountID()); + alice, calcAccountID(regular.publicKey)); std::vector multiSigs { {alice, bogie, tx}, diff --git a/src/ripple/app/tx/tests/common_transactor.cpp b/src/ripple/app/tx/tests/common_transactor.cpp index fb9869c235..e5790ddb33 100644 --- a/src/ripple/app/tx/tests/common_transactor.cpp +++ b/src/ripple/app/tx/tests/common_transactor.cpp @@ -32,7 +32,7 @@ UserAccount::UserAccount (KeyType kType, std::string const& passphrase) { RippleAddress const seed = RippleAddress::createSeedGeneric (passphrase); master_ = generateKeysFromSeed (kType, seed); - acctID_ = master_.publicKey.getAccountID (); + acctID_ = calcAccountID(master_.publicKey); } void UserAccount::setRegKey ( @@ -43,7 +43,8 @@ void UserAccount::setRegKey ( KeyPair regular = generateKeysFromSeed (kType, seed); // Tell the ledger what we're up to. - STTx tx = getSetRegularKeyTx (*this, regular.publicKey.getAccountID()); + STTx tx = getSetRegularKeyTx (*this, + calcAccountID(regular.publicKey)); singleSign (tx, *this); ledger.applyGoodTransaction (tx); @@ -79,14 +80,14 @@ TestLedger::TestLedger ( std::uint64_t startAmountDrops, UserAccount const& master, beast::unit_test::suite& suite) -: lastClosedLedger_() +: lastClosedLedger() , openLedger_() , suite_(suite) { // To leverage createGenesisLedger from the Ledger tests, we must match // its interface. TestAccount const masterAcct {master.publicKey(), master.secretKey(), 0}; - std::tie (lastClosedLedger_, openLedger_) = + std::tie (lastClosedLedger, openLedger_) = createGenesisLedger(startAmountDrops, masterAcct); } @@ -103,11 +104,11 @@ std::pair TestLedger::applyTransaction (STTx const& tx, bool check) // time sequencing of transactions. Every transaction applied by a // call to this method gets applied individually. So this transaction // is guaranteed to be applied before the next one. - close_and_advance(openLedger_, lastClosedLedger_); + close_and_advance(openLedger_, lastClosedLedger); // Check for the transaction in the closed ledger. bool const foundTx = - hasTransaction(*lastClosedLedger_, tx.getTransactionID()); + hasTransaction(*lastClosedLedger, tx.getTransactionID()); suite_.expect (r.second == foundTx); return {r.first, r.second && foundTx}; @@ -134,14 +135,6 @@ void TestLedger::applyTecTransaction (STTx const& tx, TER err, bool check) suite_.expect (ret.second == true); } -AccountState::pointer -TestLedger::getAccountState (UserAccount const& acct) const -{ - return ripple::getAccountState( - *lastClosedLedger_, acct.acctPublicKey(), - getApp().getSLECache()); -} - //------------------------------------------------------------------------------ MultiSig::MultiSig(UserAccount const& signingFor, @@ -151,7 +144,8 @@ MultiSig::MultiSig(UserAccount const& signingFor, , multiSig_() { Serializer s = tx.getMultiSigningData ( - signingFor.acctPublicKey(), signer.acctPublicKey()); + calcAccountID(signingFor.acctPublicKey()), + calcAccountID(signer.acctPublicKey())); multiSig_ = signer.secretKey().accountPrivateSign (s.getData()); } @@ -166,7 +160,7 @@ void SignerList::injectInto (STTx& tx) const list.emplace_back(sfSignerEntry); STObject& obj = list.back(); obj.reserve (2); - obj.setFieldAccount (sfAccount, entry.acct->getID ()); + obj.setAccountID (sfAccount, entry.acct->getID ()); obj.setFieldU16 (sfSignerWeight, entry.weight); obj.setTypeFromSField (sfSignerEntry); } @@ -211,7 +205,7 @@ void insertMultiSigs (STTx& tx, std::vector const& multiSigs) prevSigningForID = entry.signingForAccount(); signingFor.emplace (sfSigningFor); signingFor->reserve (2); - signingFor->setFieldAccount (sfAccount, entry.signingForAccount()); + signingFor->setAccountID (sfAccount, entry.signingForAccount()); signingFor->setFieldArray (sfSigningAccounts, STArray()); } assert(signingFor); @@ -223,7 +217,7 @@ void insertMultiSigs (STTx& tx, std::vector const& multiSigs) STObject& signingAccount (signingAccounts.back()); signingAccount.reserve (3); - signingAccount.setFieldAccount (sfAccount, entry.signingAccount()); + signingAccount.setAccountID (sfAccount, entry.signingAccount()); signingAccount.setFieldVL (sfMultiSignature, entry.multiSignature()); signingAccount.setFieldVL (sfSigningPubKey, entry.signingPubKey()); } @@ -242,7 +236,7 @@ void insertMultiSigs (STTx& tx, std::vector const& multiSigs) STTx getSeqTx (UserAccount& acct, TxType type) { STTx tx (type); // Sets SOTemplate and sfTransactionType. - tx.setFieldAccount (sfAccount, acct.getID()); + tx.setAccountID (sfAccount, acct.getID()); tx.setFieldAmount (sfFee, STAmount (10)); tx.setFieldU32 (sfFlags, tfUniversal); tx.setFieldU32 (sfSequence, acct.consumeSeq()); @@ -279,7 +273,7 @@ STTx getPaymentTx ( UserAccount& from, UserAccount const& to, std::uint64_t amountDrops) { STTx tx = getSeqTx (from, ttPAYMENT); - tx.setFieldAccount (sfDestination, to.getID()); + tx.setAccountID (sfDestination, to.getID()); tx.setFieldAmount (sfAmount, amountDrops); return tx; } @@ -288,7 +282,7 @@ STTx getPaymentTx ( UserAccount& from, UserAccount const& to, STAmount const& amount) { STTx tx = getSeqTx (from, ttPAYMENT); - tx.setFieldAccount (sfDestination, to.getID()); + tx.setAccountID (sfDestination, to.getID()); tx.setFieldAmount (sfAmount, amount); return tx; } @@ -297,7 +291,7 @@ STTx getPaymentTx ( STTx getSetRegularKeyTx (UserAccount& acct, AccountID const& regKey) { STTx tx = getSeqTx (acct, ttREGULAR_KEY_SET); - tx.setFieldAccount (sfRegularKey, regKey); + tx.setAccountID (sfRegularKey, regKey); return tx; } @@ -332,7 +326,7 @@ STTx getCreateTicketTx (UserAccount& acct) STTx getCreateTicketTx (UserAccount& acct, UserAccount const& target) { STTx tx = getSeqTx (acct, ttTICKET_CREATE); - tx.setFieldAccount (sfTarget, target.getID()); + tx.setAccountID (sfTarget, target.getID()); return tx; } @@ -365,13 +359,15 @@ void payInDrops (TestLedger& ledger, std::uint64_t getNativeBalance(TestLedger& ledger, UserAccount& acct) { - return ledger.getAccountState(acct)->sle().getFieldAmount( - sfBalance).mantissa(); + return ledger.lastClosedLedger->read( + keylet::account(acct.getID()))->getFieldAmount( + sfBalance).mantissa(); } std::uint32_t getOwnerCount(TestLedger& ledger, UserAccount& acct) { - return ledger.getAccountState(acct)->sle().getFieldU32 (sfOwnerCount); + return ledger.lastClosedLedger->read( + keylet::account(acct.getID()))->getFieldU32(sfOwnerCount); } std::vector getRippleStates ( diff --git a/src/ripple/app/tx/tests/common_transactor.h b/src/ripple/app/tx/tests/common_transactor.h index 6baf109da6..563cab66ad 100644 --- a/src/ripple/app/tx/tests/common_transactor.h +++ b/src/ripple/app/tx/tests/common_transactor.h @@ -100,8 +100,10 @@ public: // This class collects a bunch of the ledger shenanigans tests have to do. class TestLedger { +public: + std::shared_ptr lastClosedLedger; + private: - std::shared_ptr lastClosedLedger_; Ledger::pointer openLedger_; beast::unit_test::suite& suite_; @@ -127,11 +129,6 @@ public: // expected error code. void applyTecTransaction (STTx const& tx, TER err, bool check = true); - // Return the AccountState for a UserAccount - // VFALCO This function is not necessary, just expose - // the ledger data member and use the free function. - AccountState::pointer getAccountState (UserAccount const& acct) const; - // Return the current open ledger. Ledger::pointer openLedger () { diff --git a/src/ripple/ledger/ViewAPI.h b/src/ripple/ledger/ViewAPI.h index f03f3f9a54..0009a1543c 100644 --- a/src/ripple/ledger/ViewAPI.h +++ b/src/ripple/ledger/ViewAPI.h @@ -24,6 +24,7 @@ #include #include #include +#include namespace ripple { diff --git a/src/ripple/ledger/impl/ViewAPI.cpp b/src/ripple/ledger/impl/ViewAPI.cpp index f225f0edaf..840f76f190 100644 --- a/src/ripple/ledger/impl/ViewAPI.cpp +++ b/src/ripple/ledger/impl/ViewAPI.cpp @@ -403,7 +403,7 @@ adjustOwnerCount (View& view, if (adjusted < current) { WriteLog (lsFATAL, View) << - "Account " << sle->getFieldAccount160(sfAccount) << + "Account " << sle->getAccountID(sfAccount) << " owner count exceeds max!"; adjusted = std::numeric_limits::max (); @@ -415,7 +415,7 @@ adjustOwnerCount (View& view, if (adjusted > current) { WriteLog (lsFATAL, View) << - "Account " << sle->getFieldAccount160 (sfAccount) << + "Account " << sle->getAccountID (sfAccount) << " owner count set below 0!"; adjusted = 0; assert(false); @@ -796,7 +796,7 @@ trustCreate (View& view, sleRippleState->getIndex (), [uLowAccountID](std::shared_ptr const& sle, bool) { - sle->setFieldAccount (sfOwner, uLowAccountID); + sle->setAccountID (sfOwner, uLowAccountID); }); if (tesSUCCESS == terResult) @@ -807,7 +807,7 @@ trustCreate (View& view, sleRippleState->getIndex (), [uHighAccountID](std::shared_ptr const& sle, bool) { - sle->setFieldAccount (sfOwner, uHighAccountID); + sle->setAccountID (sfOwner, uHighAccountID); }); } @@ -816,7 +816,7 @@ trustCreate (View& view, const bool bSetDst = saLimit.getIssuer () == uDstAccountID; const bool bSetHigh = bSrcHigh ^ bSetDst; - assert (sleAccount->getFieldAccount160 (sfAccount) == + assert (sleAccount->getAccountID (sfAccount) == (bSetHigh ? uHighAccountID : uLowAccountID)); auto slePeer = view.peek (keylet::account( bSetHigh ? uLowAccountID : uHighAccountID)); @@ -923,7 +923,7 @@ offerDelete (View& view, if (! sle) return tesSUCCESS; auto offerIndex = sle->getIndex (); - auto owner = sle->getFieldAccount160 (sfAccount); + auto owner = sle->getAccountID (sfAccount); // Detect legacy directories. bool bOwnerNode = sle->isFieldPresent (sfOwnerNode); diff --git a/src/ripple/net/InfoSub.h b/src/ripple/net/InfoSub.h index a38316a02c..cee6c389c9 100644 --- a/src/ripple/net/InfoSub.h +++ b/src/ripple/net/InfoSub.h @@ -67,18 +67,18 @@ public: // you get transactions as they occur or once their // results are confirmed virtual void subAccount (ref ispListener, - const hash_set& vnaAccountIDs, + hash_set const& vnaAccountIDs, bool realTime) = 0; // for normal use, removes from InfoSub and server virtual void unsubAccount (ref isplistener, - const hash_set& vnaAccountIDs, + hash_set const& vnaAccountIDs, bool realTime) = 0; // for use during InfoSub destruction // Removes only from the server virtual void unsubAccountInternal (std::uint64_t uListener, - const hash_set& vnaAccountIDs, + hash_set const& vnaAccountIDs, bool realTime) = 0; // VFALCO TODO Document the bool return value @@ -124,11 +124,11 @@ public: void onSendEmpty (); void insertSubAccountInfo ( - RippleAddress addr, + AccountID const& account, bool rt); void deleteSubAccountInfo ( - RippleAddress addr, + AccountID const& account, bool rt); void clearPathRequest (); @@ -145,8 +145,8 @@ protected: private: Consumer m_consumer; Source& m_source; - hash_set realTimeSubscriptions_; - hash_set normalSubscriptions_; + hash_set realTimeSubscriptions_; + hash_set normalSubscriptions_; std::shared_ptr mPathRequest; std::uint64_t mSeq; }; diff --git a/src/ripple/net/impl/InfoSub.cpp b/src/ripple/net/impl/InfoSub.cpp index 360dc245b5..a92a9119fe 100644 --- a/src/ripple/net/impl/InfoSub.cpp +++ b/src/ripple/net/impl/InfoSub.cpp @@ -89,24 +89,24 @@ void InfoSub::onSendEmpty () { } -void InfoSub::insertSubAccountInfo (RippleAddress addr, bool rt) +void InfoSub::insertSubAccountInfo (AccountID const& account, bool rt) { ScopedLockType sl (mLock); if (rt) - realTimeSubscriptions_.insert (addr); + realTimeSubscriptions_.insert (account); else - normalSubscriptions_.insert (addr); + normalSubscriptions_.insert (account); } -void InfoSub::deleteSubAccountInfo (RippleAddress addr, bool rt) +void InfoSub::deleteSubAccountInfo (AccountID const& account, bool rt) { ScopedLockType sl (mLock); if (rt) - realTimeSubscriptions_.erase (addr); + realTimeSubscriptions_.erase (account); else - normalSubscriptions_.erase (addr); + normalSubscriptions_.erase (account); } void InfoSub::clearPathRequest () diff --git a/src/ripple/net/impl/RPCCall.cpp b/src/ripple/net/impl/RPCCall.cpp index 7151e6e2a9..ebde040994 100644 --- a/src/ripple/net/impl/RPCCall.cpp +++ b/src/ripple/net/impl/RPCCall.cpp @@ -18,6 +18,7 @@ //============================================================================== #include +#include #include #include #include @@ -28,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -169,21 +171,24 @@ private: } // account_tx accountID [ledger_min [ledger_max [limit [offset]]]] [binary] [count] [descending] - Json::Value parseAccountTransactions (Json::Value const& jvParams) + Json::Value + parseAccountTransactions (Json::Value const& jvParams) { Json::Value jvRequest (Json::objectValue); - RippleAddress raAccount; unsigned int iParams = jvParams.size (); - if (!raAccount.setAccountID (jvParams[0u].asString ())) + auto const account = + parseBase58(jvParams[0u].asString()); + if (! account) return rpcError (rpcACT_MALFORMED); - jvRequest[jss::account] = raAccount.humanAccountID (); + jvRequest[jss::account]= getApp().accountIDCache().toBase58(*account); bool bDone = false; while (!bDone && iParams >= 2) { + // VFALCO Why is Json::StaticString appearing on the right side? if (jvParams[iParams - 1].asString () == jss::binary) { jvRequest[jss::binary] = true; @@ -240,13 +245,14 @@ private: Json::Value parseTxAccount (Json::Value const& jvParams) { Json::Value jvRequest (Json::objectValue); - RippleAddress raAccount; unsigned int iParams = jvParams.size (); - if (!raAccount.setAccountID (jvParams[0u].asString ())) + auto const account = + parseBase58(jvParams[0u].asString()); + if (! account) return rpcError (rpcACT_MALFORMED); - jvRequest[jss::account] = raAccount.humanAccountID (); + jvRequest[jss::account] = getApp().accountIDCache().toBase58(*account); bool bDone = false; @@ -568,7 +574,9 @@ private: RippleAddress raAddress; - if (!raAddress.setAccountPublic (strIdent) && !raAddress.setAccountID (strIdent) && !raAddress.setSeedGeneric (strIdent)) + if (! raAddress.setAccountPublic (strIdent) && + ! parseBase58(strIdent) && + ! raAddress.setSeedGeneric (strIdent)) return rpcError (rpcACT_MALFORMED); // Get info on account. @@ -586,7 +594,9 @@ private: { RippleAddress raPeer; - if (!raPeer.setAccountPublic (strPeer) && !raPeer.setAccountID (strPeer) && !raPeer.setSeedGeneric (strPeer)) + if (! raPeer.setAccountPublic (strPeer) && + ! parseBase58(strPeer) && + ! raPeer.setSeedGeneric (strPeer)) return rpcError (rpcACT_MALFORMED); jvRequest["peer"] = strPeer; diff --git a/src/ripple/overlay/impl/Manifest.cpp b/src/ripple/overlay/impl/Manifest.cpp index 15592ec45f..60a8daca30 100644 --- a/src/ripple/overlay/impl/Manifest.cpp +++ b/src/ripple/overlay/impl/Manifest.cpp @@ -137,9 +137,9 @@ ManifestCache::configValidatorKey( { throw std::runtime_error ("Expected 34-byte validator key"); } - if (key[0] != VER_NODE_PUBLIC) + if (key[0] != TOKEN_NODE_PUBLIC) { - throw std::runtime_error ("Expected VER_NODE_PUBLIC (28)"); + throw std::runtime_error ("Expected TOKEN_NODE_PUBLIC (28)"); } if (key[1] != 0xED) { diff --git a/src/ripple/protocol/AccountID.h b/src/ripple/protocol/AccountID.h new file mode 100644 index 0000000000..854fb36bb4 --- /dev/null +++ b/src/ripple/protocol/AccountID.h @@ -0,0 +1,194 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2014 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef RIPPLE_PROTOCOL_ACCOUNTID_H_INCLUDED +#define RIPPLE_PROTOCOL_ACCOUNTID_H_INCLUDED + +#include +// VFALCO Uncomment when the header issues are resolved +//#include +#include +#include +#include +#include +#include +#include +#include + +namespace ripple { + +// VFALCO Forward declared due to header issues +class AnyPublicKey; + +namespace detail { + +class AccountIDTag { }; + +} // detail + +/** A 160-bit unsigned that uniquely identifies an account. */ +using AccountID = base_uint< + 160, detail::AccountIDTag>; + +/** Convert AccountID to base58 checked string */ +std::string +toBase58 (AccountID const& v); + +/** Parse AccountID from checked, base58 string. + @return boost::none if a parse error occurs +*/ +template<> +boost::optional +parseBase58 (std::string const& s); + +// Parses AccountID using Bitcoin's alphabet +// This is to catch user error. Likely not needed +// DEPRECATED +boost::optional +deprecatedParseBitcoinAccountID (std::string const& s); + +// Compatibility with legacy code +bool +deprecatedParseBase58 (AccountID& account, + Json::Value const& jv); + +/** Parse AccountID from hexadecimal string + + If the string is not exactly 40 + hex digits, boost::none is returned. + + @return boost::none if a parse error occurs +*/ +template<> +boost::optional +parseHex (std::string const& s); + +/** Parse AccountID from hex or checked base58 string. + + @return boost::none if a parse error occurs +*/ +template<> +boost::optional +parseHexOrBase58 (std::string const& s); + +// VFALCO NOTE These help transition away from RippleAddress + +/** Compute AccountID from public key. + + The account ID is computed as the 160-bit hash of the + public key data. This excludes the version byte and + guard bytes included in the base58 representation. + +*/ +AccountID +calcAccountID (AnyPublicKey const& pk); + +/** A special account that's used as the "issuer" for XRP. */ +AccountID const& +xrpAccount(); + +/** A placeholder for empty accounts. */ +AccountID const& +noAccount(); + +/** Convert hex or base58 string to AccountID. + + @return `true` if the parsing was successful. +*/ +// DEPRECATED +bool +to_issuer (AccountID&, std::string const&); + +// DEPRECATED Should be checking the currency or native flag +inline +bool +isXRP(AccountID const& c) +{ + return c == zero; +} + +// DEPRECATED +inline +std::string +to_string (AccountID const& account) +{ + return toBase58(account); +} + +// DEPRECATED +inline std::ostream& operator<< (std::ostream& os, AccountID const& x) +{ + os << to_string (x); + return os; +} + +//------------------------------------------------------------------------------ + +/** Caches the base58 representations of AccountIDs + + This operation occurs with sufficient frequency to + justify having a cache. In the future, rippled should + require clients to receive "binary" results, where + AccountIDs are hex-encoded. +*/ +class AccountIDCache +{ +private: + std::mutex mutable mutex_; + std::size_t capacity_; + hash_map mutable m0_; + hash_map mutable m1_; + +public: + AccountIDCache(AccountIDCache const&) = delete; + AccountIDCache& operator= (AccountIDCache const&) = delete; + + explicit + AccountIDCache (std::size_t capacity); + + /** Return ripple::toBase58 for the AccountID + + Thread Safety: + Safe to call from any thread concurrently + + @note This function intentionally returns a + copy for correctness. + */ + std::string + toBase58 (AccountID const&) const; +}; + +} // ripple + +//------------------------------------------------------------------------------ + +namespace std { + +// DEPRECATED +// VFALCO Use beast::uhash or a hardened container +template <> +struct hash : ripple::AccountID::hasher +{ +}; + +} // std + +#endif diff --git a/src/ripple/protocol/Indexes.h b/src/ripple/protocol/Indexes.h index 5c741dc575..9951da7940 100644 --- a/src/ripple/protocol/Indexes.h +++ b/src/ripple/protocol/Indexes.h @@ -53,9 +53,6 @@ getLedgerFeeIndex (); uint256 getAccountRootIndex (AccountID const& account); -uint256 -getAccountRootIndex (const RippleAddress & account); - uint256 getGeneratorIndex (AccountID const& uGeneratorID); @@ -110,9 +107,6 @@ namespace keylet { struct account_t { Keylet operator()(AccountID const& id) const; - - // DEPRECATED - Keylet operator()(RippleAddress const& ra) const; }; static account_t const account {}; diff --git a/src/ripple/protocol/JsonFields.h b/src/ripple/protocol/JsonFields.h index 9c2c338ad3..8efeb2fb6a 100644 --- a/src/ripple/protocol/JsonFields.h +++ b/src/ripple/protocol/JsonFields.h @@ -41,7 +41,7 @@ JSS ( ClearFlag ); // field. JSS ( Destination ); // in: TransactionSign; field. JSS ( Fee ); // in/out: TransactionSign; field. JSS ( Flags ); // in/out: TransactionSign; field. -JSS ( Invalid ); // out: app/misc/AccountState +JSS ( Invalid ); // JSS ( LimitAmount ); // field. JSS ( OfferSequence ); // field. JSS ( Paths ); // in/out: TransactionSign @@ -371,7 +371,7 @@ JSS ( uptime ); // out: GetCounts JSS ( url ); // in/out: Subscribe, Unsubscribe JSS ( url_password ); // in: Subscribe JSS ( url_username ); // in: Subscribe -JSS ( urlgravatar ); // out: AccountState +JSS ( urlgravatar ); // JSS ( username ); // in: Subscribe JSS ( validated ); // out: NetworkOPs, LookupLedger, AccountTx* // Tx diff --git a/src/ripple/protocol/RippleAddress.h b/src/ripple/protocol/RippleAddress.h index 1a9349d1a4..0996ff1284 100644 --- a/src/ripple/protocol/RippleAddress.h +++ b/src/ripple/protocol/RippleAddress.h @@ -26,24 +26,13 @@ #include #include #include +#include #include #include #include namespace ripple { -enum VersionEncoding -{ - VER_NONE = 1, - VER_NODE_PUBLIC = 28, - VER_NODE_PRIVATE = 32, - VER_ACCOUNT_ID = 0, - VER_ACCOUNT_PUBLIC = 35, - VER_ACCOUNT_PRIVATE = 34, - VER_FAMILY_GENERATOR = 41, - VER_FAMILY_SEED = 33, -}; - // // Used to hold addresses and parse and produce human formats. // @@ -78,10 +67,8 @@ public: void clear (); bool isSet () const; - static void clearCache (); - /** Returns the public key. - Precondition: version == VER_NODE_PUBLIC + Precondition: version == TOKEN_NODE_PUBLIC */ RipplePublicKey toPublicKey() const; @@ -120,20 +107,6 @@ public: static RippleAddress createNodePrivate (RippleAddress const& naSeed); - // - // Accounts IDs - // - AccountID getAccountID () const; - - std::string humanAccountID () const; - - bool setAccountID ( - std::string const& strAccountID, - Base58::Alphabet const& alphabet = Base58::getRippleAlphabet()); - void setAccountID (AccountID const& hash160In); - - static RippleAddress createAccountID (AccountID const& uiAccountID); - // // Accounts Public // @@ -300,6 +273,10 @@ RippleAddress getSeedFromRPC (Json::Value const& params); KeyPair generateKeysFromSeed (KeyType keyType, RippleAddress const& seed); +// DEPRECATED +AccountID +calcAccountID (RippleAddress const& publicKey); + } // ripple #endif diff --git a/src/ripple/protocol/STAccount.h b/src/ripple/protocol/STAccount.h index d805ccbe97..1b2530169e 100644 --- a/src/ripple/protocol/STAccount.h +++ b/src/ripple/protocol/STAccount.h @@ -65,9 +65,6 @@ public: } std::string getText () const override; - RippleAddress getValueNCA () const; - void setValueNCA (RippleAddress const& nca); - template void setValueH160 (base_uint<160, Tag> const& v) { @@ -75,6 +72,10 @@ public: assert (peekValue ().size () == (160 / 8)); } + // VFALCO This is a clumsy interface, it should return + // the value. And it should not be possible to + // have anything other than a uint160 in here. + // The base_uint tag should always be `AccountIDTag`. template bool getValueH160 (base_uint<160, Tag>& v) const { diff --git a/src/ripple/protocol/STLedgerEntry.h b/src/ripple/protocol/STLedgerEntry.h index a9cc604d96..75ab812a18 100644 --- a/src/ripple/protocol/STLedgerEntry.h +++ b/src/ripple/protocol/STLedgerEntry.h @@ -114,17 +114,7 @@ public: bool isThreadedType() const; // is this a ledger entry that can be threaded bool isThreaded () const; // is this ledger entry actually threaded - - bool hasOneOwner () const; // This node has one other node that owns it - - bool hasTwoOwners () const; // This node has two nodes that own it (like ripple balance) - - RippleAddress getOwner () const; - - RippleAddress getFirstOwner () const; - - RippleAddress getSecondOwner () const; - + uint256 getThreadedTransaction () const; std::uint32_t getThreadedLedger () const; diff --git a/src/ripple/protocol/STObject.h b/src/ripple/protocol/STObject.h index 74ac73389a..08f9ebcebf 100644 --- a/src/ripple/protocol/STObject.h +++ b/src/ripple/protocol/STObject.h @@ -215,13 +215,16 @@ public: // Break the multi-signing hash computation into 2 parts for optimization. Serializer startMultiSigningData () const; void finishMultiSigningData ( - RippleAddress const& signingForID, - RippleAddress const& signingID, Serializer& s) const; + AccountID const& signingForID, + AccountID const& signingID, Serializer& s) const; + // VFALCO Get functions are usually simple observers but + // this one performs an expensive construction. + // // Get data to compute a complete multi-signature. Serializer getMultiSigningData ( - RippleAddress const& signingForID, - RippleAddress const& signingID) const; + AccountID const& signingForID, + AccountID const& signingID) const; const STBase& peekAtIndex (int offset) const { @@ -259,8 +262,7 @@ public: uint160 getFieldH160 (SField const& field) const; uint256 getFieldH256 (SField const& field) const; - RippleAddress getFieldAccount (SField const& field) const; - AccountID getFieldAccount160 (SField const& field) const; + AccountID getAccountID (SField const& field) const; Blob getFieldVL (SField const& field) const; STAmount const& getFieldAmount (SField const& field) const; @@ -282,11 +284,9 @@ public: void setFieldH128 (SField const& field, uint128 const&); void setFieldH256 (SField const& field, uint256 const& ); void setFieldVL (SField const& field, Blob const&); - void setFieldAccount (SField const& field, AccountID const&); - void setFieldAccount (SField const& field, RippleAddress const& addr) - { - setFieldAccount (field, addr.getAccountID ()); - } + + void setAccountID (SField const& field, AccountID const&); + void setFieldAmount (SField const& field, STAmount const&); void setFieldPathSet (SField const& field, STPathSet const&); void setFieldV256 (SField const& field, STVector256 const& v); diff --git a/src/ripple/protocol/STTx.h b/src/ripple/protocol/STTx.h index 88dacaaa62..11cbe99657 100644 --- a/src/ripple/protocol/STTx.h +++ b/src/ripple/protocol/STTx.h @@ -22,6 +22,7 @@ #include #include +#include #include namespace ripple { @@ -94,16 +95,11 @@ public: setFieldAmount (sfFee, fee); } - RippleAddress getSourceAccount () const - { - return getFieldAccount (sfAccount); - } Blob getSigningPubKey () const { return getFieldVL (sfSigningPubKey); } void setSigningPubKey (const RippleAddress & naSignPubKey); - void setSourceAccount (const RippleAddress & naSource); std::uint32_t getSequence () const { @@ -114,7 +110,8 @@ public: return setFieldU32 (sfSequence, seq); } - std::vector getMentionedAccounts () const; + boost::container::flat_set + getMentionedAccounts() const; uint256 getTransactionID () const; diff --git a/src/ripple/protocol/UintTypes.h b/src/ripple/protocol/UintTypes.h index 05e25aba66..ad66072c31 100644 --- a/src/ripple/protocol/UintTypes.h +++ b/src/ripple/protocol/UintTypes.h @@ -22,11 +22,11 @@ #include #include +#include namespace ripple { namespace detail { -class AccountIDTag {}; class CurrencyTag {}; class DirectoryTag {}; class NodeIDTag {}; @@ -37,33 +37,20 @@ class NodeIDTag {}; The last 64 bits of this are the quality. */ using Directory = base_uint<256, detail::DirectoryTag>; -/** AccountID is a hash representing a specific account. */ -using AccountID = base_uint<160, detail::AccountIDTag>; - /** Currency is a hash representing a specific currency. */ using Currency = base_uint<160, detail::CurrencyTag>; /** NodeID is a 160-bit hash representing one node. */ using NodeID = base_uint<160, detail::NodeIDTag>; -using CurrencySet = hash_set; - -/** A special account that's used as the "issuer" for XRP. */ -AccountID const& xrpAccount(); - /** XRP currency. */ Currency const& xrpCurrency(); -/** A placeholder for empty accounts. */ -AccountID const& noAccount(); - /** A placeholder for empty currencies. */ Currency const& noCurrency(); /** We deliberately disallow the currency that looks like "XRP" because too many people were using it instead of the correct XRP currency. */ - - Currency const& badCurrency(); inline bool isXRP(Currency const& c) @@ -71,14 +58,6 @@ inline bool isXRP(Currency const& c) return c == zero; } -inline bool isXRP(AccountID const& c) -{ - return c == zero; -} - -/** Returns a human-readable form of the account. */ -std::string to_string(AccountID const&); - /** Returns "", "XRP", or three letter ISO code. */ std::string to_string(Currency const& c); @@ -88,16 +67,6 @@ bool to_currency(Currency&, std::string const&); /** Tries to convert a string to a Currency, returns noCurrency() on failure. */ Currency to_currency(std::string const&); -/** Tries to convert a string to an AccountID representing an issuer, returns true - * on success. */ -bool to_issuer(AccountID&, std::string const&); - -inline std::ostream& operator<< (std::ostream& os, AccountID const& x) -{ - os << to_string (x); - return os; -} - inline std::ostream& operator<< (std::ostream& os, Currency const& x) { os << to_string (x); @@ -108,11 +77,6 @@ inline std::ostream& operator<< (std::ostream& os, Currency const& x) namespace std { -template <> -struct hash : ripple::AccountID::hasher -{ -}; - template <> struct hash : ripple::Currency::hasher { diff --git a/src/ripple/protocol/impl/AccountID.cpp b/src/ripple/protocol/impl/AccountID.cpp new file mode 100644 index 0000000000..8ebd679a39 --- /dev/null +++ b/src/ripple/protocol/impl/AccountID.cpp @@ -0,0 +1,239 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2012, 2013 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include +#include +#include +#include +#include +#include + +namespace ripple { + +std::string +toBase58 (AccountID const& v) +{ + return base58EncodeToken( + TOKEN_ACCOUNT_ID, + v.data(), v.size()); +} + +template<> +boost::optional +parseBase58 (std::string const& s) +{ + auto const result = + decodeBase58Token( + s, TOKEN_ACCOUNT_ID); + if (result.empty()) + return boost::none; + AccountID id; + if (result.size() != id.size()) + return boost::none; + std::memcpy(id.data(), + result.data(), result.size()); + return id; +} + +boost::optional +deprecatedParseBitcoinAccountID (std::string const& s) +{ + auto const result = + decodeBase58TokenBitcoin( + s, TOKEN_ACCOUNT_ID); + if (result.empty()) + return boost::none; + AccountID id; + if (result.size() != id.size()) + return boost::none; + std::memcpy(id.data(), + result.data(), result.size()); + return id; +} + +bool +deprecatedParseBase58 (AccountID& account, + Json::Value const& jv) +{ + if (! jv.isString()) + return false; + auto const result = + parseBase58(jv.asString()); + if (! result) + return false; + account = *result; + return true; +} + +template<> +boost::optional +parseHex (std::string const& s) +{ + if (s.size() != 40) + return boost::none; + AccountID id; + if (! id.SetHex(s, true)) + return boost::none; + return id; +} + +template<> +boost::optional +parseHexOrBase58 (std::string const& s) +{ + auto result = + parseHex(s); + if (! result) + result = parseBase58(s); + return result; +} + +//------------------------------------------------------------------------------ +/* + Calculation of the Account ID + + The AccountID is a 160-bit identifier that uniquely + distinguishes an account. The account may or may not + exist in the ledger. Even for accounts that are not in + the ledger, cryptographic operations may be performed + which affect the ledger. For example, designating an + account not in the ledger as a regular key for an + account that is in the ledger. + + Why did we use half of SHA512 for most things but then + SHA256 followed by RIPEMD160 for account IDs? Why didn't + we do SHA512 half then RIPEMD160? Or even SHA512 then RIPEMD160? + For that matter why RIPEMD160 at all why not just SHA512 and keep + only 160 bits? + + Answer (David Schwartz): + + The short answer is that we kept Bitcoin's behavior. + The longer answer was that: + 1) Using a single hash could leave ripple + vulnerable to length extension attacks. + 2) Only RIPEMD160 is generally considered safe at 160 bits. + + Any of those schemes would have been acceptable. However, + the one chosen avoids any need to defend the scheme chosen. + (Against any criticism other than unnecessary complexity.) + + "The historical reason was that in the very early days, + we wanted to give people as few ways to argue that we were + less secure than Bitcoin. So where there was no good reason + to change something, it was not changed." +*/ + +AccountID +calcAccountID (AnyPublicKey const& pk) +{ + ripesha_hasher rsh; + rsh(pk.data(), pk.size()); + auto const d = static_cast< + ripesha_hasher::result_type>(rsh); + AccountID id; + static_assert(sizeof(d) == sizeof(id), ""); + std::memcpy(id.data(), d.data(), d.size()); + return id; +} + +AccountID const& +xrpAccount() +{ + static AccountID const account(0); + return account; +} + +AccountID const& +noAccount() +{ + static AccountID const account(1); + return account; +} + +bool +to_issuer (AccountID& issuer, std::string const& s) +{ + if (s.size () == (160 / 4)) + { + issuer.SetHex (s); + return true; + } + auto const account = + parseBase58(s); + if (! account) + return false; + issuer = *account; + return true; +} + +//------------------------------------------------------------------------------ + +/* VFALCO NOTE + An alternate implementation could use a pair of insert-only + hash maps that each use a single large memory allocation + to store a fixed size hash table and all of the AccountID/string + pairs laid out in memory (wouldn't use std::string here just a + length prefixed or zero terminated array). Possibly using + boost::intrusive as the basis for the unordered container. + This would cut down to one allocate/free cycle per swap of + the map. +*/ + +AccountIDCache::AccountIDCache( + std::size_t capacity) + : capacity_(capacity) +{ + m1_.reserve(capacity_); +} + +std::string +AccountIDCache::toBase58( + AccountID const& id) const +{ + std::lock_guard< + std::mutex> lock(mutex_); + auto iter = m1_.find(id); + if (iter != m1_.end()) + return iter->second; + iter = m0_.find(id); + std::string result; + if (iter != m0_.end()) + { + result = iter->second; + // Can use insert-only hash maps if + // we didn't erase from here. + m0_.erase(iter); + } + else + { + result = + ripple::toBase58(id); + } + if (m1_.size() >= capacity_) + { + m0_ = std::move(m1_); + m1_.clear(); + m1_.reserve(capacity_); + } + m1_.emplace(id, result); + return result; +} + +} // ripple diff --git a/src/ripple/protocol/impl/AnyPublicKey.cpp b/src/ripple/protocol/impl/AnyPublicKey.cpp index 4a713257cd..a4ebae4e65 100644 --- a/src/ripple/protocol/impl/AnyPublicKey.cpp +++ b/src/ripple/protocol/impl/AnyPublicKey.cpp @@ -95,7 +95,7 @@ toString (AnyPublicKey const& pk) { Blob buffer; buffer.reserve (1 + pk.size ()); - buffer.push_back (VER_NODE_PUBLIC); + buffer.push_back (TOKEN_NODE_PUBLIC); auto const data = pk.data (); buffer.insert (buffer.end (), data, data + pk.size ()); return Base58::encodeWithCheck (buffer); diff --git a/src/ripple/protocol/impl/Indexes.cpp b/src/ripple/protocol/impl/Indexes.cpp index 8c34a0bae9..4b8ab9cb75 100644 --- a/src/ripple/protocol/impl/Indexes.cpp +++ b/src/ripple/protocol/impl/Indexes.cpp @@ -64,12 +64,6 @@ getAccountRootIndex (AccountID const& account) account); } -uint256 -getAccountRootIndex (const RippleAddress & account) -{ - return getAccountRootIndex (account.getAccountID ()); -} - uint256 getGeneratorIndex (AccountID const& uGeneratorID) { @@ -203,13 +197,6 @@ Keylet account_t::operator()( getAccountRootIndex(id) }; } -Keylet account_t::operator()( - RippleAddress const& ra) const -{ - return { ltACCOUNT_ROOT, - getAccountRootIndex(ra.getAccountID()) }; -} - Keylet child (uint256 const& key) { return { ltCHILD, key }; diff --git a/src/ripple/protocol/impl/RippleAddress.cpp b/src/ripple/protocol/impl/RippleAddress.cpp index 0d1cfcae48..a0c3db5407 100644 --- a/src/ripple/protocol/impl/RippleAddress.cpp +++ b/src/ripple/protocol/impl/RippleAddress.cpp @@ -26,10 +26,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -83,19 +85,19 @@ bool verifySignature (Blob const& pubkey, uint256 const& hash, Blob const& sig, RippleAddress::RippleAddress () : mIsValid (false) { - nVersion = VER_NONE; + nVersion = TOKEN_NONE; } void RippleAddress::clear () { - nVersion = VER_NONE; + nVersion = TOKEN_NONE; vchData.clear (); mIsValid = false; } bool RippleAddress::isSet () const { - return nVersion != VER_NONE; + return nVersion != TOKEN_NONE; } // @@ -145,7 +147,7 @@ RippleAddress RippleAddress::createNodePublic (std::string const& strPublic) RipplePublicKey RippleAddress::toPublicKey() const { - assert (nVersion == VER_NODE_PUBLIC); + assert (nVersion == TOKEN_NODE_PUBLIC); return RipplePublicKey (vchData.begin(), vchData.end()); } @@ -159,10 +161,10 @@ NodeID RippleAddress::getNodeID () const { switch (nVersion) { - case VER_NONE: + case TOKEN_NONE: throw std::runtime_error ("unset source - getNodeID"); - case VER_NODE_PUBLIC: { + case TOKEN_NODE_PUBLIC: { // Note, we are encoding the left. NodeID node; node.copyFrom(Hash160 (vchData)); @@ -178,10 +180,10 @@ Blob const& RippleAddress::getNodePublic () const { switch (nVersion) { - case VER_NONE: + case TOKEN_NONE: throw std::runtime_error ("unset source - getNodePublic"); - case VER_NODE_PUBLIC: + case TOKEN_NODE_PUBLIC: return vchData; default: @@ -193,10 +195,10 @@ std::string RippleAddress::humanNodePublic () const { switch (nVersion) { - case VER_NONE: + case TOKEN_NONE: throw std::runtime_error ("unset source - humanNodePublic"); - case VER_NODE_PUBLIC: + case TOKEN_NODE_PUBLIC: return ToString (); default: @@ -207,7 +209,7 @@ std::string RippleAddress::humanNodePublic () const bool RippleAddress::setNodePublic (std::string const& strPublic) { mIsValid = SetString ( - strPublic, VER_NODE_PUBLIC, Base58::getRippleAlphabet ()); + strPublic, TOKEN_NODE_PUBLIC, Base58::getRippleAlphabet ()); return mIsValid; } @@ -216,7 +218,7 @@ void RippleAddress::setNodePublic (Blob const& vPublic) { mIsValid = true; - SetData (VER_NODE_PUBLIC, vPublic); + SetData (TOKEN_NODE_PUBLIC, vPublic); } bool RippleAddress::verifyNodePublic ( @@ -250,10 +252,10 @@ Blob const& RippleAddress::getNodePrivateData () const { switch (nVersion) { - case VER_NONE: + case TOKEN_NONE: throw std::runtime_error ("unset source - getNodePrivateData"); - case VER_NODE_PRIVATE: + case TOKEN_NODE_PRIVATE: return vchData; default: @@ -265,10 +267,10 @@ uint256 RippleAddress::getNodePrivate () const { switch (nVersion) { - case VER_NONE: + case TOKEN_NONE: throw std::runtime_error ("unset source = getNodePrivate"); - case VER_NODE_PRIVATE: + case TOKEN_NODE_PRIVATE: return uint256 (vchData); default: @@ -280,10 +282,10 @@ std::string RippleAddress::humanNodePrivate () const { switch (nVersion) { - case VER_NONE: + case TOKEN_NONE: throw std::runtime_error ("unset source - humanNodePrivate"); - case VER_NODE_PRIVATE: + case TOKEN_NODE_PRIVATE: return ToString (); default: @@ -294,7 +296,7 @@ std::string RippleAddress::humanNodePrivate () const bool RippleAddress::setNodePrivate (std::string const& strPrivate) { mIsValid = SetString ( - strPrivate, VER_NODE_PRIVATE, Base58::getRippleAlphabet ()); + strPrivate, TOKEN_NODE_PRIVATE, Base58::getRippleAlphabet ()); return mIsValid; } @@ -303,14 +305,14 @@ void RippleAddress::setNodePrivate (Blob const& vPrivate) { mIsValid = true; - SetData (VER_NODE_PRIVATE, vPrivate); + SetData (TOKEN_NODE_PRIVATE, vPrivate); } void RippleAddress::setNodePrivate (uint256 hash256) { mIsValid = true; - SetData (VER_NODE_PRIVATE, hash256); + SetData (TOKEN_NODE_PRIVATE, hash256); } void RippleAddress::signNodePrivate (uint256 const& hash, Blob& vchSig) const @@ -321,131 +323,6 @@ void RippleAddress::signNodePrivate (uint256 const& hash, Blob& vchSig) const throw std::runtime_error ("Signing failed."); } -// -// AccountID -// - -AccountID RippleAddress::getAccountID () const -{ - switch (nVersion) - { - case VER_NONE: - throw std::runtime_error ("unset source - getAccountID"); - - case VER_ACCOUNT_ID: - return AccountID(vchData); - - case VER_ACCOUNT_PUBLIC: { - // Note, we are encoding the left. - // TODO(tom): decipher this comment. - AccountID account; - account.copyFrom (Hash160 (vchData)); - return account; - } - - default: - throw badSourceError (nVersion); - } -} - -using StaticLockType = std::mutex; -using StaticScopedLockType = std::lock_guard ; - -static StaticLockType s_lock; -static hash_map rncMapOld, rncMapNew; - -void RippleAddress::clearCache () -{ - StaticScopedLockType sl (s_lock); - - rncMapOld.clear (); - rncMapNew.clear (); -} - -std::string RippleAddress::humanAccountID () const -{ - switch (nVersion) - { - case VER_NONE: - throw std::runtime_error ("unset source - humanAccountID"); - - case VER_ACCOUNT_ID: - { - std::string ret; - - { - StaticScopedLockType sl (s_lock); - - auto it = rncMapNew.find (vchData); - - if (it != rncMapNew.end ()) - { - // Found in new map, nothing to do - ret = it->second; - } - else - { - it = rncMapOld.find (vchData); - - if (it != rncMapOld.end ()) - { - ret = it->second; - rncMapOld.erase (it); - } - else - ret = ToString (); - - if (rncMapNew.size () >= 128000) - { - rncMapOld = std::move (rncMapNew); - rncMapNew.clear (); - rncMapNew.reserve (128000); - } - - rncMapNew[vchData] = ret; - } - } - - return ret; - } - - case VER_ACCOUNT_PUBLIC: - { - RippleAddress accountID; - - (void) accountID.setAccountID (getAccountID ()); - - return accountID.ToString (); - } - - default: - throw badSourceError (nVersion); - } -} - -bool RippleAddress::setAccountID ( - std::string const& strAccountID, Base58::Alphabet const& alphabet) -{ - if (strAccountID.empty ()) - { - setAccountID (AccountID ()); - - mIsValid = true; - } - else - { - mIsValid = SetString (strAccountID, VER_ACCOUNT_ID, alphabet); - } - - return mIsValid; -} - -void RippleAddress::setAccountID (AccountID const& hash160) -{ - mIsValid = true; - SetData (VER_ACCOUNT_ID, hash160); -} - // // AccountPublic // @@ -464,14 +341,14 @@ Blob const& RippleAddress::getAccountPublic () const { switch (nVersion) { - case VER_NONE: + case TOKEN_NONE: throw std::runtime_error ("unset source - getAccountPublic"); - case VER_ACCOUNT_ID: + case TOKEN_ACCOUNT_ID: throw std::runtime_error ("public not available from account id"); break; - case VER_ACCOUNT_PUBLIC: + case TOKEN_ACCOUNT_PUBLIC: return vchData; default: @@ -483,13 +360,13 @@ std::string RippleAddress::humanAccountPublic () const { switch (nVersion) { - case VER_NONE: + case TOKEN_NONE: throw std::runtime_error ("unset source - humanAccountPublic"); - case VER_ACCOUNT_ID: + case TOKEN_ACCOUNT_ID: throw std::runtime_error ("public not available from account id"); - case VER_ACCOUNT_PUBLIC: + case TOKEN_ACCOUNT_PUBLIC: return ToString (); default: @@ -500,7 +377,7 @@ std::string RippleAddress::humanAccountPublic () const bool RippleAddress::setAccountPublic (std::string const& strPublic) { mIsValid = SetString ( - strPublic, VER_ACCOUNT_PUBLIC, Base58::getRippleAlphabet ()); + strPublic, TOKEN_ACCOUNT_PUBLIC, Base58::getRippleAlphabet ()); return mIsValid; } @@ -509,7 +386,7 @@ void RippleAddress::setAccountPublic (Blob const& vPublic) { mIsValid = true; - SetData (VER_ACCOUNT_PUBLIC, vPublic); + SetData (TOKEN_ACCOUNT_PUBLIC, vPublic); } void RippleAddress::setAccountPublic (RippleAddress const& generator, int seq) @@ -541,14 +418,6 @@ bool RippleAddress::accountPublicVerify ( fullyCanonical); } -RippleAddress RippleAddress::createAccountID (AccountID const& account) -{ - RippleAddress na; - na.setAccountID (account); - - return na; -} - // // AccountPrivate // @@ -567,10 +436,10 @@ uint256 RippleAddress::getAccountPrivate () const { switch (nVersion) { - case VER_NONE: + case TOKEN_NONE: throw std::runtime_error ("unset source - getAccountPrivate"); - case VER_ACCOUNT_PRIVATE: + case TOKEN_ACCOUNT_SECRET: return uint256::fromVoid (vchData.data() + (vchData.size() - 32)); default: @@ -581,7 +450,7 @@ uint256 RippleAddress::getAccountPrivate () const bool RippleAddress::setAccountPrivate (std::string const& strPrivate) { mIsValid = SetString ( - strPrivate, VER_ACCOUNT_PRIVATE, Base58::getRippleAlphabet ()); + strPrivate, TOKEN_ACCOUNT_SECRET, Base58::getRippleAlphabet ()); return mIsValid; } @@ -589,13 +458,13 @@ bool RippleAddress::setAccountPrivate (std::string const& strPrivate) void RippleAddress::setAccountPrivate (Blob const& vPrivate) { mIsValid = true; - SetData (VER_ACCOUNT_PRIVATE, vPrivate); + SetData (TOKEN_ACCOUNT_SECRET, vPrivate); } void RippleAddress::setAccountPrivate (uint256 hash256) { mIsValid = true; - SetData (VER_ACCOUNT_PRIVATE, hash256); + SetData (TOKEN_ACCOUNT_SECRET, hash256); } void RippleAddress::setAccountPrivate ( @@ -689,10 +558,10 @@ Blob const& RippleAddress::getGenerator () const // returns the public generator switch (nVersion) { - case VER_NONE: + case TOKEN_NONE: throw std::runtime_error ("unset source - getGenerator"); - case VER_FAMILY_GENERATOR: + case TOKEN_FAMILY_GENERATOR: // Do nothing. return vchData; @@ -705,10 +574,10 @@ std::string RippleAddress::humanGenerator () const { switch (nVersion) { - case VER_NONE: + case TOKEN_NONE: throw std::runtime_error ("unset source - humanGenerator"); - case VER_FAMILY_GENERATOR: + case TOKEN_FAMILY_GENERATOR: return ToString (); default: @@ -719,7 +588,7 @@ std::string RippleAddress::humanGenerator () const void RippleAddress::setGenerator (Blob const& vPublic) { mIsValid = true; - SetData (VER_FAMILY_GENERATOR, vPublic); + SetData (TOKEN_FAMILY_GENERATOR, vPublic); } RippleAddress RippleAddress::createGeneratorPublic (RippleAddress const& naSeed) @@ -737,10 +606,10 @@ uint128 RippleAddress::getSeed () const { switch (nVersion) { - case VER_NONE: + case TOKEN_NONE: throw std::runtime_error ("unset source - getSeed"); - case VER_FAMILY_SEED: + case TOKEN_FAMILY_SEED: return uint128 (vchData); default: @@ -752,10 +621,10 @@ std::string RippleAddress::humanSeed1751 () const { switch (nVersion) { - case VER_NONE: + case TOKEN_NONE: throw std::runtime_error ("unset source - humanSeed1751"); - case VER_FAMILY_SEED: + case TOKEN_FAMILY_SEED: { std::string strHuman; std::string strLittle; @@ -780,10 +649,10 @@ std::string RippleAddress::humanSeed () const { switch (nVersion) { - case VER_NONE: + case TOKEN_NONE: throw std::runtime_error ("unset source - humanSeed"); - case VER_FAMILY_SEED: + case TOKEN_FAMILY_SEED: return ToString (); default: @@ -809,7 +678,7 @@ int RippleAddress::setSeed1751 (std::string const& strHuman1751) bool RippleAddress::setSeed (std::string const& strSeed) { - mIsValid = SetString (strSeed, VER_FAMILY_SEED, Base58::getRippleAlphabet ()); + mIsValid = SetString (strSeed, TOKEN_FAMILY_SEED, Base58::getRippleAlphabet ()); return mIsValid; } @@ -820,8 +689,10 @@ bool RippleAddress::setSeedGeneric (std::string const& strText) bool bResult = true; uint128 uSeed; + if (parseBase58(strText)) + return false; + if (strText.empty () - || naTemp.setAccountID (strText) || naTemp.setAccountPublic (strText) || naTemp.setAccountPrivate (strText) || naTemp.setNodePublic (strText) @@ -853,7 +724,7 @@ void RippleAddress::setSeed (uint128 hash128) { mIsValid = true; - SetData (VER_FAMILY_SEED, hash128); + SetData (TOKEN_FAMILY_SEED, hash128); } void RippleAddress::setSeedRandom () @@ -978,4 +849,20 @@ KeyPair generateKeysFromSeed (KeyType type, RippleAddress const& seed) return result; } +// DEPRECATED +AccountID +calcAccountID (RippleAddress const& publicKey) +{ + auto const& pk = + publicKey.getAccountPublic(); + ripesha_hasher rsh; + rsh(pk.data(), pk.size()); + auto const d = static_cast< + ripesha_hasher::result_type>(rsh); + AccountID id; + static_assert(sizeof(d) == sizeof(id), ""); + std::memcpy(id.data(), d.data(), d.size()); + return id; +} + } // ripple diff --git a/src/ripple/protocol/impl/STAccount.cpp b/src/ripple/protocol/impl/STAccount.cpp index 9456344cd6..9428113a00 100644 --- a/src/ripple/protocol/impl/STAccount.cpp +++ b/src/ripple/protocol/impl/STAccount.cpp @@ -19,6 +19,7 @@ #include #include +#include namespace ripple { @@ -31,12 +32,11 @@ std::string STAccount::getText () const { AccountID u; RippleAddress a; - - if (!getValueH160 (u)) + if (! getValueH160 (u)) return STBlob::getText (); - - a.setAccountID (u); - return a.humanAccountID (); + // VFALCO This should use getApp().accountIDCache() + // Maybe pass the cache in? + return toBase58(u); } STAccount* @@ -55,20 +55,4 @@ bool STAccount::isValueH160 () const return peekValue ().size () == (160 / 8); } -RippleAddress STAccount::getValueNCA () const -{ - RippleAddress a; - AccountID account; - - if (getValueH160 (account)) - a.setAccountID (account); - - return a; -} - -void STAccount::setValueNCA (RippleAddress const& nca) -{ - setValueH160 (nca.getAccountID ()); -} - } // ripple diff --git a/src/ripple/protocol/impl/STLedgerEntry.cpp b/src/ripple/protocol/impl/STLedgerEntry.cpp index cf2e864e36..210bfa3009 100644 --- a/src/ripple/protocol/impl/STLedgerEntry.cpp +++ b/src/ripple/protocol/impl/STLedgerEntry.cpp @@ -123,31 +123,6 @@ bool STLedgerEntry::isThreaded () const return isFieldPresent (sfPreviousTxnID); } -bool STLedgerEntry::hasOneOwner () const -{ - return (type_ != ltACCOUNT_ROOT) && (getFieldIndex (sfAccount) != -1); -} - -bool STLedgerEntry::hasTwoOwners () const -{ - return type_ == ltRIPPLE_STATE; -} - -RippleAddress STLedgerEntry::getOwner () const -{ - return getFieldAccount (sfAccount); -} - -RippleAddress STLedgerEntry::getFirstOwner () const -{ - return RippleAddress::createAccountID (getFieldAmount (sfLowLimit).getIssuer ()); -} - -RippleAddress STLedgerEntry::getSecondOwner () const -{ - return RippleAddress::createAccountID (getFieldAmount (sfHighLimit).getIssuer ()); -} - uint256 STLedgerEntry::getThreadedTransaction () const { return getFieldH256 (sfPreviousTxnID); diff --git a/src/ripple/protocol/impl/STObject.cpp b/src/ripple/protocol/impl/STObject.cpp index 52a3e41412..659d720db7 100644 --- a/src/ripple/protocol/impl/STObject.cpp +++ b/src/ripple/protocol/impl/STObject.cpp @@ -347,19 +347,21 @@ STObject::startMultiSigningData () const return s; } +// VFALCO This should not be a member, +// and the function shouldn't even exist void STObject::finishMultiSigningData ( - RippleAddress const& signingForID, - RippleAddress const& signingID, + AccountID const& signingForID, + AccountID const& signingID, Serializer& s) const { - s.add160 (signingForID.getAccountID ()); - s.add160 (signingID.getAccountID ()); + s.add160 (signingForID); + s.add160 (signingID); } Serializer STObject::getMultiSigningData ( - RippleAddress const& signingForID, RippleAddress const& signingID) const + AccountID const& signingForID, AccountID const& signingID) const { Serializer s (startMultiSigningData ()); finishMultiSigningData (signingForID, signingID, s); @@ -586,26 +588,7 @@ uint256 STObject::getFieldH256 (SField const& field) const return getFieldByValue (field); } -RippleAddress STObject::getFieldAccount (SField const& field) const -{ - const STBase* rf = peekAtPField (field); - - if (!rf) - throw std::runtime_error ("Field not found"); - - SerializedTypeID id = rf->getSType (); - - if (id == STI_NOTPRESENT) return RippleAddress (); - - const STAccount* cf = dynamic_cast (rf); - - if (!cf) - throw std::runtime_error ("Wrong field type"); - - return cf->getValueNCA (); -} - -AccountID STObject::getFieldAccount160 (SField const& field) const +AccountID STObject::getAccountID (SField const& field) const { auto rf = peekAtPField (field); if (!rf) @@ -715,7 +698,7 @@ void STObject::setFieldV256 (SField const& field, STVector256 const& v) setFieldUsingSetValue (field, v); } -void STObject::setFieldAccount (SField const& field, AccountID const& v) +void STObject::setAccountID (SField const& field, AccountID const& v) { STBase* rf = getPField (field, true); diff --git a/src/ripple/protocol/impl/STParsedJSON.cpp b/src/ripple/protocol/impl/STParsedJSON.cpp index 760758a414..85ddd0a65b 100644 --- a/src/ripple/protocol/impl/STParsedJSON.cpp +++ b/src/ripple/protocol/impl/STParsedJSON.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -544,13 +545,14 @@ static boost::optional parseLeaf ( // set it, otherwise, we assume it's an AccountID if (!uAccount.SetHexExact (account.asString ())) { - RippleAddress a; - if (!a.setAccountID (account.asString ())) + auto const a = parseBase58( + account.asString()); + if (! a) { error = invalid_data (element_name, "account"); return ret; } - uAccount = a.getAccountID (); + uAccount = *a; } } @@ -586,13 +588,14 @@ static boost::optional parseLeaf ( if (!uIssuer.SetHexExact (issuer.asString ())) { - RippleAddress a; - if (!a.setAccountID (issuer.asString ())) + auto const a = parseBase58( + issuer.asString()); + if (! a) { error = invalid_data (element_name, "issuer"); return ret; } - uIssuer = a.getAccountID (); + uIssuer = *a; } } @@ -623,18 +626,17 @@ static boost::optional parseLeaf ( try { - AccountID account; - if (!account.SetHexExact (strValue)) + // VFALCO This needs careful auditing + auto const account = + parseHexOrBase58( + strValue); + if (! account) { - RippleAddress a; - if (!a.setAccountID (strValue)) - { - error = invalid_data (json_name, fieldName); - return ret; - } - account.copyFrom (a.getAccountID ()); + error = invalid_data (json_name, fieldName); + return ret; } - ret = detail::make_stvar (field, account); + ret = detail::make_stvar ( + field, *account); } catch (...) { diff --git a/src/ripple/protocol/impl/STTx.cpp b/src/ripple/protocol/impl/STTx.cpp index 15d2866ba0..b9159bb9f1 100644 --- a/src/ripple/protocol/impl/STTx.cpp +++ b/src/ripple/protocol/impl/STTx.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -120,36 +121,29 @@ STTx::getFullText () const return ret; } -std::vector +boost::container::flat_set STTx::getMentionedAccounts () const { - std::vector accounts; + boost::container::flat_set list; for (auto const& it : *this) { if (auto sa = dynamic_cast (&it)) { - auto const na = sa->getValueNCA (); - - if (std::find (accounts.cbegin (), accounts.cend (), na) == accounts.cend ()) - accounts.push_back (na); + AccountID id; + assert(sa->isValueH160()); + if (sa->getValueH160(id)) + list.insert(id); } else if (auto sa = dynamic_cast (&it)) { auto const& issuer = sa->getIssuer (); - - if (isXRP (issuer)) - continue; - - RippleAddress na; - na.setAccountID (issuer); - - if (std::find (accounts.cbegin (), accounts.cend (), na) == accounts.cend ()) - accounts.push_back (na); + if (! isXRP (issuer)) + list.insert(issuer); } } - return accounts; + return list; } static Blob getSigningData (STTx const& that) @@ -226,11 +220,6 @@ void STTx::setSigningPubKey (RippleAddress const& naSignPubKey) setFieldVL (sfSigningPubKey, naSignPubKey.getAccountPublic ()); } -void STTx::setSourceAccount (RippleAddress const& naSource) -{ - setFieldAccount (sfAccount, naSource); -} - Json::Value STTx::getJson (int) const { Json::Value ret = STObject::getJson (0); @@ -269,6 +258,7 @@ std::string STTx::getMetaSQL (std::uint32_t inLedger, return getMetaSQL (s, inLedger, TXN_SQL_VALIDATED, escapedMetaData); } +// VFALCO This could be a free function elsewhere std::string STTx::getMetaSQL (Serializer rawTxn, std::uint32_t inLedger, char status, std::string const& escapedMetaData) const @@ -281,7 +271,7 @@ STTx::getMetaSQL (Serializer rawTxn, return str (boost::format (bfTrans) % to_string (getTransactionID ()) % format->getName () - % getSourceAccount ().humanAccountID () + % toBase58(getAccountID(sfAccount)) % getSequence () % inLedger % status % rTxn % escapedMetaData); } @@ -338,7 +328,7 @@ STTx::checkMultiSign () const Serializer const dataStart (startMultiSigningData ()); // We also use the sfAccount field inside the loop. Get it once. - RippleAddress const txnAccountID = getFieldAccount (sfAccount); + auto const txnAccountID = getAccountID (sfAccount); // Determine whether signatures must be full canonical. ECDSA const fullyCanonical = (getFlags() & tfFullyCanonicalSig) @@ -398,17 +388,16 @@ STTx::checkMultiSign () const */ // We use this std::set to detect this form of double-signing. - std::set firstLevelSigners; + std::set firstLevelSigners; // SigningFors must be in sorted order by AccountID. - RippleAddress lastSigningForID; - lastSigningForID.setAccountID (""); + AccountID lastSigningForID = zero; // Every signature must verify or we reject the transaction. for (auto const& signingFor : multiSigners) { - RippleAddress const signingForID = - signingFor.getFieldAccount (sfAccount); + auto const signingForID = + signingFor.getAccountID (sfAccount); // SigningFors must be in order by account ID. No duplicates allowed. if (lastSigningForID >= signingForID) @@ -440,13 +429,12 @@ STTx::checkMultiSign () const } // SingingAccounts must be in sorted order by AccountID. - RippleAddress lastSigningAcctID; - lastSigningAcctID.setAccountID (""); + AccountID lastSigningAcctID = zero; for (auto const& signingAcct : signingAccounts) { - RippleAddress const signingAcctID = - signingAcct.getFieldAccount (sfAccount); + auto const signingAcctID = + signingAcct.getAccountID (sfAccount); // None of the multi-signers may sign for themselves. if (signingForID == signingAcctID) diff --git a/src/ripple/protocol/impl/UintTypes.cpp b/src/ripple/protocol/impl/UintTypes.cpp index 2c2281b7cb..7088144780 100644 --- a/src/ripple/protocol/impl/UintTypes.cpp +++ b/src/ripple/protocol/impl/UintTypes.cpp @@ -22,15 +22,11 @@ #include #include #include +#include #include namespace ripple { -std::string to_string(AccountID const& account) -{ - return RippleAddress::createAccountID (account).humanAccountID (); -} - std::string to_string(Currency const& currency) { // Characters we are willing to allow in the ASCII representation of a @@ -111,38 +107,12 @@ Currency to_currency(std::string const& code) return currency; } -bool to_issuer(AccountID& issuer, std::string const& s) -{ - if (s.size () == (160 / 4)) - { - issuer.SetHex (s); - return true; - } - RippleAddress address; - bool success = address.setAccountID (s); - if (success) - issuer = address.getAccountID (); - return success; -} - -AccountID const& xrpAccount() -{ - static AccountID const account(0); - return account; -} - Currency const& xrpCurrency() { static Currency const currency(0); return currency; } -AccountID const& noAccount() -{ - static AccountID const account(1); - return account; -} - Currency const& noCurrency() { static Currency const currency(1); diff --git a/src/ripple/protocol/impl/digest.cpp b/src/ripple/protocol/impl/digest.cpp index ca7f5a5d3d..c17d173b0e 100644 --- a/src/ripple/protocol/impl/digest.cpp +++ b/src/ripple/protocol/impl/digest.cpp @@ -25,12 +25,11 @@ namespace ripple { -static_assert(sizeof(decltype( - openssl_ripemd160_hasher::ctx_)) == - sizeof(RIPEMD160_CTX), ""); - openssl_ripemd160_hasher::openssl_ripemd160_hasher() { + static_assert(sizeof(decltype( + openssl_ripemd160_hasher::ctx_)) == + sizeof(RIPEMD160_CTX), ""); auto const ctx = reinterpret_cast< RIPEMD160_CTX*>(ctx_); RIPEMD160_Init(ctx); @@ -54,12 +53,11 @@ openssl_ripemd160_hasher::operator result_type() noexcept return digest; } -static_assert(sizeof(decltype( - openssl_sha256_hasher::ctx_)) == - sizeof(SHA256_CTX), ""); - openssl_sha256_hasher::openssl_sha256_hasher() { + static_assert(sizeof(decltype( + openssl_sha256_hasher::ctx_)) == + sizeof(SHA256_CTX), ""); auto const ctx = reinterpret_cast< SHA256_CTX*>(ctx_); SHA256_Init(ctx); diff --git a/src/ripple/protocol/impl/tokens.cpp b/src/ripple/protocol/impl/tokens.cpp new file mode 100644 index 0000000000..320cb25beb --- /dev/null +++ b/src/ripple/protocol/impl/tokens.cpp @@ -0,0 +1,331 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2012, 2013 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include +#include +#include +#include +#include +#include // +#include +#include + +namespace ripple { + +static char rippleAlphabet[] = + "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"; + +static char bitcoinAlphabet[] = + "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; + +//------------------------------------------------------------------------------ + +template +static +typename Hasher::result_type +digest (void const* data, std::size_t size) noexcept +{ + Hasher h; + h(data, size); + return static_cast< + typename Hasher::result_type>(h); +} + +template > +static +typename Hasher::result_type +digest (std::array const& v) +{ + return digest(v.data(), v.size()); +} + +// Computes a double digest (e.g. digest of the digest) +template +static +typename Hasher::result_type +digest2 (Args const&... args) +{ + return digest( + digest(args...)); +} + +/* Calculate a 4-byte checksum of the data + + The checksum is calculated as the first 4 bytes + of the SHA256 digest of the message. This is added + to the base58 encoding of identifiers to detect + user error in data entry. + + @note This checksum algorithm is part of the client API +*/ +void +checksum (void* out, + void const* message, + std::size_t size) +{ + auto const h = + digest2(message, size); + std::memcpy(out, h.data(), 4); +} + +//------------------------------------------------------------------------------ + +// Code from Bitcoin: https://github.com/bitcoin/bitcoin +// Copyright (c) 2014 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// +// Modified from the original +// +// WARNING Do not call this directly, use +// encodeBase58Token instead since it +// calculates the size of buffer needed. +static +std::string +encodeBase58( + void const* message, std::size_t size, + void *temp, char const* const alphabet) +{ + auto pbegin = reinterpret_cast< + unsigned char const*>(message); + auto const pend = pbegin + size; + // Skip & count leading zeroes. + int zeroes = 0; + while (pbegin != pend && *pbegin == 0) + { + pbegin++; + zeroes++; + } + auto const b58begin = reinterpret_cast< + unsigned char*>(temp); + // log(256) / log(58), rounded up. + auto const b58end = b58begin + + size * (138 / 100 + 1); + std::fill(b58begin, b58end, 0); + while (pbegin != pend) + { + int carry = *pbegin; + // Apply "b58 = b58 * 256 + ch". + for (auto iter = b58end; iter != b58begin; --iter) + { + carry += 256 * (iter[-1]); + iter[-1] = carry % 58; + carry /= 58; + } + assert(carry == 0); + pbegin++; + } + // Skip leading zeroes in base58 result. + auto iter = b58begin; + while (iter != b58end && *iter == 0) + ++iter; + // Translate the result into a string. + std::string str; + str.reserve(zeroes + (b58end - iter)); + str.assign(zeroes, alphabet[0]); + while (iter != b58end) + str += alphabet[*(iter++)]; + return str; +} + +/* Base-58 encode a Ripple Token + + Ripple Tokens have a one-byte prefx indicating + the type of token, followed by the data for the + token, and finally a 4-byte checksum. + + Tokens include the following: + + Wallet Seed + Account Public Key + Account ID + + @param temp A pointer to storage of not + less than 2*(size+6) bytes +*/ +std::string +base58EncodeToken (std::uint8_t type, + void const* token, std::size_t size) +{ + char buf[1024]; + // expanded token includes type + checksum + auto const expanded = 1 + size + 4; + // add scratch, log(256) / log(58), rounded up. + auto const needed = expanded + + size * (138 / 100 + 1); + std::unique_ptr< + char[]> pbuf; + char* temp; + if (needed > sizeof(buf)) + { + pbuf.reset(new char[needed]); + temp = pbuf.get(); + } + else + { + temp = buf; + } + // Lay the data out as + // + temp[0] = type; + std::memcpy(temp + 1, token, size); + checksum(temp + 1 + size, temp, 1 + size); + return encodeBase58(temp, expanded, + temp + expanded, rippleAlphabet); +} + +//------------------------------------------------------------------------------ + +// Code from Bitcoin: https://github.com/bitcoin/bitcoin +// Copyright (c) 2014 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// +// Modified from the original +template +static +std::string +decodeBase58 (std::string const& s, + InverseArray const& inv) +{ + auto psz = s.c_str(); + auto remain = s.size(); + // Skip and count leading zeroes + int zeroes = 0; + while (remain > 0 && inv[*psz] == 0) + { + ++zeroes; + ++psz; + --remain; + } + // Allocate enough space in big-endian base256 representation. + // log(58) / log(256), rounded up. + std::vector b256( + remain * 733 / 1000 + 1); + while (remain > 0) + { + auto carry = inv[*psz]; + if (carry == -1) + return {}; + // Apply "b256 = b256 * 58 + carry". + for (auto iter = b256.rbegin(); + iter != b256.rend(); ++iter) + { + carry += 58 * *iter; + *iter = carry % 256; + carry /= 256; + } + assert(carry == 0); + ++psz; + --remain; + } + // Skip leading zeroes in b256. + auto iter = std::find_if( + b256.begin(), b256.end(),[](unsigned char c) + { return c != 0; }); + std::string result; + result.reserve (zeroes + (b256.end() - iter)); + result.assign (zeroes, 0x00); + while (iter != b256.end()) + result.push_back(*(iter++)); + return result; +} + +/* Base58 decode a Ripple token + + The type and checksum are are checked + and removed from the returned result. +*/ +template +static +std::string +decodeBase58Token (std::string const& s, + int type, InverseArray const& inv) +{ + auto result = decodeBase58(s, inv); + if (result.empty()) + return result; + // Reject zero length tokens + if (result.size() < 6) + return {}; + if (result[0] != type) + return {}; + std::array guard; + checksum(guard.data(), + result.data(), result.size() - 4); + if (std::memcmp(guard.data(), + result.data() + + result.size() - 4, 4) != 0) + return {}; + result.resize(result.size() - 4); + // Erase the type byte + // VFALCO This might cause problems later + result.erase(result.begin()); + return result; +} + +//------------------------------------------------------------------------------ + +// Maps characters to their base58 digit +class InverseAlphabet +{ +private: + std::array map_; + +public: + explicit + InverseAlphabet(std::string const& digits) + { + map_.fill(-1); + int i = 0; + for(auto const c : digits) + map_[static_cast< + unsigned char>(c)] = i++; + } + + int + operator[](char c) const + { + return map_[static_cast< + unsigned char>(c)]; + } +}; + +static InverseAlphabet rippleInverse(rippleAlphabet); + +static InverseAlphabet bitcoinInverse(bitcoinAlphabet); + +std::string +decodeBase58Token( + std::string const& s, int type) +{ + return decodeBase58Token( + s, type, rippleInverse); +} + +std::string +decodeBase58TokenBitcoin( + std::string const& s, int type) +{ + return decodeBase58Token( + s, type, bitcoinInverse); +} + +} // ripple diff --git a/src/ripple/protocol/tests/Issue.test.cpp b/src/ripple/protocol/tests/Issue.test.cpp index baaf24d08e..078bb8e282 100644 --- a/src/ripple/protocol/tests/Issue.test.cpp +++ b/src/ripple/protocol/tests/Issue.test.cpp @@ -489,6 +489,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Issue,types,ripple); +BEAST_DEFINE_TESTSUITE(Issue,protocol,ripple); } diff --git a/src/ripple/protocol/tests/RippleAddress.test.cpp b/src/ripple/protocol/tests/RippleAddress.test.cpp index 0261e8b374..d32bace4b3 100644 --- a/src/ripple/protocol/tests/RippleAddress.test.cpp +++ b/src/ripple/protocol/tests/RippleAddress.test.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include namespace ripple { @@ -72,14 +73,14 @@ public: RippleAddress naAccountPublic0 = RippleAddress::createAccountPublic (generator, 0); RippleAddress naAccountPrivate0 = RippleAddress::createAccountPrivate (generator, naSeed, 0); - expect (naAccountPublic0.humanAccountID () == "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", naAccountPublic0.humanAccountID ()); + expect (toBase58(calcAccountID(naAccountPublic0)) == "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"); expect (naAccountPublic0.humanAccountPublic () == "aBQG8RQAzjs1eTKFEAQXr2gS4utcDiEC9wmi7pfUPTi27VCahwgw", naAccountPublic0.humanAccountPublic ()); // Create account #1 public/private key pair. RippleAddress naAccountPublic1 = RippleAddress::createAccountPublic (generator, 1); RippleAddress naAccountPrivate1 = RippleAddress::createAccountPrivate (generator, naSeed, 1); - expect (naAccountPublic1.humanAccountID () == "r4bYF7SLUMD7QgSLLpgJx38WJSY12ViRjP", naAccountPublic1.humanAccountID ()); + expect (toBase58(calcAccountID(naAccountPublic1)) == "r4bYF7SLUMD7QgSLLpgJx38WJSY12ViRjP"); expect (naAccountPublic1.humanAccountPublic () == "aBPXpTfuLy1Bhk3HnGTTAqnovpKWQ23NpFMNkAF6F1Atg5vDyPrw", naAccountPublic1.humanAccountPublic ()); // Check account signing. diff --git a/src/ripple/protocol/tests/STTx.test.cpp b/src/ripple/protocol/tests/STTx.test.cpp index 742cf84333..b110b2e33b 100644 --- a/src/ripple/protocol/tests/STTx.test.cpp +++ b/src/ripple/protocol/tests/STTx.test.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -37,7 +38,7 @@ public: RippleAddress privateAcct = RippleAddress::createAccountPrivate (generator, seed, 1); STTx j (ttACCOUNT_SET); - j.setSourceAccount (publicAcct); + j.setAccountID (sfAccount, calcAccountID(publicAcct)); j.setSigningPubKey (publicAcct); j.setFieldVL (sfMessageKey, publicAcct.getAccountPublic ()); j.sign (privateAcct); @@ -85,11 +86,13 @@ public: // Create a transaction RippleAddress txnSeed; txnSeed.setSeedRandom (); + // VFALCO Generators are no longer supported RippleAddress txnGenerator = txnSeed.createGeneratorPublic (txnSeed); + // VFALCO Use AnyPublicKey here RippleAddress txnPublicAcct = txnSeed.createAccountPublic (txnGenerator, 1); STTx txn (ttACCOUNT_SET); - txn.setSourceAccount (txnPublicAcct); + txn.setAccountID (sfAccount, calcAccountID(txnPublicAcct)); txn.setSigningPubKey (txnPublicAcct); txn.setFieldVL (sfMessageKey, txnPublicAcct.getAccountPublic ()); Blob const emptyBlob; // Make empty signature for multi-signing @@ -101,16 +104,17 @@ public: RippleAddress const saGenerator = saSeed.createGeneratorPublic (saSeed); RippleAddress const saPublicAcct = saSeed.createAccountPublic (saGenerator, 1); - AccountID const saID = saPublicAcct.getAccountID (); + AccountID const saID = calcAccountID(saPublicAcct); // Create a field for SigningFor - AccountID const signingForID = txnPublicAcct.getAccountID (); + AccountID const signingForID = calcAccountID(txnPublicAcct); RippleAddress saPrivateAcct = saSeed.createAccountPrivate(saGenerator, saSeed, 0); // Get the stream of the transaction for use in multi-signing. - Serializer s = txn.getMultiSigningData (saPublicAcct, saPublicAcct); + Serializer s = txn.getMultiSigningData( + calcAccountID(saPublicAcct), calcAccountID(saPublicAcct)); Blob saMultiSignature = saPrivateAcct.accountPrivateSign (s.getData()); @@ -137,7 +141,7 @@ public: // Insert SigningAccounts array into SigningFor object. STObject signingFor (sfSigningFor); - signingFor.setFieldAccount (sfAccount, signingForID); + signingFor.setAccountID (sfAccount, signingForID); signingFor.setFieldArray (sfSigningAccounts, signingAccts); // Insert SigningFor into MultiSigners. @@ -169,7 +173,7 @@ public: { // Test case 1. Make a valid SigningAccount object. STObject soTest1 (sfSigningAccount); - soTest1.setFieldAccount (sfAccount, saID); + soTest1.setAccountID (sfAccount, saID); soTest1.setFieldVL (sfSigningPubKey, txnPublicAcct.getAccountPublic ()); soTest1.setFieldVL (sfMultiSignature, saMultiSignature); @@ -178,14 +182,14 @@ public: { // Test case 2. Omit sfSigningPubKey from SigningAccount. STObject soTest2 (sfSigningAccount); - soTest2.setFieldAccount (sfAccount, saID); + soTest2.setAccountID (sfAccount, saID); soTest2.setFieldVL (sfMultiSignature, saMultiSignature); testMalformedSigningAccount (soTest2, false); } { // Test case 3. Extra sfAmount in SigningAccount. STObject soTest3 (sfSigningAccount); - soTest3.setFieldAccount (sfAccount, saID); + soTest3.setAccountID (sfAccount, saID); soTest3.setFieldVL (sfSigningPubKey, txnPublicAcct.getAccountPublic ()); soTest3.setFieldVL (sfMultiSignature, saMultiSignature); diff --git a/src/ripple/app/misc/AccountState.h b/src/ripple/protocol/tests/types_test.cpp similarity index 52% rename from src/ripple/app/misc/AccountState.h rename to src/ripple/protocol/tests/types_test.cpp index d9d321cf4f..a11a13698c 100644 --- a/src/ripple/app/misc/AccountState.h +++ b/src/ripple/protocol/tests/types_test.cpp @@ -17,48 +17,31 @@ */ //============================================================================== -#ifndef RIPPLE_APP_MISC_ACCOUNTSTATE_H_INCLUDED -#define RIPPLE_APP_MISC_ACCOUNTSTATE_H_INCLUDED - -#include -#include -#include -#include +#include +#include +#include namespace ripple { -// -// Provide abstract access to an account's state, such that -// access to the serialized format is hidden. -// - -// VFALCO TODO Remove this class, its redundant and hardly used -class AccountState +struct types_test : public beast::unit_test::suite { -public: - // VFALCO TODO Figure out if we need this to be shared - using pointer = std::shared_ptr; - - // For accounts in a ledger - AccountState (std::shared_ptr sle, - RippleAddress const& naAccountI); - - SLE const& - sle() const + void + testAccountID() { - return *mLedgerEntry; + auto const s = + "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"; + if (expect(parseBase58(s))) + expect(toBase58( + *parseBase58(s)) == s); } - void addJson (Json::Value& value); - -private: - // VFALCO TODO Remove this - static std::string createGravatarUrl (uint128 uEmailHash); - - bool mValid = false; - std::shared_ptr mLedgerEntry; + void + run() override + { + testAccountID(); + } }; -} // ripple +BEAST_DEFINE_TESTSUITE(types,protocol,ripple); -#endif +} diff --git a/src/ripple/protocol/tokens.h b/src/ripple/protocol/tokens.h new file mode 100644 index 0000000000..5524dc1d8e --- /dev/null +++ b/src/ripple/protocol/tokens.h @@ -0,0 +1,100 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2012, 2013 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef RIPPLE_PROTOCOL_TOKENS_H_INCLUDED +#define RIPPLE_PROTOCOL_TOKENS_H_INCLUDED + +#include +#include +#include + +namespace ripple { + +enum TokenType +{ + TOKEN_NONE = 1, + TOKEN_NODE_PUBLIC = 28, + TOKEN_NODE_PRIVATE = 32, + TOKEN_ACCOUNT_ID = 0, + TOKEN_ACCOUNT_PUBLIC = 35, + TOKEN_ACCOUNT_SECRET = 34, + TOKEN_FAMILY_GENERATOR = 41, + TOKEN_FAMILY_SEED = 33 +}; + +template +boost::optional +parseBase58 (std::string const& s); + +template +boost::optional +parseHex (std::string const& s); + +template +boost::optional +parseHexOrBase58 (std::string const& s); + +// Facilities for converting Ripple tokens +// to and from their human readable strings + +/* Base-58 encode a Ripple Token + + Ripple Tokens have a one-byte prefx indicating + the type of token, followed by the data for the + token, and finally a 4-byte checksum. + + Tokens include the following: + + Wallet Seed + Account Public Key + Account ID + + @param temp A pointer to storage of not + less than 2*(size+6) bytes +*/ +std::string +base58EncodeToken (std::uint8_t type, + void const* token, std::size_t size); + +/** Decode a Base58 token + + The type and checksum must match or an + empty string is returned. +*/ +std::string +decodeBase58Token( + std::string const& s, int type); + +/** Decode a Base58 token using Bitcoin alphabet + + The type and checksum must match or an + empty string is returned. + + This is used to detect user error. Specifically, + when an AccountID is specified using the wrong + base58 alphabet, so that a better error message + may be returned. +*/ +std::string +decodeBase58TokenBitcoin( + std::string const& s, int type); + +} // ripple + +#endif diff --git a/src/ripple/protocol/types.h b/src/ripple/protocol/types.h new file mode 100644 index 0000000000..ad048a6ef7 --- /dev/null +++ b/src/ripple/protocol/types.h @@ -0,0 +1,27 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2012, 2013 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef RIPPLE_PROTOCOL_TYPES_H_INCLUDED +#define RIPPLE_PROTOCOL_TYPES_H_INCLUDED + +// DEPRECATED HEADER + +#include + +#endif diff --git a/src/ripple/rpc/handlers/AccountCurrencies.cpp b/src/ripple/rpc/handlers/AccountCurrencies.cpp index 4b6f4d50e9..d355a6977f 100644 --- a/src/ripple/rpc/handlers/AccountCurrencies.cpp +++ b/src/ripple/rpc/handlers/AccountCurrencies.cpp @@ -57,17 +57,18 @@ Json::Value doAccountCurrencies (RPC::Context& context) // Get info on account. bool bIndex; // out param - RippleAddress naAccount; // out param + AccountID accountID; // out param Json::Value jvAccepted ( - RPC::accountFromString (naAccount, bIndex, strIdent, iIndex, bStrict)); + RPC::accountFromString (accountID, bIndex, strIdent, iIndex, bStrict)); if (!jvAccepted.empty ()) return jvAccepted; std::set send, receive; - for (auto const& item : getRippleStateItems (naAccount.getAccountID (), ledger)) + for (auto const& item : getRippleStateItems (accountID, ledger)) { - RippleState* rspEntry = (RippleState*) item.get (); + auto const rspEntry = item.get(); + STAmount const& saBalance = rspEntry->getBalance (); if (saBalance < rspEntry->getLimit ()) diff --git a/src/ripple/rpc/handlers/AccountInfo.cpp b/src/ripple/rpc/handlers/AccountInfo.cpp index 7e18e1ee2f..16fd4294c3 100644 --- a/src/ripple/rpc/handlers/AccountInfo.cpp +++ b/src/ripple/rpc/handlers/AccountInfo.cpp @@ -20,6 +20,7 @@ #include #include #include +#include namespace ripple { @@ -52,27 +53,26 @@ Json::Value doAccountInfo (RPC::Context& context) int iIndex = params.isMember (jss::account_index) ? params[jss::account_index].asUInt () : 0; bool bStrict = params.isMember (jss::strict) && params[jss::strict].asBool (); - RippleAddress naAccount; + AccountID accountID; // Get info on account. auto jvAccepted = RPC::accountFromString ( - naAccount, bIndex, strIdent, iIndex, bStrict); + accountID, bIndex, strIdent, iIndex, bStrict); if (!jvAccepted.empty ()) return jvAccepted; - AccountState::pointer asAccepted = - getAccountState(*ledger, naAccount, - getApp().getSLECache()); + auto const sleAccepted = cachedRead(*ledger, + keylet::account(accountID).key, + getApp().getSLECache(), ltACCOUNT_ROOT); - if (asAccepted) + if (sleAccepted) { - asAccepted->addJson (jvAccepted); + injectSLE(jvAccepted, *sleAccepted); // See if there's a SignerEntries for this account. - AccountID const account = naAccount.getAccountID (); - uint256 const signerListIndex = getSignerListIndex (account); + uint256 const signerListIndex = getSignerListIndex (accountID); auto const signerList = cachedRead(*ledger, signerListIndex, getApp().getSLECache()); @@ -93,7 +93,7 @@ Json::Value doAccountInfo (RPC::Context& context) } else { - result[jss::account] = naAccount.humanAccountID (); + result[jss::account] = getApp().accountIDCache().toBase58 (accountID); RPC::inject_error (rpcACT_NOT_FOUND, result); } diff --git a/src/ripple/rpc/handlers/AccountLines.cpp b/src/ripple/rpc/handlers/AccountLines.cpp index 8abc820f63..1037e2da14 100644 --- a/src/ripple/rpc/handlers/AccountLines.cpp +++ b/src/ripple/rpc/handlers/AccountLines.cpp @@ -30,7 +30,7 @@ struct VisitData { std::vector items; AccountID const& accountID; - RippleAddress const& rippleAddressPeer; + bool hasPeer; AccountID const& raPeerAccount; }; @@ -91,10 +91,11 @@ Json::Value doAccountLines (RPC::Context& context) std::string strIdent (params[jss::account].asString ()); bool bIndex (params.isMember (jss::account_index)); int iIndex (bIndex ? params[jss::account_index].asUInt () : 0); - RippleAddress rippleAddress; + + AccountID accountID; auto jv = RPC::accountFromString ( - rippleAddress, bIndex, strIdent, iIndex, false); + accountID, bIndex, strIdent, iIndex, false); if (! jv.empty ()) { for (auto it = jv.begin (); it != jv.end (); ++it) @@ -103,35 +104,32 @@ Json::Value doAccountLines (RPC::Context& context) return result; } - if (! ledger->exists(keylet::account( - rippleAddress.getAccountID()))) + if (! ledger->exists(keylet::account (accountID))) return rpcError (rpcACT_NOT_FOUND); - std::string strPeer (params.isMember (jss::peer) - ? params[jss::peer].asString () : ""); - bool bPeerIndex (params.isMember (jss::peer_index)); - int iPeerIndex (bIndex ? params[jss::peer_index].asUInt () : 0); + std::string strPeer; + if (params.isMember (jss::peer)) + strPeer = params[jss::peer].asString (); + auto hasPeer = ! strPeer.empty (); - RippleAddress rippleAddressPeer; - - if (! strPeer.empty ()) + AccountID raPeerAccount; + if (hasPeer) { - result[jss::peer] = rippleAddress.humanAccountID (); + bool bPeerIndex (params.isMember (jss::peer_index)); + int iPeerIndex (bIndex ? params[jss::peer_index].asUInt () : 0); + + result[jss::peer] = getApp().accountIDCache().toBase58 (accountID); if (bPeerIndex) result[jss::peer_index] = iPeerIndex; result = RPC::accountFromString ( - rippleAddressPeer, bPeerIndex, strPeer, iPeerIndex, false); + raPeerAccount, bPeerIndex, strPeer, iPeerIndex, false); if (! result.empty ()) return result; } - AccountID raPeerAccount; - if (rippleAddressPeer.isValid ()) - raPeerAccount = rippleAddressPeer.getAccountID (); - unsigned int limit; if (params.isMember (jss::limit)) { @@ -154,8 +152,7 @@ Json::Value doAccountLines (RPC::Context& context) } Json::Value& jsonLines (result[jss::lines] = Json::arrayValue); - AccountID const& raAccount(rippleAddress.getAccountID ()); - VisitData visitData = { {}, raAccount, rippleAddressPeer, raPeerAccount }; + VisitData visitData = {{}, accountID, hasPeer, raPeerAccount}; unsigned int reserve (limit); uint256 startAfter; std::uint64_t startHint; @@ -176,15 +173,15 @@ Json::Value doAccountLines (RPC::Context& context) if (sleLine == nullptr || sleLine->getType () != ltRIPPLE_STATE) return rpcError (rpcINVALID_PARAMS); - if (sleLine->getFieldAmount (sfLowLimit).getIssuer () == raAccount) + if (sleLine->getFieldAmount (sfLowLimit).getIssuer () == accountID) startHint = sleLine->getFieldU64 (sfLowNode); - else if (sleLine->getFieldAmount (sfHighLimit).getIssuer () == raAccount) + else if (sleLine->getFieldAmount (sfHighLimit).getIssuer () == accountID) startHint = sleLine->getFieldU64 (sfHighNode); else return rpcError (rpcINVALID_PARAMS); // Caller provided the first line (startAfter), add it as first result - auto const line = RippleState::makeItem (raAccount, sleLine); + auto const line = RippleState::makeItem (accountID, sleLine); if (line == nullptr) return rpcError (rpcINVALID_PARAMS); @@ -201,15 +198,15 @@ Json::Value doAccountLines (RPC::Context& context) { CachedView const view( *ledger, getApp().getSLECache()); - if (! forEachItemAfter(view, raAccount, + if (! forEachItemAfter(view, accountID, startAfter, startHint, reserve, [&visitData](std::shared_ptr const& sleCur) { auto const line = RippleState::makeItem (visitData.accountID, sleCur); if (line != nullptr && - (! visitData.rippleAddressPeer.isValid () || - visitData.raPeerAccount == line->getAccountIDPeer ())) + (! visitData.hasPeer || + visitData.raPeerAccount == line->getAccountIDPeer ())) { visitData.items.emplace_back (line); return true; @@ -231,7 +228,7 @@ Json::Value doAccountLines (RPC::Context& context) visitData.items.pop_back (); } - result[jss::account] = rippleAddress.humanAccountID (); + result[jss::account] = getApp().accountIDCache().toBase58 (accountID); for (auto const& item : visitData.items) addLine (jsonLines, *item.get ()); diff --git a/src/ripple/rpc/handlers/AccountObjects.cpp b/src/ripple/rpc/handlers/AccountObjects.cpp index 65d43041b1..ff0f1ada75 100644 --- a/src/ripple/rpc/handlers/AccountObjects.cpp +++ b/src/ripple/rpc/handlers/AccountObjects.cpp @@ -18,6 +18,7 @@ //============================================================================== #include +#include #include #include #include @@ -51,14 +52,14 @@ Json::Value doAccountObjects (RPC::Context& context) if (ledger == nullptr) return result; - RippleAddress raAccount; + AccountID accountID; { bool bIndex; auto const strIdent = params[jss::account].asString (); auto iIndex = context.params.isMember (jss::account_index) ? context.params[jss::account_index].asUInt () : 0; auto jv = RPC::accountFromString ( - raAccount, bIndex, strIdent, iIndex, false); + accountID, bIndex, strIdent, iIndex, false); if (! jv.empty ()) { for (auto it = jv.begin (); it != jv.end (); ++it) @@ -68,8 +69,7 @@ Json::Value doAccountObjects (RPC::Context& context) } } - if (! ledger->exists(keylet::account( - raAccount.getAccountID()))) + if (! ledger->exists(keylet::account (accountID))) return rpcError (rpcACT_NOT_FOUND); auto type = ltINVALID; @@ -144,13 +144,13 @@ Json::Value doAccountObjects (RPC::Context& context) return RPC::invalid_field_error (jss::marker); } - if (! RPC::getAccountObjects (*ledger, raAccount.getAccountID (), type, + if (! RPC::getAccountObjects (*ledger, accountID, type, dirIndex, entryIndex, limit, result)) { return RPC::invalid_field_error (jss::marker); } - result[jss::account] = raAccount.humanAccountID (); + result[jss::account] = getApp().accountIDCache().toBase58 (accountID); context.loadType = Resource::feeMediumBurdenRPC; return result; } diff --git a/src/ripple/rpc/handlers/AccountOffers.cpp b/src/ripple/rpc/handlers/AccountOffers.cpp index c1ea61ffeb..553e4f1609 100644 --- a/src/ripple/rpc/handlers/AccountOffers.cpp +++ b/src/ripple/rpc/handlers/AccountOffers.cpp @@ -47,10 +47,10 @@ Json::Value doAccountOffers (RPC::Context& context) std::string strIdent (params[jss::account].asString ()); bool bIndex (params.isMember (jss::account_index)); int const iIndex (bIndex ? params[jss::account_index].asUInt () : 0); - RippleAddress rippleAddress; + AccountID accountID; Json::Value const jv = RPC::accountFromString ( - rippleAddress, bIndex, strIdent, iIndex, false); + accountID, bIndex, strIdent, iIndex, false); if (! jv.empty ()) { for (Json::Value::const_iterator it (jv.begin ()); it != jv.end (); ++it) @@ -60,13 +60,12 @@ Json::Value doAccountOffers (RPC::Context& context) } // Get info on account. - result[jss::account] = rippleAddress.humanAccountID (); + result[jss::account] = getApp().accountIDCache().toBase58 (accountID); if (bIndex) result[jss::account_index] = iIndex; - if (! ledger->exists(keylet::account( - rippleAddress.getAccountID()))) + if (! ledger->exists(keylet::account (accountID))) return rpcError (rpcACT_NOT_FOUND); unsigned int limit; @@ -90,7 +89,6 @@ Json::Value doAccountOffers (RPC::Context& context) limit = RPC::Tuning::defaultOffersPerRequest; } - AccountID const& raAccount (rippleAddress.getAccountID ()); Json::Value& jsonOffers (result[jss::offers] = Json::arrayValue); std::vector > offers; unsigned int reserve (limit); @@ -112,7 +110,7 @@ Json::Value doAccountOffers (RPC::Context& context) if (sleOffer == nullptr || sleOffer->getType () != ltOFFER || - raAccount != sleOffer->getFieldAccount160 (sfAccount)) + accountID != sleOffer->getAccountID (sfAccount)) { return rpcError (rpcINVALID_PARAMS); } @@ -138,7 +136,7 @@ Json::Value doAccountOffers (RPC::Context& context) { CachedView const view( *ledger, getApp().getSLECache()); - if (! forEachItemAfter(*ledger, raAccount, + if (! forEachItemAfter(*ledger, accountID, startAfter, startHint, reserve, [&offers](std::shared_ptr const& offer) { diff --git a/src/ripple/rpc/handlers/AccountTx.cpp b/src/ripple/rpc/handlers/AccountTx.cpp index a982d942eb..4312ac1a72 100644 --- a/src/ripple/rpc/handlers/AccountTx.cpp +++ b/src/ripple/rpc/handlers/AccountTx.cpp @@ -18,8 +18,10 @@ //============================================================================== #include +#include #include #include +#include namespace ripple { @@ -36,7 +38,6 @@ Json::Value doAccountTx (RPC::Context& context) { auto& params = context.params; - RippleAddress raAccount; int limit = params.isMember (jss::limit) ? params[jss::limit].asUInt () : -1; bool bBinary = params.isMember (jss::binary) && params[jss::binary].asBool (); @@ -57,7 +58,9 @@ Json::Value doAccountTx (RPC::Context& context) if (!params.isMember (jss::account)) return rpcError (rpcINVALID_PARAMS); - if (!raAccount.setAccountID (params[jss::account].asString ())) + auto const account = parseBase58( + params[jss::account].asString()); + if (! account) return rpcError (rpcACT_MALFORMED); context.loadType = Resource::feeMediumBurdenRPC; @@ -101,13 +104,13 @@ Json::Value doAccountTx (RPC::Context& context) #endif Json::Value ret (Json::objectValue); - ret[jss::account] = raAccount.humanAccountID (); + ret[jss::account] = getApp().accountIDCache().toBase58(*account); Json::Value& jvTxns = (ret[jss::transactions] = Json::arrayValue); if (bBinary) { auto txns = context.netOps.getTxsAccountB ( - raAccount, uLedgerMin, uLedgerMax, bForward, resumeToken, limit, + *account, uLedgerMin, uLedgerMax, bForward, resumeToken, limit, context.role == Role::ADMIN); for (auto& it: txns) @@ -128,7 +131,7 @@ Json::Value doAccountTx (RPC::Context& context) else { auto txns = context.netOps.getTxsAccount ( - raAccount, uLedgerMin, uLedgerMax, bForward, resumeToken, limit, + *account, uLedgerMin, uLedgerMax, bForward, resumeToken, limit, context.role == Role::ADMIN); for (auto& it: txns) diff --git a/src/ripple/rpc/handlers/AccountTxOld.cpp b/src/ripple/rpc/handlers/AccountTxOld.cpp index f6ee5b8be8..d575015377 100644 --- a/src/ripple/rpc/handlers/AccountTxOld.cpp +++ b/src/ripple/rpc/handlers/AccountTxOld.cpp @@ -34,7 +34,6 @@ namespace ripple { // } Json::Value doAccountTxOld (RPC::Context& context) { - RippleAddress raAccount; std::uint32_t offset = context.params.isMember (jss::offset) ? context.params[jss::offset].asUInt () : 0; @@ -56,7 +55,9 @@ Json::Value doAccountTxOld (RPC::Context& context) if (!context.params.isMember (jss::account)) return rpcError (rpcINVALID_PARAMS); - if (!raAccount.setAccountID (context.params[jss::account].asString ())) + auto const raAccount = parseBase58( + context.params[jss::account].asString()); + if (! raAccount) return rpcError (rpcACT_MALFORMED); if (offset > 3000) @@ -121,13 +122,13 @@ Json::Value doAccountTxOld (RPC::Context& context) Json::Value ret (Json::objectValue); - ret[jss::account] = raAccount.humanAccountID (); + ret[jss::account] = getApp().accountIDCache().toBase58(*raAccount); Json::Value& jvTxns = (ret[jss::transactions] = Json::arrayValue); if (bBinary) { auto txns = context.netOps.getAccountTxsB ( - raAccount, uLedgerMin, uLedgerMax, bDescending, offset, limit, + *raAccount, uLedgerMin, uLedgerMax, bDescending, offset, limit, context.role == Role::ADMIN); for (auto it = txns.begin (), end = txns.end (); it != end; ++it) @@ -149,7 +150,7 @@ Json::Value doAccountTxOld (RPC::Context& context) else { auto txns = context.netOps.getAccountTxs ( - raAccount, uLedgerMin, uLedgerMax, bDescending, offset, limit, + *raAccount, uLedgerMin, uLedgerMax, bDescending, offset, limit, context.role == Role::ADMIN); for (auto it = txns.begin (), end = txns.end (); it != end; ++it) diff --git a/src/ripple/rpc/handlers/BookOffers.cpp b/src/ripple/rpc/handlers/BookOffers.cpp index 6614bd77d4..9549d6e6fb 100644 --- a/src/ripple/rpc/handlers/BookOffers.cpp +++ b/src/ripple/rpc/handlers/BookOffers.cpp @@ -18,6 +18,7 @@ //============================================================================== #include +#include namespace ripple { @@ -143,20 +144,17 @@ Json::Value doBookOffers (RPC::Context& context) return RPC::make_error (rpcDST_ISR_MALFORMED, "Invalid field 'taker_gets.issuer', expected non-XRP issuer."); - RippleAddress raTakerID; - + boost::optional takerID; if (context.params.isMember (jss::taker)) { if (! context.params [jss::taker].isString ()) return RPC::expected_field_error (jss::taker, "string"); - if (! raTakerID.setAccountID (context.params [jss::taker].asString ())) + takerID = parseBase58( + context.params [jss::taker].asString()); + if (! takerID) return RPC::invalid_field_error (jss::taker); } - else - { - raTakerID.setAccountID (noAccount()); - } if (pay_currency == get_currency && pay_issuer == get_issuer) { @@ -190,7 +188,7 @@ Json::Value doBookOffers (RPC::Context& context) context.role == Role::ADMIN, lpLedger, {{pay_currency, pay_issuer}, {get_currency, get_issuer}}, - raTakerID.getAccountID (), bProof, iLimit, jvMarker, jvResult); + takerID ? *takerID : zero, bProof, iLimit, jvMarker, jvResult); context.loadType = Resource::feeMediumBurdenRPC; diff --git a/src/ripple/rpc/handlers/GatewayBalances.cpp b/src/ripple/rpc/handlers/GatewayBalances.cpp index 8856a88652..3c4317cd18 100644 --- a/src/ripple/rpc/handlers/GatewayBalances.cpp +++ b/src/ripple/rpc/handlers/GatewayBalances.cpp @@ -18,6 +18,7 @@ //============================================================================== #include +#include #include #include #include @@ -78,17 +79,16 @@ Json::Value doGatewayBalances (RPC::Context& context) // Get info on account. bool bIndex; // out param - RippleAddress naAccount; // out param - Json::Value jvAccepted (RPC::accountFromString ( - naAccount, bIndex, strIdent, iIndex, bStrict)); + AccountID accountID; + Json::Value jvAccepted = RPC::accountFromString ( + accountID, bIndex, strIdent, iIndex, bStrict); if (!jvAccepted.empty ()) return jvAccepted; context.loadType = Resource::feeHighBurdenRPC; - result[jss::account] = naAccount.humanAccountID(); - auto accountID = naAccount.getAccountID(); + result[jss::account] = getApp().accountIDCache().toBase58 (accountID); // Parse the specified hotwallet(s), if any std::set hotWallets; @@ -103,13 +103,18 @@ Json::Value doGatewayBalances (RPC::Context& context) if (j.isString()) { RippleAddress ra; - if (! ra.setAccountPublic (j.asString ()) && - ! ra.setAccountID (j.asString())) + if (ra.setAccountPublic (j.asString ())) { - valid = false; + hotWallets.insert(calcAccountID(ra)); } else - hotWallets.insert (ra.getAccountID ()); + { + auto const a =parseBase58(j.asString()); + if (! a) + valid = false; + else + hotWallets.insert(*a); + } } else { @@ -147,7 +152,7 @@ Json::Value doGatewayBalances (RPC::Context& context) { CachedView const view( *ledger, getApp().getSLECache()); - forEachItem(view, accountID, + forEachItem(view, accountID, [&](std::shared_ptr const& sle) { auto rs = RippleState::makeItem (accountID, sle); diff --git a/src/ripple/rpc/handlers/LedgerEntry.cpp b/src/ripple/rpc/handlers/LedgerEntry.cpp index 931e725245..c75baffb20 100644 --- a/src/ripple/rpc/handlers/LedgerEntry.cpp +++ b/src/ripple/rpc/handlers/LedgerEntry.cpp @@ -48,19 +48,12 @@ Json::Value doLedgerEntry (RPC::Context& context) } else if (context.params.isMember (jss::account_root)) { - RippleAddress naAccount; - - if (!naAccount.setAccountID ( - context.params[jss::account_root].asString ()) - || !naAccount.getAccountID ()) - { + auto const account = parseBase58( + context.params[jss::account_root].asString()); + if (! account || account->isZero()) jvResult[jss::error] = "malformedAddress"; - } else - { - uNodeIndex - = getAccountRootIndex (naAccount.getAccountID ()); - } + uNodeIndex = keylet::account(*account).key; } else if (context.params.isMember (jss::directory)) { @@ -89,18 +82,16 @@ Json::Value doLedgerEntry (RPC::Context& context) } else if (context.params[jss::directory].isMember (jss::owner)) { - RippleAddress naOwnerID; + auto const ownerID = parseBase58( + context.params[jss::directory][jss::owner].asString()); - if (!naOwnerID.setAccountID ( - context.params[jss::directory][jss::owner].asString ())) + if (! ownerID) { jvResult[jss::error] = "malformedAddress"; } else { - uint256 uDirRoot - = getOwnerDirIndex ( - naOwnerID.getAccountID ()); + uint256 uDirRoot = getOwnerDirIndex (*ownerID); uNodeIndex = getDirNodeIndex (uDirRoot, uSubIndex); } } @@ -129,19 +120,18 @@ Json::Value doLedgerEntry (RPC::Context& context) } else { + // VFALCO Can we remove this? RippleAddress na0Public; // To find the generator's index. RippleAddress naGenerator = RippleAddress::createGeneratorPublic (naGeneratorID); na0Public.setAccountPublic (naGenerator, 0); - uNodeIndex = getGeneratorIndex (na0Public.getAccountID ()); + uNodeIndex = getGeneratorIndex (calcAccountID(na0Public)); } } else if (context.params.isMember (jss::offer)) { - RippleAddress naAccountID; - if (!context.params[jss::offer].isObject ()) { uNodeIndex.SetHex (context.params[jss::offer].asString ()); @@ -152,15 +142,15 @@ Json::Value doLedgerEntry (RPC::Context& context) { jvResult[jss::error] = "malformedRequest"; } - else if (!naAccountID.setAccountID ( - context.params[jss::offer][jss::account].asString ())) - { - jvResult[jss::error] = "malformedAddress"; - } else { - uNodeIndex = getOfferIndex (naAccountID.getAccountID (), - context.params[jss::offer][jss::seq].asUInt ()); + auto const id = parseBase58( + context.params[jss::offer][jss::account].asString()); + if (! id) + jvResult[jss::error] = "malformedAddress"; + else + uNodeIndex = getOfferIndex (*id, + context.params[jss::offer][jss::seq].asUInt ()); } } else if (context.params.isMember (jss::ripple_state)) @@ -183,22 +173,26 @@ Json::Value doLedgerEntry (RPC::Context& context) { jvResult[jss::error] = "malformedRequest"; } - else if (!naA.setAccountID ( - jvRippleState[jss::accounts][0u].asString ()) - || !naB.setAccountID ( - jvRippleState[jss::accounts][1u].asString ())) - { - jvResult[jss::error] = "malformedAddress"; - } - else if (!to_currency ( - uCurrency, jvRippleState[jss::currency].asString ())) - { - jvResult[jss::error] = "malformedCurrency"; - } else { - uNodeIndex = getRippleStateIndex ( - naA.getAccountID (), naB.getAccountID (), uCurrency); + auto const id1 = parseBase58( + jvRippleState[jss::accounts][0u].asString()); + auto const id2 = parseBase58( + jvRippleState[jss::accounts][1u].asString()); + if (! id1 || ! id2) + { + jvResult[jss::error] = "malformedAddress"; + } + else if (!to_currency (uCurrency, + jvRippleState[jss::currency].asString())) + { + jvResult[jss::error] = "malformedCurrency"; + } + else + { + uNodeIndex = getRippleStateIndex( + *id1, *id2, uCurrency); + } } } else diff --git a/src/ripple/rpc/handlers/NoRippleCheck.cpp b/src/ripple/rpc/handlers/NoRippleCheck.cpp index 3eb4339006..fedb5b9ec2 100644 --- a/src/ripple/rpc/handlers/NoRippleCheck.cpp +++ b/src/ripple/rpc/handlers/NoRippleCheck.cpp @@ -18,6 +18,7 @@ //============================================================================== #include +#include #include #include #include @@ -29,12 +30,12 @@ namespace ripple { static void fillTransaction ( Json::Value& txArray, - RippleAddress const& account, + AccountID const& accountID, std::uint32_t& sequence, Ledger::ref ledger) { txArray["Sequence"] = Json::UInt (sequence++); - txArray["Account"] = account.humanAccountID (); + txArray["Account"] = getApp().accountIDCache().toBase58 (accountID); txArray["Fee"] = Json::UInt (scaleFeeLoad ( getApp().getFeeTrack(), *ledger, 10, false)); } @@ -96,10 +97,10 @@ Json::Value doNoRippleCheck (RPC::Context& context) std::string strIdent (params[jss::account].asString ()); bool bIndex (params.isMember (jss::account_index)); int iIndex (bIndex ? params[jss::account_index].asUInt () : 0); - RippleAddress rippleAddress; + AccountID accountID; Json::Value const jv = RPC::accountFromString ( - rippleAddress, bIndex, strIdent, iIndex, false); + accountID, bIndex, strIdent, iIndex, false); if (! jv.empty ()) { for (Json::Value::const_iterator it (jv.begin ()); it != jv.end (); ++it) @@ -108,17 +109,17 @@ Json::Value doNoRippleCheck (RPC::Context& context) return result; } - AccountState::pointer accountState = - getAccountState(*ledger, rippleAddress, - getApp().getSLECache()); - if (! accountState) + auto const sle = cachedRead(*ledger, + keylet::account(accountID).key, + getApp().getSLECache(), ltACCOUNT_ROOT); + if (! sle) return rpcError (rpcACT_NOT_FOUND); - std::uint32_t seq = accountState->sle().getFieldU32 (sfSequence); + std::uint32_t seq = sle->getFieldU32 (sfSequence); Json::Value& problems = (result["problems"] = Json::arrayValue); - bool bDefaultRipple = accountState->sle().getFieldU32 (sfFlags) & lsfDefaultRipple; + bool bDefaultRipple = sle->getFieldU32 (sfFlags) & lsfDefaultRipple; if (bDefaultRipple & ! roleGateway) { @@ -133,15 +134,13 @@ Json::Value doNoRippleCheck (RPC::Context& context) Json::Value& tx = jvTransactions.append (Json::objectValue); tx["TransactionType"] = "AccountSet"; tx["SetFlag"] = 8; - fillTransaction (tx, rippleAddress, seq, ledger); + fillTransaction (tx, accountID, seq, ledger); } } - auto const accountID = rippleAddress.getAccountID (); - CachedView const view( *ledger, getApp().getSLECache()); - forEachItemAfter (view, accountID, + forEachItemAfter (view, accountID, uint256(), 0, limit, [&](std::shared_ptr const& ownedItem) { @@ -181,7 +180,7 @@ Json::Value doNoRippleCheck (RPC::Context& context) tx["TransactionType"] = "TrustSet"; tx["LimitAmount"] = limitAmount.getJson (0); tx["Flags"] = bNoRipple ? tfClearNoRipple : tfSetNoRipple; - fillTransaction(tx, rippleAddress, seq, ledger); + fillTransaction(tx, accountID, seq, ledger); return true; } diff --git a/src/ripple/rpc/handlers/OwnerInfo.cpp b/src/ripple/rpc/handlers/OwnerInfo.cpp index c87736d8e9..d05c6addbb 100644 --- a/src/ripple/rpc/handlers/OwnerInfo.cpp +++ b/src/ripple/rpc/handlers/OwnerInfo.cpp @@ -39,32 +39,32 @@ Json::Value doOwnerInfo (RPC::Context& context) bool bIndex; int iIndex = context.params.isMember (jss::account_index) ? context.params[jss::account_index].asUInt () : 0; - RippleAddress raAccount; Json::Value ret; // Get info on account. auto const& closedLedger = context.netOps.getClosedLedger (); + AccountID accountID; Json::Value jAccepted = RPC::accountFromString ( - raAccount, + accountID, bIndex, strIdent, iIndex, false); - ret[jss::accepted] = jAccepted.empty () ? context.netOps.getOwnerInfo ( - closedLedger, raAccount) : jAccepted; + ret[jss::accepted] = jAccepted.empty () ? + context.netOps.getOwnerInfo (closedLedger, accountID) : jAccepted; auto const& currentLedger = context.netOps.getCurrentLedger (); Json::Value jCurrent = RPC::accountFromString ( - raAccount, + accountID, bIndex, strIdent, iIndex, false); - ret[jss::current] = jCurrent.empty () ? context.netOps.getOwnerInfo ( - currentLedger, raAccount) : jCurrent; + ret[jss::current] = jCurrent.empty () ? + context.netOps.getOwnerInfo (currentLedger, accountID) : jCurrent; return ret; } diff --git a/src/ripple/rpc/handlers/RipplePathFind.cpp b/src/ripple/rpc/handlers/RipplePathFind.cpp index cef0f117b5..4ec7ccb9c9 100644 --- a/src/ripple/rpc/handlers/RipplePathFind.cpp +++ b/src/ripple/rpc/handlers/RipplePathFind.cpp @@ -19,11 +19,13 @@ #include #include +#include #include #include #include #include #include +#include #include #include @@ -38,8 +40,8 @@ Json::Value doRipplePathFind (RPC::Context& context) context.loadType = Resource::feeHighBurdenRPC; - RippleAddress raSrc; - RippleAddress raDst; + AccountID raSrc; + AccountID raDst; STAmount saDstAmount; Ledger::pointer lpLedger; @@ -61,9 +63,8 @@ Json::Value doRipplePathFind (RPC::Context& context) { jvResult = rpcError (rpcSRC_ACT_MISSING); } - else if (!context.params[jss::source_account].isString () - || !raSrc.setAccountID ( - context.params[jss::source_account].asString ())) + else if (! deprecatedParseBase58(raSrc, + context.params[jss::source_account])) { jvResult = rpcError (rpcSRC_ACT_MALFORMED); } @@ -71,9 +72,8 @@ Json::Value doRipplePathFind (RPC::Context& context) { jvResult = rpcError (rpcDST_ACT_MISSING); } - else if (!context.params[jss::destination_account].isString () - || !raDst.setAccountID ( - context.params[jss::destination_account].asString ())) + else if (! deprecatedParseBase58 (raDst, + context.params[jss::destination_account])) { jvResult = rpcError (rpcDST_ACT_MALFORMED); } @@ -140,7 +140,7 @@ Json::Value doRipplePathFind (RPC::Context& context) jvDestCur.append (to_string (uCurrency)); jvResult[jss::destination_currencies] = jvDestCur; - jvResult[jss::destination_account] = raDst.humanAccountID (); + jvResult[jss::destination_account] = getApp().accountIDCache().toBase58(raDst); int level = getConfig().PATH_SEARCH_OLD; if ((getConfig().PATH_SEARCH_MAX > level) @@ -177,9 +177,9 @@ Json::Value doRipplePathFind (RPC::Context& context) } Json::Value -buildSrcCurrencies(RippleAddress const& raSrc, RippleLineCache::pointer const& cache) +buildSrcCurrencies(AccountID const& account, RippleLineCache::pointer const& cache) { - auto currencies = accountSourceCurrencies(raSrc, cache, true); + auto currencies = accountSourceCurrencies(account, cache, true); auto jvSrcCurrencies = Json::Value(Json::arrayValue); for (auto const& uCurrency : currencies) @@ -193,16 +193,16 @@ buildSrcCurrencies(RippleAddress const& raSrc, RippleLineCache::pointer const& c } std::pair -ripplePathFind(RippleLineCache::pointer const& cache, - RippleAddress const& raSrc, RippleAddress const& raDst, +ripplePathFind (RippleLineCache::pointer const& cache, + AccountID const& raSrc, AccountID const& raDst, STAmount const& saDstAmount, Ledger::pointer const& lpLedger, Json::Value const& jvSrcCurrencies, boost::optional const& contextPaths, int const& level) { FindPaths fp( cache, - raSrc.getAccountID(), - raDst.getAccountID(), + raSrc, + raDst, saDstAmount, level, 4); // max paths @@ -230,7 +230,7 @@ ripplePathFind(RippleLineCache::pointer const& cache, } if (uSrcCurrencyID.isNonZero()) - uSrcIssuerID = raSrc.getAccountID(); + uSrcIssuerID = raSrc; // Parse optional issuer. if (jvSource.isMember(jss::issuer) && @@ -275,7 +275,7 @@ ripplePathFind(RippleLineCache::pointer const& cache, isXRP(uSrcIssuerID) ? isXRP(uSrcCurrencyID) ? // Default to source account. xrpAccount() : - AccountID(raSrc.getAccountID()) + (raSrc) : uSrcIssuerID; // Use specifed issuer. STAmount saMaxAmount({ uSrcCurrencyID, issuer }, 1); @@ -288,8 +288,8 @@ ripplePathFind(RippleLineCache::pointer const& cache, 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. + raDst, // --> Account to deliver to. + raSrc, // --> Account sending from. spsComputed); // --> Path set. WriteLog(lsWARNING, RPCHandler) @@ -312,8 +312,8 @@ ripplePathFind(RippleLineCache::pointer const& cache, 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. + raDst, // --> Account to deliver to. + raSrc, // --> Account sending from. spsComputed); // --> Path set. WriteLog(lsDEBUG, PathRequest) << "Extra path element gives " diff --git a/src/ripple/rpc/handlers/Subscribe.cpp b/src/ripple/rpc/handlers/Subscribe.cpp index 05f27403e6..52587abfb8 100644 --- a/src/ripple/rpc/handlers/Subscribe.cpp +++ b/src/ripple/rpc/handlers/Subscribe.cpp @@ -264,12 +264,15 @@ Json::Value doSubscribe (RPC::Context& context) return rpcError (rpcBAD_MARKET); } - RippleAddress raTakerID; + boost::optional takerID; - if (!j.isMember (jss::taker)) - raTakerID.setAccountID (noAccount()); - else if (!raTakerID.setAccountID (j[jss::taker].asString ())) - return rpcError (rpcBAD_ISSUER); + if (j.isMember (jss::taker)) + { + takerID = parseBase58( + j[jss::taker].asString()); + if (! takerID) + return rpcError (rpcBAD_ISSUER); + } if (!isConsistent (book)) { @@ -296,7 +299,7 @@ Json::Value doSubscribe (RPC::Context& context) { context.netOps.getBookPage (context.role == Role::ADMIN, lpLedger, field == jss::asks ? reversed (book) : book, - raTakerID.getAccountID(), false, 0, jvMarker, + takerID ? *takerID : noAccount(), false, 0, jvMarker, jvOffers); if (jvResult.isMember (field)) diff --git a/src/ripple/rpc/handlers/WalletPropose.cpp b/src/ripple/rpc/handlers/WalletPropose.cpp index a14fc98953..6819a5071d 100644 --- a/src/ripple/rpc/handlers/WalletPropose.cpp +++ b/src/ripple/rpc/handlers/WalletPropose.cpp @@ -96,7 +96,7 @@ Json::Value walletPropose (Json::Value const& params) obj[jss::master_seed] = naSeed.humanSeed (); obj[jss::master_seed_hex] = to_string (naSeed.getSeed ()); obj[jss::master_key] = naSeed.humanSeed1751(); - obj[jss::account_id] = naAccount.humanAccountID (); + obj[jss::account_id] = toBase58(calcAccountID(naAccount)); obj[jss::public_key] = naAccount.humanAccountPublic(); obj[jss::key_type] = to_string (type); diff --git a/src/ripple/rpc/impl/AccountFromString.cpp b/src/ripple/rpc/impl/AccountFromString.cpp index cb4ae6f24f..e04ef1962e 100644 --- a/src/ripple/rpc/impl/AccountFromString.cpp +++ b/src/ripple/rpc/impl/AccountFromString.cpp @@ -23,35 +23,41 @@ namespace ripple { namespace RPC { -// --> strIdent: public key, account ID, or regular seed. -// --> bStrict: Only allow account id or public key. -// <-- bIndex: true if iIndex > 0 and used the index. -// -// Returns a Json::objectValue, containing error information if there was one. Json::Value accountFromString ( - RippleAddress& naAccount, + AccountID& result, bool& bIndex, std::string const& strIdent, int const iIndex, bool const bStrict) { - RippleAddress naSeed; - - if (naAccount.setAccountPublic (strIdent) || - naAccount.setAccountID (strIdent)) + // VFALCO Use AnyPublicKey + // Try public key + RippleAddress naAccount; + if (naAccount.setAccountPublic(strIdent)) { - // Got the account. + result = calcAccountID(naAccount); bIndex = false; - return Json::Value (Json::objectValue); + return Json::objectValue; + } + + // Try AccountID + auto accountID = + parseBase58(strIdent); + if (accountID) + { + result = *accountID; + bIndex = false; + return Json::objectValue; } if (bStrict) { - auto success = naAccount.setAccountID ( - strIdent, Base58::getBitcoinAlphabet ()); - return rpcError (success ? rpcACT_BITCOIN : rpcACT_MALFORMED); + accountID = deprecatedParseBitcoinAccountID(strIdent); + return rpcError (accountID ? rpcACT_BITCOIN : rpcACT_MALFORMED); } + RippleAddress naSeed; + // Otherwise, it must be a seed. if (!naSeed.setSeedGeneric (strIdent)) return rpcError (rpcBAD_SEED); @@ -67,7 +73,8 @@ Json::Value accountFromString ( bIndex = !iIndex; naAccount.setAccountPublic (naGenerator, iIndex); - return Json::Value (Json::objectValue); + result = calcAccountID(naAccount); + return Json::objectValue; } } // RPC diff --git a/src/ripple/rpc/impl/AccountFromString.h b/src/ripple/rpc/impl/AccountFromString.h index 130c7f2384..b118169c22 100644 --- a/src/ripple/rpc/impl/AccountFromString.h +++ b/src/ripple/rpc/impl/AccountFromString.h @@ -26,8 +26,13 @@ namespace ripple { namespace RPC { +// --> strIdent: public key, account ID, or regular seed. +// --> bStrict: Only allow account id or public key. +// <-- bIndex: true if iIndex > 0 and used the index. +// +// Returns a Json::objectValue, containing error information if there was one. Json::Value accountFromString ( - RippleAddress& naAccount, + AccountID& result, bool& bIndex, std::string const& strIdent, int iIndex, diff --git a/src/ripple/rpc/impl/Accounts.cpp b/src/ripple/rpc/impl/Accounts.cpp index de829282d1..fbb405c783 100644 --- a/src/ripple/rpc/impl/Accounts.cpp +++ b/src/ripple/rpc/impl/Accounts.cpp @@ -20,6 +20,8 @@ #include #include #include +#include +#include namespace ripple { namespace RPC { @@ -37,18 +39,19 @@ Json::Value accounts ( do { - RippleAddress naAccount; + // VFALCO Should be AnyPublicKey + RippleAddress pk; + pk.setAccountPublic (naMasterGenerator, uIndex++); - naAccount.setAccountPublic (naMasterGenerator, uIndex++); + auto const sle = cachedRead(*lrLedger, + keylet::account(calcAccountID(pk)).key, + getApp().getSLECache(), ltACCOUNT_ROOT); - AccountState::pointer as = - getAccountState (*lrLedger, naAccount, getApp().getSLECache()); - - if (as) + if (sle) { Json::Value jsonAccount (Json::objectValue); - as->addJson (jsonAccount); + injectSLE(jsonAccount, *sle); jsonAccounts.append (jsonAccount); } diff --git a/src/ripple/rpc/impl/ParseAccountIds.cpp b/src/ripple/rpc/impl/ParseAccountIds.cpp index 8b8ce4559e..91cfcec84e 100644 --- a/src/ripple/rpc/impl/ParseAccountIds.cpp +++ b/src/ripple/rpc/impl/ParseAccountIds.cpp @@ -23,22 +23,20 @@ namespace ripple { namespace RPC { -hash_set parseAccountIds (Json::Value const& jvArray) +hash_set +parseAccountIds (Json::Value const& jvArray) { - hash_set result; - + hash_set result; for (auto const& jv: jvArray) { - RippleAddress address; - - if (!(jv.isString () && address.setAccountID ((jv.asString ())))) - { - result.clear (); - break; - } - result.insert (address); + if (! jv.isString()) + return hash_set(); + auto const id = + parseBase58(jv.asString()); + if (! id) + return hash_set(); + result.insert(*id); } - return result; } diff --git a/src/ripple/rpc/impl/ParseAccountIds.h b/src/ripple/rpc/impl/ParseAccountIds.h index 8937d32d0d..db80da12fa 100644 --- a/src/ripple/rpc/impl/ParseAccountIds.h +++ b/src/ripple/rpc/impl/ParseAccountIds.h @@ -20,10 +20,14 @@ #ifndef RIPPLE_RPC_PARSEACCOUNTIDS_H_INCLUDED #define RIPPLE_RPC_PARSEACCOUNTIDS_H_INCLUDED +#include +#include + namespace ripple { namespace RPC { -hash_set parseAccountIds (Json::Value const& jvArray); +hash_set +parseAccountIds (Json::Value const& jvArray); } // RPC } // ripple diff --git a/src/ripple/rpc/impl/RipplePathFind.h b/src/ripple/rpc/impl/RipplePathFind.h index b2a56245f8..c1676729cb 100644 --- a/src/ripple/rpc/impl/RipplePathFind.h +++ b/src/ripple/rpc/impl/RipplePathFind.h @@ -28,11 +28,15 @@ namespace ripple { class RippleAddress; Json::Value -buildSrcCurrencies(RippleAddress const& raSrc, RippleLineCache::pointer const& cache); +buildSrcCurrencies(AccountID const& raSrc, RippleLineCache::pointer const& cache); std::pair -ripplePathFind(RippleLineCache::pointer const& cache, RippleAddress const& raSrc, RippleAddress const& raDst, - STAmount const& saDstAmount, Ledger::pointer const& lpLedger, Json::Value const& jvSrcCurrencies, boost::optional const& contextPaths, int const& level); +ripplePathFind (RippleLineCache::pointer const& cache, + AccountID const& raSrc, AccountID const& raDst, + STAmount const& saDstAmount, Ledger::pointer const& lpLedger, + Json::Value const& jvSrcCurrencies, + boost::optional const& contextPaths, + int const& level); } diff --git a/src/ripple/rpc/impl/TransactionSign.cpp b/src/ripple/rpc/impl/TransactionSign.cpp index 71a3f5b537..3653336b2b 100644 --- a/src/ripple/rpc/impl/TransactionSign.cpp +++ b/src/ripple/rpc/impl/TransactionSign.cpp @@ -18,8 +18,8 @@ //============================================================================== #include -#include #include +#include #include #include #include @@ -40,8 +40,8 @@ namespace detail { class SigningForParams { private: - RippleAddress const* const signingForAcctID_; - RippleAddress const* const multiSigningAcctID_; + AccountID const* const signingForAcctID_; + AccountID const* const multiSigningAcctID_; RippleAddress* const multiSignPublicKey_; Blob* const multiSignature_; public: @@ -55,8 +55,8 @@ public: SigningForParams (SigningForParams const& rhs) = delete; SigningForParams ( - RippleAddress const& signingForAcctID, - RippleAddress const& multiSigningAcctID, + AccountID const& signingForAcctID, + AccountID const& multiSigningAcctID, RippleAddress& multiSignPublicKey, Blob& multiSignature) : signingForAcctID_ (&signingForAcctID) @@ -80,12 +80,12 @@ public: } // Don't call this method unless isMultiSigning() returns true. - RippleAddress const& getSigningFor () + AccountID const& getSigningFor () { return *signingForAcctID_; } - RippleAddress const& getSigner () + AccountID const& getSigner () { return *multiSigningAcctID_; } @@ -105,15 +105,16 @@ public: // TxnSignApiFacade methods -void TxnSignApiFacade::snapshotAccountState (RippleAddress const& accountID) +void TxnSignApiFacade::snapshotAccountState (AccountID const& accountID) { if (!netOPs_) // Unit testing. return; ledger_ = netOPs_->getCurrentLedger (); accountID_ = accountID; - accountState_ = getAccountState ( - *ledger_, accountID_, getApp().getSLECache()); + sle_ = cachedRead(*ledger_, + keylet::account(accountID_).key, + getApp().getSLECache(), ltACCOUNT_ROOT); } bool TxnSignApiFacade::isValidAccount () const @@ -121,7 +122,7 @@ bool TxnSignApiFacade::isValidAccount () const if (!ledger_) // Unit testing. return true; - return static_cast (accountState_); + return static_cast (sle_); } std::uint32_t TxnSignApiFacade::getSeq () const @@ -129,7 +130,7 @@ std::uint32_t TxnSignApiFacade::getSeq () const if (!ledger_) // Unit testing. return 0; - return accountState_->sle().getFieldU32(sfSequence); + return sle_->getFieldU32(sfSequence); } void TxnSignApiFacade::processTransaction ( @@ -145,7 +146,7 @@ void TxnSignApiFacade::processTransaction ( } bool TxnSignApiFacade::findPathsForOneIssuer ( - RippleAddress const& dstAccountID, + AccountID const& dstAccountID, Issue const& srcIssue, STAmount const& dstAmount, int searchLevel, @@ -160,8 +161,8 @@ bool TxnSignApiFacade::findPathsForOneIssuer ( auto cache = std::make_shared (ledger_); return ripple::findPathsForOneIssuer ( cache, - accountID_.getAccountID (), - dstAccountID.getAccountID (), + accountID_, + dstAccountID, srcIssue, dstAmount, searchLevel, @@ -199,12 +200,12 @@ bool TxnSignApiFacade::hasAccountRoot () const } error_code_i acctMatchesPubKey ( - AccountState::pointer accountState, - RippleAddress const& accountID, + std::shared_ptr accountState, + AccountID const& accountID, RippleAddress const& publicKey) { - AccountID const publicKeyAcctID = publicKey.getAccountID (); - bool const isMasterKey = publicKeyAcctID == accountID.getAccountID (); + AccountID const publicKeyAcctID = calcAccountID(publicKey); + bool const isMasterKey = publicKeyAcctID == accountID; // If we can't get the accountRoot, but the accountIDs match, that's // good enough. @@ -216,7 +217,7 @@ error_code_i acctMatchesPubKey ( } // If we *can* get to the accountRoot, check for MASTER_DISABLED - auto const& sle = accountState->sle(); + auto const& sle = *accountState; if (isMasterKey) { if (sle.isFlag(lsfDisableMaster)) @@ -226,7 +227,7 @@ error_code_i acctMatchesPubKey ( // The last gasp is that we have public Regular key. if ((sle.isFieldPresent (sfRegularKey)) && - (publicKeyAcctID == sle.getFieldAccount160 (sfRegularKey))) + (publicKeyAcctID == sle.getAccountID (sfRegularKey))) { return rpcSUCCESS; } @@ -239,21 +240,24 @@ error_code_i TxnSignApiFacade::singleAcctMatchesPubKey ( if (!netOPs_) // Unit testing. return rpcSUCCESS; - return acctMatchesPubKey (accountState_, accountID_, publicKey); + return acctMatchesPubKey (sle_, accountID_, publicKey); } error_code_i TxnSignApiFacade::multiAcctMatchesPubKey ( - RippleAddress const& accountID, + AccountID const& accountID, RippleAddress const& publicKey) const { - AccountState::pointer accountState; + std::shared_ptr accountState; // VFALCO Do we need to check netOPs_? if (netOPs_ && ledger_) - // If it's available, get the AccountState for the multi-signer's - // accountID. It's okay if the AccountState is not available, + { + // If it's available, get the account root for the multi-signer's + // accountID. It's okay if the account root is not available, // since they might be signing with a phantom (unfunded) account. - accountState = getAccountState ( - *ledger_, accountID, getApp().getSLECache()); + accountState = cachedRead(*ledger_, + keylet::account(accountID).key, + getApp().getSLECache(), ltACCOUNT_ROOT); + } return acctMatchesPubKey (accountState, accountID, publicKey); } @@ -356,7 +360,7 @@ enum class PathFind : unsigned char static Json::Value checkPayment( Json::Value const& params, Json::Value& tx_json, - RippleAddress const& raSrcAddressID, + AccountID const& raSrcAddressID, TxnSignApiFacade const& apiFacade, Role const role, PathFind const doPath) @@ -365,8 +369,6 @@ static Json::Value checkPayment( if (tx_json[jss::TransactionType].asString () != "Payment") return Json::Value(); - RippleAddress dstAccountID; - if (!tx_json.isMember (jss::Amount)) return RPC::missing_field_error ("tx_json.Amount"); @@ -378,7 +380,9 @@ static Json::Value checkPayment( if (!tx_json.isMember (jss::Destination)) return RPC::missing_field_error ("tx_json.Destination"); - if (!dstAccountID.setAccountID (tx_json[jss::Destination].asString ())) + auto const dstAccountID = parseBase58( + tx_json[jss::Destination].asString()); + if (! dstAccountID) return RPC::invalid_field_error ("tx_json.Destination"); if ((doPath == PathFind::dont) && params.isMember (jss::build_path)) @@ -402,7 +406,7 @@ static Json::Value checkPayment( { // If no SendMax, default to Amount with sender as issuer. saSendMax = amount; - saSendMax.setIssuer (raSrcAddressID.getAccountID ()); + saSendMax.setIssuer (raSrcAddressID); } if (saSendMax.native () && amount.native ()) @@ -417,7 +421,7 @@ static Json::Value checkPayment( STPathSet spsPaths; STPath fullLiquidityPath; bool valid = apiFacade.findPathsForOneIssuer ( - dstAccountID, + *dstAccountID, saSendMax.issue (), amount, getConfig ().PATH_SEARCH_OLD, @@ -446,20 +450,20 @@ static Json::Value checkPayment( // Validate (but don't modify) the contents of the tx_json. // -// Returns a pair. The Json::Value is non-empty +// Returns a pair. The Json::Value is non-empty // and contains as error if there was an error. The returned RippleAddress // is the "Account" addressID if there was no error. // // This code does not check the "Sequence" field, since the expectations // for that field are particularly context sensitive. -static std::pair +static std::pair checkTxJsonFields ( Json::Value const& tx_json, TxnSignApiFacade const& apiFacade, Role const role, bool const verify) { - std::pair ret; + std::pair ret; if (! tx_json.isObject ()) { @@ -480,9 +484,10 @@ checkTxJsonFields ( return ret; } - RippleAddress srcAddressID; + auto const srcAddressID = parseBase58( + tx_json[jss::Account].asString()); - if (! srcAddressID.setAccountID (tx_json[jss::Account].asString ())) + if (! srcAddressID) { ret.first = RPC::make_error (rpcSRC_ACT_MALFORMED, RPC::invalid_field_message ("tx_json.Account")); @@ -506,7 +511,7 @@ checkTxJsonFields ( } // It's all good. Return the AddressID. - ret.second = std::move (srcAddressID); + ret.second = *srcAddressID; return ret; } @@ -542,7 +547,9 @@ struct transactionPreProcessResult { } }; -static transactionPreProcessResult transactionPreProcessImpl ( +static +transactionPreProcessResult +transactionPreProcessImpl ( Json::Value& params, TxnSignApiFacade& apiFacade, Role role, @@ -569,7 +576,7 @@ static transactionPreProcessResult transactionPreProcessImpl ( if (RPC::contains_error (txJsonResult.first)) return std::move (txJsonResult.first); - RippleAddress const raSrcAddressID = std::move (txJsonResult.second); + auto const raSrcAddressID = txJsonResult.second; // This test covers the case where we're offline so the sequence number // cannot be determined locally. If we're offline then the caller must @@ -586,7 +593,7 @@ static transactionPreProcessResult transactionPreProcessImpl ( WriteLog (lsDEBUG, RPCHandler) << "transactionSign: Failed to find source account " << "in current ledger: " - << raSrcAddressID.humanAccountID(); + << toBase58(raSrcAddressID); return rpcError (rpcSRC_ACT_NOT_FOUND); } @@ -630,8 +637,8 @@ static transactionPreProcessResult transactionPreProcessImpl ( return rpcError (rpcSRC_ACT_NOT_FOUND); WriteLog (lsTRACE, RPCHandler) << - "verify: " << keypair.publicKey.humanAccountID() << - " : " << raSrcAddressID.humanAccountID(); + "verify: " << toBase58(calcAccountID(keypair.publicKey)) << + " : " << toBase58(raSrcAddressID); // If multisigning then we need to return the public key. if (signingArgs.isMultiSigning()) @@ -687,8 +694,8 @@ static transactionPreProcessResult transactionPreProcessImpl ( // If multisign then return multiSignature, else set TxnSignature field. if (signingArgs.isMultiSigning ()) { - Serializer s = stpTrans->getMultiSigningData ( - signingArgs.getSigningFor (), signingArgs.getSigner ()); + Serializer s = stpTrans->getMultiSigningData( + signingArgs.getSigningFor(), signingArgs.getSigner()); Blob multiSignature = keypair.secretKey.accountPrivateSign(s.getData()); signingArgs.moveMultiSignature (std::move (multiSignature)); } @@ -787,15 +794,16 @@ Json::Value transactionFormatResultImpl (Transaction::pointer tpTrans) void insertMultiSigners ( Json::Value& jvResult, - RippleAddress const& signingForAcctID, - RippleAddress const& signingAcctID, + AccountID const& signingForAcctID, + AccountID const& signingAcctID, RippleAddress const& accountPublic, Blob const& signature) { // Build a SigningAccount object to inject into the SigningAccounts. Json::Value signingAccount (Json::objectValue); - signingAccount[sfAccount.getJsonName ()] = signingAcctID.humanAccountID (); + signingAccount[sfAccount.getJsonName ()] = + getApp().accountIDCache().toBase58(signingAcctID); signingAccount[sfSigningPubKey.getJsonName ()] = strHex (accountPublic.getAccountPublic ()); @@ -813,7 +821,8 @@ void insertMultiSigners ( // Put the signingForAcctID and the SigningAccounts in the SigningFor. Json::Value signingFor (Json::objectValue); - signingFor[sfAccount.getJsonName ()] = signingForAcctID.humanAccountID (); + signingFor[sfAccount.getJsonName ()] = + getApp().accountIDCache().toBase58(signingForAcctID); signingFor[sfSigningAccounts.getJsonName ()] = signingAccounts; @@ -949,9 +958,9 @@ Json::Value transactionSignFor ( return RPC::missing_field_error (accountField); // Turn the signer's account into a RippleAddress for multi-sign. - RippleAddress multiSignAddrID; - if (! multiSignAddrID.setAccountID ( - jvRequest[accountField].asString ())) + auto const multiSignAddrID = parseBase58( + jvRequest[accountField].asString()); + if (! multiSignAddrID) { return RPC::make_error (rpcSRC_ACT_MALFORMED, RPC::invalid_field_message (accountField)); @@ -964,9 +973,9 @@ Json::Value transactionSignFor ( return RPC::missing_field_error (signing_forField); // Turn the signing_for account into a RippleAddress for multi-sign. - RippleAddress multiSignForAddrID; - if (! multiSignForAddrID.setAccountID ( - jvRequest[signing_forField].asString ())) + auto const multiSignForAddrID = parseBase58( + jvRequest[signing_forField].asString ()); + if (! multiSignForAddrID) { return RPC::make_error (rpcSIGN_FOR_MALFORMED, RPC::invalid_field_message (signing_forField)); @@ -984,8 +993,9 @@ Json::Value transactionSignFor ( // Add and amend fields based on the transaction type. Blob multiSignature; RippleAddress multiSignPubKey; - SigningForParams signForParams ( - multiSignForAddrID, multiSignAddrID, multiSignPubKey, multiSignature); + SigningForParams signForParams( + *multiSignForAddrID, *multiSignAddrID, + multiSignPubKey, multiSignature); transactionPreProcessResult preprocResult = transactionPreProcessImpl ( @@ -1000,7 +1010,7 @@ Json::Value transactionSignFor ( // Make sure the multiSignAddrID can legitimately multi-sign. { error_code_i const err = - apiFacade.multiAcctMatchesPubKey (multiSignAddrID, multiSignPubKey); + apiFacade.multiAcctMatchesPubKey(*multiSignAddrID, multiSignPubKey); if (err != rpcSUCCESS) return rpcError (err); @@ -1019,7 +1029,7 @@ Json::Value transactionSignFor ( // Finally, do what we were called for: return a SigningFor object. insertMultiSigners (json, - multiSignForAddrID, multiSignAddrID, multiSignPubKey, multiSignature); + *multiSignForAddrID, *multiSignAddrID, multiSignPubKey, multiSignature); return json; } @@ -1049,7 +1059,7 @@ Json::Value transactionSubmitMultiSigned ( if (RPC::contains_error (txJsonResult.first)) return std::move (txJsonResult.first); - RippleAddress const raSrcAddressID = std::move (txJsonResult.second); + auto const raSrcAddressID = txJsonResult.second; apiFacade.snapshotAccountState (raSrcAddressID); if (!apiFacade.isValidAccount ()) @@ -1058,7 +1068,7 @@ Json::Value transactionSubmitMultiSigned ( WriteLog (lsDEBUG, RPCHandler) << "transactionSubmitMultiSigned: Failed to find source account " << "in current ledger: " - << raSrcAddressID.humanAccountID (); + << toBase58(raSrcAddressID); return rpcError (rpcSRC_ACT_NOT_FOUND); } @@ -1199,15 +1209,18 @@ Json::Value transactionSubmitMultiSigned ( } // Lambdas for sorting arrays and finding duplicates. - auto byFieldAccountID = - [] (STObject const& a, STObject const& b) { - return (a.getFieldAccount (sfAccount).getAccountID () < - b.getFieldAccount (sfAccount).getAccountID ()); }; + auto byFieldAccountID = [](STObject const& a, STObject const& b) + { + return a.getAccountID(sfAccount) < + b.getAccountID(sfAccount); + }; auto ifDuplicateAccountID = - [] (STObject const& a, STObject const& b) { - return (a.getFieldAccount (sfAccount).getAccountID () == - b.getFieldAccount (sfAccount).getAccountID ()); }; + [](STObject const& a, STObject const& b) + { + return a.getAccountID(sfAccount) == + b.getAccountID(sfAccount); + }; { // MultiSigners are submitted sorted in AccountID order. This @@ -1224,7 +1237,7 @@ Json::Value transactionSubmitMultiSigned ( { std::ostringstream err; err << "Duplicate SigningFor:Account entries (" - << dupAccountItr->getFieldAccount (sfAccount).humanAccountID () + << getApp().accountIDCache().toBase58(dupAccountItr->getAccountID(sfAccount)) << ") are not allowed."; return RPC::make_param_error(err.str ()); } @@ -1246,25 +1259,23 @@ Json::Value transactionSubmitMultiSigned ( { std::ostringstream err; err << "Duplicate SigningAccounts:SigningAccount:Account entries (" - << dupAccountItr->getFieldAccount (sfAccount).humanAccountID () + << getApp().accountIDCache().toBase58(dupAccountItr->getAccountID(sfAccount)) << ") are not allowed."; return RPC::make_param_error(err.str ()); } // An account may not sign for itself. - RippleAddress const signingForAcct = - signingFor.getFieldAccount (sfAccount); - - auto const selfSigningItr = std::find_if( - signingAccts.begin (), signingAcctsEnd, - [&signingForAcct](STObject const& elem) - { return elem.getFieldAccount (sfAccount) == signingForAcct; }); - - if (selfSigningItr != signingAcctsEnd) + auto const account = + signingFor.getAccountID(sfAccount); + if (std::find_if (signingAccts.begin(), signingAcctsEnd, + [&account](STObject const& elem) + { + return elem.getAccountID(sfAccount) == account; + }) != signingAcctsEnd) { std::ostringstream err; err << "A SigningAccount may not SignFor itself (" - << signingForAcct.humanAccountID () << ")."; + << getApp().accountIDCache().toBase58(account) << ")."; return RPC::make_param_error(err.str ()); } } diff --git a/src/ripple/rpc/impl/TransactionSign.h b/src/ripple/rpc/impl/TransactionSign.h index 2da4d2e9e6..6ae4679838 100644 --- a/src/ripple/rpc/impl/TransactionSign.h +++ b/src/ripple/rpc/impl/TransactionSign.h @@ -24,6 +24,7 @@ namespace ripple { namespace RPC { namespace detail { + // A class that allows these methods to be called with or without a // real NetworkOPs instance. This allows for unit testing. class TxnSignApiFacade @@ -31,8 +32,8 @@ class TxnSignApiFacade private: NetworkOPs* const netOPs_; Ledger::pointer ledger_; - RippleAddress accountID_; - AccountState::pointer accountState_; + AccountID accountID_; + std::shared_ptr sle_; public: // Enum used to construct a Facade for unit tests. @@ -59,14 +60,14 @@ public: , ledger_ (ledger) { } - void snapshotAccountState (RippleAddress const& accountID); + void snapshotAccountState (AccountID const& accountID); bool isValidAccount () const; std::uint32_t getSeq () const; bool findPathsForOneIssuer ( - RippleAddress const& dstAccountID, + AccountID const& dstAccountID, Issue const& srcIssue, STAmount const& dstAmount, int searchLevel, @@ -90,7 +91,7 @@ public: RippleAddress const& publicKey) const; error_code_i multiAcctMatchesPubKey ( - RippleAddress const& acctID, + AccountID const& acctID, RippleAddress const& publicKey) const; int getValidatedLedgerAge () const; diff --git a/src/ripple/test/jtx/impl/Account.cpp b/src/ripple/test/jtx/impl/Account.cpp index ee2f856507..7484e137bc 100644 --- a/src/ripple/test/jtx/impl/Account.cpp +++ b/src/ripple/test/jtx/impl/Account.cpp @@ -20,6 +20,7 @@ #include #include #include +#include namespace ripple { namespace test { @@ -53,8 +54,8 @@ Account::Account( { pk_ = std::move(keys.publicKey); sk_ = std::move(keys.secretKey); - id_ = pk_.getAccountID(); - human_ = pk_.humanAccountID(); + id_ = calcAccountID(pk_); + human_ = toBase58(id_); } Account::Account (std::string name, diff --git a/src/ripple/test/jtx/impl/Env.cpp b/src/ripple/test/jtx/impl/Env.cpp index 0bff914ade..e121d6b6b8 100644 --- a/src/ripple/test/jtx/impl/Env.cpp +++ b/src/ripple/test/jtx/impl/Env.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include // VFALCO TODO Use AnyPublicKey, AnySecretKey, AccountID @@ -80,11 +81,12 @@ Env::lookup (AccountID const& id) const Account const& Env::lookup (std::string const& base58ID) const { - RippleAddress ra; - if (! ra.setAccountID(base58ID)) + auto const account = + parseBase58(base58ID); + if (! account) throw std::runtime_error( "Env::lookup: invalid account ID"); - return lookup(ra.getAccountID()); + return lookup(*account); } PrettyAmount @@ -240,7 +242,7 @@ Env::autofill_sig (JTx& jt) auto const ar = le(account); if (ar && ar->isFieldPresent(sfRegularKey)) jtx::sign(jv, lookup( - ar->getFieldAccount160(sfRegularKey))); + ar->getAccountID(sfRegularKey))); else jtx::sign(jv, account); } diff --git a/src/ripple/test/jtx/impl/multisign.cpp b/src/ripple/test/jtx/impl/multisign.cpp index 06b9b7038d..e99ac8a114 100644 --- a/src/ripple/test/jtx/impl/multisign.cpp +++ b/src/ripple/test/jtx/impl/multisign.cpp @@ -22,6 +22,7 @@ #include #include #include +#include namespace ripple { namespace test { @@ -82,12 +83,16 @@ msig::operator()(Env const& env, JTx& jt) const env.test.log << pretty(jt.jv); throw; } - auto const signingForID = [](Json::Value const& jv) - { - RippleAddress ra; - ra.setAccountID(jv[jss::Account].asString()); - return ra.getAccountID(); - }(jt.jv); + auto const signFor = + parseBase58( + jt.jv[jss::Account].asString()); + if (! signFor) + { + env.test.log << + "invalid AccountID: '" << + jt.jv[jss::Account].asString() << "'"; + throw parse_error("msig: bad Account"); + } auto& jv = jt["MultiSigners"][0u]["SigningFor"]; jv[jss::Account] = jt[jss::Account]; auto& js = jv["SigningAccounts"]; @@ -103,7 +108,7 @@ msig::operator()(Env const& env, JTx& jt) const Serializer ss; ss.add32 (HashPrefix::txMultiSign); st->addWithoutSigningFields(ss); - ss.add160(signingForID); + ss.add160(*signFor); ss.add160(e.id()); jo["MultiSignature"] = strHex(make_Slice( e.sk().accountPrivateSign(ss.getData()))); diff --git a/src/ripple/test/jtx/impl/utility.cpp b/src/ripple/test/jtx/impl/utility.cpp index 2fba02e5e3..ab837bf548 100644 --- a/src/ripple/test/jtx/impl/utility.cpp +++ b/src/ripple/test/jtx/impl/utility.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include namespace ripple { @@ -71,12 +72,14 @@ fill_seq (Json::Value& jv, { if (jv.isMember(jss::Sequence)) return; - // VFALCO TODO Use - // parseBase58(jv[jss::Account].asString()) - RippleAddress ra; - ra.setAccountID(jv[jss::Account].asString()); + auto const account = + parseBase58( + jv[jss::Account].asString()); + if (! account) + throw parse_error( + "unexpected invalid Account"); auto const ar = ledger.read( - keylet::account(ra.getAccountID())); + keylet::account(*account)); if (!ar) return; jv[jss::Sequence] = diff --git a/src/ripple/unity/app_misc.cpp b/src/ripple/unity/app_misc.cpp index d0798a8471..8a1fad248c 100644 --- a/src/ripple/unity/app_misc.cpp +++ b/src/ripple/unity/app_misc.cpp @@ -19,7 +19,6 @@ #include -#include #include #include #include diff --git a/src/ripple/unity/protocol.cpp b/src/ripple/unity/protocol.cpp index a65aa47eb4..93209ce2f1 100644 --- a/src/ripple/unity/protocol.cpp +++ b/src/ripple/unity/protocol.cpp @@ -19,6 +19,7 @@ #include +#include #include #include #include @@ -36,6 +37,7 @@ #include #include #include +#include #include #include @@ -64,6 +66,7 @@ #include #include #include +#include #if DOXYGEN #include