From 2f485672fad15071a1164cdf9d06db0f587f36e7 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Thu, 18 Jun 2015 11:05:18 -0700 Subject: [PATCH] Refactor AccountID (RIPD-953): All AccountID functionality is removed from RippleAddress and replaced with free functions. The AccountID to string conversion cache is factored out as an explicit type with an instance in the Application object. New base58 conversion functions are used, with no dependence on OpenSSL. All types and free functions related to AccountID are consolidated into one header file. Routines to operate on "tokens" are also introduced and consolidated into a single header file. A token one of the cryptographic primitives used in Ripple: Secret Seed Server Public Key Server Secret Key Account ID Account Public Key Account Private Key and these deprecated primitives: Account Family Seed Account Family Generator --- Builds/VisualStudio2013/RippleD.vcxproj | 30 +- .../VisualStudio2013/RippleD.vcxproj.filters | 33 +- src/ripple/app/ledger/AcceptedLedgerTx.cpp | 13 +- src/ripple/app/ledger/AcceptedLedgerTx.h | 7 +- src/ripple/app/ledger/Ledger.cpp | 73 ++-- src/ripple/app/ledger/Ledger.h | 31 +- src/ripple/app/ledger/MetaView.h | 2 +- src/ripple/app/ledger/impl/MetaView.cpp | 29 +- .../app/ledger/tests/DeferredCredits.test.cpp | 5 +- src/ripple/app/ledger/tests/common_ledger.cpp | 30 +- src/ripple/app/main/Application.cpp | 19 +- src/ripple/app/main/Application.h | 4 +- src/ripple/app/misc/AccountState.cpp | 73 ---- src/ripple/app/misc/AmendmentTableImpl.cpp | 2 +- src/ripple/app/misc/CanonicalTXSet.cpp | 2 +- src/ripple/app/misc/FeeVoteImpl.cpp | 2 +- src/ripple/app/misc/NetworkOPs.cpp | 123 ++----- src/ripple/app/misc/NetworkOPs.h | 15 +- src/ripple/app/misc/UniqueNodeList.cpp | 2 +- src/ripple/app/misc/impl/AccountTxPaging.cpp | 11 +- src/ripple/app/misc/impl/AccountTxPaging.h | 2 +- .../app/misc/tests/AccountTxPaging.test.cpp | 6 +- src/ripple/app/paths/AccountCurrencies.cpp | 16 +- src/ripple/app/paths/AccountCurrencies.h | 19 +- src/ripple/app/paths/PathRequest.cpp | 119 ++++--- src/ripple/app/paths/PathRequest.h | 6 +- src/ripple/app/paths/cursor/AdvanceNode.cpp | 2 +- src/ripple/app/paths/tests/Path_test.cpp | 212 ----------- src/ripple/app/tx/Transaction.h | 3 +- src/ripple/app/tx/TransactionMeta.h | 7 +- src/ripple/app/tx/impl/CancelTicket.cpp | 4 +- src/ripple/app/tx/impl/Change.cpp | 4 +- src/ripple/app/tx/impl/CreateOffer.cpp | 2 +- src/ripple/app/tx/impl/CreateTicket.cpp | 6 +- src/ripple/app/tx/impl/LocalTxs.cpp | 12 +- src/ripple/app/tx/impl/Offer.h | 2 +- src/ripple/app/tx/impl/Payment.cpp | 6 +- src/ripple/app/tx/impl/SetRegularKey.cpp | 7 +- src/ripple/app/tx/impl/SetSignerList.cpp | 2 +- src/ripple/app/tx/impl/SignerEntries.cpp | 2 +- src/ripple/app/tx/impl/Transaction.cpp | 6 +- src/ripple/app/tx/impl/TransactionEngine.cpp | 2 +- src/ripple/app/tx/impl/TransactionMeta.cpp | 39 +-- src/ripple/app/tx/impl/Transactor.cpp | 30 +- src/ripple/app/tx/tests/MultiSign.test.cpp | 23 +- src/ripple/app/tx/tests/common_transactor.cpp | 48 ++- src/ripple/app/tx/tests/common_transactor.h | 9 +- src/ripple/ledger/ViewAPI.h | 1 + src/ripple/ledger/impl/ViewAPI.cpp | 12 +- src/ripple/net/InfoSub.h | 14 +- src/ripple/net/impl/InfoSub.cpp | 12 +- src/ripple/net/impl/RPCCall.cpp | 28 +- src/ripple/overlay/impl/Manifest.cpp | 4 +- src/ripple/protocol/AccountID.h | 194 ++++++++++ src/ripple/protocol/Indexes.h | 6 - src/ripple/protocol/JsonFields.h | 4 +- src/ripple/protocol/RippleAddress.h | 35 +- src/ripple/protocol/STAccount.h | 7 +- src/ripple/protocol/STLedgerEntry.h | 12 +- src/ripple/protocol/STObject.h | 22 +- src/ripple/protocol/STTx.h | 9 +- src/ripple/protocol/UintTypes.h | 38 +- src/ripple/protocol/impl/AccountID.cpp | 239 +++++++++++++ src/ripple/protocol/impl/AnyPublicKey.cpp | 2 +- src/ripple/protocol/impl/Indexes.cpp | 13 - src/ripple/protocol/impl/RippleAddress.cpp | 249 ++++--------- src/ripple/protocol/impl/STAccount.cpp | 26 +- src/ripple/protocol/impl/STLedgerEntry.cpp | 25 -- src/ripple/protocol/impl/STObject.cpp | 35 +- src/ripple/protocol/impl/STParsedJSON.cpp | 34 +- src/ripple/protocol/impl/STTx.cpp | 52 ++- src/ripple/protocol/impl/UintTypes.cpp | 32 +- src/ripple/protocol/impl/digest.cpp | 14 +- src/ripple/protocol/impl/tokens.cpp | 331 ++++++++++++++++++ src/ripple/protocol/tests/Issue.test.cpp | 2 +- .../protocol/tests/RippleAddress.test.cpp | 5 +- src/ripple/protocol/tests/STTx.test.cpp | 22 +- .../tests/types_test.cpp} | 53 +-- src/ripple/protocol/tokens.h | 100 ++++++ src/ripple/protocol/types.h | 27 ++ src/ripple/rpc/handlers/AccountCurrencies.cpp | 9 +- src/ripple/rpc/handlers/AccountInfo.cpp | 20 +- src/ripple/rpc/handlers/AccountLines.cpp | 51 ++- src/ripple/rpc/handlers/AccountObjects.cpp | 12 +- src/ripple/rpc/handlers/AccountOffers.cpp | 14 +- src/ripple/rpc/handlers/AccountTx.cpp | 13 +- src/ripple/rpc/handlers/AccountTxOld.cpp | 11 +- src/ripple/rpc/handlers/BookOffers.cpp | 14 +- src/ripple/rpc/handlers/GatewayBalances.cpp | 25 +- src/ripple/rpc/handlers/LedgerEntry.cpp | 76 ++-- src/ripple/rpc/handlers/NoRippleCheck.cpp | 29 +- src/ripple/rpc/handlers/OwnerInfo.cpp | 14 +- src/ripple/rpc/handlers/RipplePathFind.cpp | 42 +-- src/ripple/rpc/handlers/Subscribe.cpp | 15 +- src/ripple/rpc/handlers/WalletPropose.cpp | 2 +- src/ripple/rpc/impl/AccountFromString.cpp | 39 ++- src/ripple/rpc/impl/AccountFromString.h | 7 +- src/ripple/rpc/impl/Accounts.cpp | 17 +- src/ripple/rpc/impl/ParseAccountIds.cpp | 22 +- src/ripple/rpc/impl/ParseAccountIds.h | 6 +- src/ripple/rpc/impl/RipplePathFind.h | 10 +- src/ripple/rpc/impl/TransactionSign.cpp | 175 ++++----- src/ripple/rpc/impl/TransactionSign.h | 11 +- src/ripple/test/jtx/impl/Account.cpp | 5 +- src/ripple/test/jtx/impl/Env.cpp | 10 +- src/ripple/test/jtx/impl/multisign.cpp | 19 +- src/ripple/test/jtx/impl/utility.cpp | 13 +- src/ripple/unity/app_misc.cpp | 1 - src/ripple/unity/protocol.cpp | 3 + 109 files changed, 1901 insertions(+), 1545 deletions(-) delete mode 100644 src/ripple/app/misc/AccountState.cpp delete mode 100644 src/ripple/app/paths/tests/Path_test.cpp create mode 100644 src/ripple/protocol/AccountID.h create mode 100644 src/ripple/protocol/impl/AccountID.cpp create mode 100644 src/ripple/protocol/impl/tokens.cpp rename src/ripple/{app/misc/AccountState.h => protocol/tests/types_test.cpp} (52%) create mode 100644 src/ripple/protocol/tokens.h create mode 100644 src/ripple/protocol/types.h 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