diff --git a/Builds/VisualStudio2013/RippleD.vcxproj b/Builds/VisualStudio2013/RippleD.vcxproj
index 5a8bd7980..5a479f379 100644
--- a/Builds/VisualStudio2013/RippleD.vcxproj
+++ b/Builds/VisualStudio2013/RippleD.vcxproj
@@ -1730,6 +1730,9 @@
+
+ True
+
True
diff --git a/Builds/VisualStudio2013/RippleD.vcxproj.filters b/Builds/VisualStudio2013/RippleD.vcxproj.filters
index 9a9a59cb1..bb96d05e1 100644
--- a/Builds/VisualStudio2013/RippleD.vcxproj.filters
+++ b/Builds/VisualStudio2013/RippleD.vcxproj.filters
@@ -2586,6 +2586,9 @@
ripple\app\ledger
+
+ ripple\app\ledger
+
ripple\app\ledger
diff --git a/src/ripple/app/consensus/LedgerConsensus.cpp b/src/ripple/app/consensus/LedgerConsensus.cpp
index 46e35c756..83e1dadb4 100644
--- a/src/ripple/app/consensus/LedgerConsensus.cpp
+++ b/src/ripple/app/consensus/LedgerConsensus.cpp
@@ -1452,174 +1452,6 @@ private:
msg, protocol::mtHAVE_SET)));
}
- /** Apply a set of transactions to a ledger
-
- @param set The set of transactions to apply
- @param applyLedger The ledger to which the transactions should
- be applied.
- @param checkLedger A reference ledger for determining error
- messages (typically new last closed ledger).
- @param retriableTransactions collect failed transactions in this set
- @param openLgr true if applyLedger is open, else false.
- */
- void applyTransactions (SHAMap::ref set, Ledger::ref applyLedger,
- Ledger::ref checkLedger, CanonicalTXSet& retriableTransactions,
- bool openLgr)
- {
- TransactionEngine engine (applyLedger);
-
- if (set)
- {
- for (SHAMapItem::pointer item = set->peekFirstItem (); !!item;
- item = set->peekNextItem (item->getTag ()))
- {
- // If the checkLedger doesn't have the transaction
- if (!checkLedger->hasTransaction (item->getTag ()))
- {
- // Then try to apply the transaction to applyLedger
- WriteLog (lsINFO, LedgerConsensus) <<
- "Processing candidate transaction: " << item->getTag ();
- try
- {
- SerializerIterator sit (item->peekSerializer ());
- STTx::pointer txn
- = std::make_shared(sit);
- if (applyTransaction (engine, txn,
- openLgr, true) == resultRetry)
- {
- // On failure, stash the failed transaction for
- // later retry.
- retriableTransactions.push_back (txn);
- }
- }
- catch (...)
- {
- WriteLog (lsWARNING, LedgerConsensus) << " Throws";
- }
- }
- }
- }
-
- int changes;
- bool certainRetry = true;
- // Attempt to apply all of the retriable transactions
- for (int pass = 0; pass < LEDGER_TOTAL_PASSES; ++pass)
- {
- WriteLog (lsDEBUG, LedgerConsensus) << "Pass: " << pass << " Txns: "
- << retriableTransactions.size ()
- << (certainRetry ? " retriable" : " final");
- changes = 0;
-
- auto it = retriableTransactions.begin ();
-
- while (it != retriableTransactions.end ())
- {
- try
- {
- switch (applyTransaction (engine, it->second,
- openLgr, certainRetry))
- {
- case resultSuccess:
- it = retriableTransactions.erase (it);
- ++changes;
- break;
-
- case resultFail:
- it = retriableTransactions.erase (it);
- break;
-
- case resultRetry:
- ++it;
- }
- }
- catch (...)
- {
- WriteLog (lsWARNING, LedgerConsensus)
- << "Transaction throws";
- it = retriableTransactions.erase (it);
- }
- }
-
- WriteLog (lsDEBUG, LedgerConsensus) << "Pass: "
- << pass << " finished " << changes << " changes";
-
- // A non-retry pass made no changes
- if (!changes && !certainRetry)
- return;
-
- // Stop retriable passes
- if ((!changes) || (pass >= LEDGER_RETRY_PASSES))
- certainRetry = false;
- }
-
- // If there are any transactions left, we must have
- // tried them in at least one final pass
- assert (retriableTransactions.empty() || !certainRetry);
- }
-
- /** Apply a transaction to a ledger
-
- @param engine The transaction engine containing the ledger.
- @param txn The transaction to be applied to ledger.
- @param openLedger true if ledger is open
- @param retryAssured true if the transaction should be retried on failure.
- @return One of resultSuccess, resultFail or resultRetry.
- */
- int applyTransaction (TransactionEngine& engine
- , STTx::ref txn, bool openLedger, bool retryAssured)
- {
- // Returns false if the transaction has need not be retried.
- TransactionEngineParams parms = openLedger ? tapOPEN_LEDGER : tapNONE;
-
- if (retryAssured)
- {
- parms = static_cast (parms | tapRETRY);
- }
-
- if (getApp().getHashRouter ().setFlag (txn->getTransactionID ()
- , SF_SIGGOOD))
- {
- parms = static_cast
- (parms | tapNO_CHECK_SIGN);
- }
- WriteLog (lsDEBUG, LedgerConsensus) << "TXN "
- << txn->getTransactionID ()
- << (openLedger ? " open" : " closed")
- << (retryAssured ? "/retry" : "/final");
- WriteLog (lsTRACE, LedgerConsensus) << txn->getJson (0);
-
- try
- {
- bool didApply;
- TER result = engine.applyTransaction (*txn, parms, didApply);
-
- if (didApply)
- {
- WriteLog (lsDEBUG, LedgerConsensus)
- << "Transaction success: " << transHuman (result);
- return resultSuccess;
- }
-
- if (isTefFailure (result) || isTemMalformed (result) ||
- isTelLocal (result))
- {
- // failure
- WriteLog (lsDEBUG, LedgerConsensus)
- << "Transaction failure: " << transHuman (result);
- return resultFail;
- }
-
- WriteLog (lsDEBUG, LedgerConsensus)
- << "Transaction retry: " << transHuman (result);
- return resultRetry;
- }
- catch (...)
- {
- WriteLog (lsWARNING, LedgerConsensus) << "Throws";
- return resultFail;
- }
- }
-
/**
Round the close time to the close time resolution.
@@ -2164,4 +1996,173 @@ make_LedgerConsensus (LedgerConsensus::clock_type& clock, LocalTxs& localtx,
prevLCLHash, previousLedger, closeTime, feeVote);
}
+/** Apply a transaction to a ledger
+
+ @param engine The transaction engine containing the ledger.
+ @param txn The transaction to be applied to ledger.
+ @param openLedger true if ledger is open
+ @param retryAssured true if the transaction should be retried on failure.
+ @return One of resultSuccess, resultFail or resultRetry.
+*/
+static
+int applyTransaction (TransactionEngine& engine
+ , STTx::ref txn, bool openLedger, bool retryAssured)
+{
+ // Returns false if the transaction has need not be retried.
+ TransactionEngineParams parms = openLedger ? tapOPEN_LEDGER : tapNONE;
+
+ if (retryAssured)
+ {
+ parms = static_cast (parms | tapRETRY);
+ }
+
+ if (getApp().getHashRouter ().setFlag (txn->getTransactionID ()
+ , SF_SIGGOOD))
+ {
+ parms = static_cast
+ (parms | tapNO_CHECK_SIGN);
+ }
+ WriteLog (lsDEBUG, LedgerConsensus) << "TXN "
+ << txn->getTransactionID ()
+ << (openLedger ? " open" : " closed")
+ << (retryAssured ? "/retry" : "/final");
+ WriteLog (lsTRACE, LedgerConsensus) << txn->getJson (0);
+
+ try
+ {
+ bool didApply;
+ TER result = engine.applyTransaction (*txn, parms, didApply);
+
+ if (didApply)
+ {
+ WriteLog (lsDEBUG, LedgerConsensus)
+ << "Transaction success: " << transHuman (result);
+ return LedgerConsensusImp::resultSuccess;
+ }
+
+ if (isTefFailure (result) || isTemMalformed (result) ||
+ isTelLocal (result))
+ {
+ // failure
+ WriteLog (lsDEBUG, LedgerConsensus)
+ << "Transaction failure: " << transHuman (result);
+ return LedgerConsensusImp::resultFail;
+ }
+
+ WriteLog (lsDEBUG, LedgerConsensus)
+ << "Transaction retry: " << transHuman (result);
+ return LedgerConsensusImp::resultRetry;
+ }
+ catch (...)
+ {
+ WriteLog (lsWARNING, LedgerConsensus) << "Throws";
+ return LedgerConsensusImp::resultFail;
+ }
+}
+
+/** Apply a set of transactions to a ledger
+
+ @param set The set of transactions to apply
+ @param applyLedger The ledger to which the transactions should
+ be applied.
+ @param checkLedger A reference ledger for determining error
+ messages (typically new last closed ledger).
+ @param retriableTransactions collect failed transactions in this set
+ @param openLgr true if applyLedger is open, else false.
+*/
+void applyTransactions (SHAMap::ref set, Ledger::ref applyLedger,
+ Ledger::ref checkLedger, CanonicalTXSet& retriableTransactions,
+ bool openLgr)
+{
+ TransactionEngine engine (applyLedger);
+
+ if (set)
+ {
+ for (SHAMapItem::pointer item = set->peekFirstItem (); !!item;
+ item = set->peekNextItem (item->getTag ()))
+ {
+ // If the checkLedger doesn't have the transaction
+ if (!checkLedger->hasTransaction (item->getTag ()))
+ {
+ // Then try to apply the transaction to applyLedger
+ WriteLog (lsINFO, LedgerConsensus) <<
+ "Processing candidate transaction: " << item->getTag ();
+ try
+ {
+ SerializerIterator sit (item->peekSerializer ());
+ STTx::pointer txn
+ = std::make_shared(sit);
+ if (applyTransaction (engine, txn,
+ openLgr, true) == LedgerConsensusImp::resultRetry)
+ {
+ // On failure, stash the failed transaction for
+ // later retry.
+ retriableTransactions.push_back (txn);
+ }
+ }
+ catch (...)
+ {
+ WriteLog (lsWARNING, LedgerConsensus) << " Throws";
+ }
+ }
+ }
+ }
+
+ int changes;
+ bool certainRetry = true;
+ // Attempt to apply all of the retriable transactions
+ for (int pass = 0; pass < LEDGER_TOTAL_PASSES; ++pass)
+ {
+ WriteLog (lsDEBUG, LedgerConsensus) << "Pass: " << pass << " Txns: "
+ << retriableTransactions.size ()
+ << (certainRetry ? " retriable" : " final");
+ changes = 0;
+
+ auto it = retriableTransactions.begin ();
+
+ while (it != retriableTransactions.end ())
+ {
+ try
+ {
+ switch (applyTransaction (engine, it->second,
+ openLgr, certainRetry))
+ {
+ case LedgerConsensusImp::resultSuccess:
+ it = retriableTransactions.erase (it);
+ ++changes;
+ break;
+
+ case LedgerConsensusImp::resultFail:
+ it = retriableTransactions.erase (it);
+ break;
+
+ case LedgerConsensusImp::resultRetry:
+ ++it;
+ }
+ }
+ catch (...)
+ {
+ WriteLog (lsWARNING, LedgerConsensus)
+ << "Transaction throws";
+ it = retriableTransactions.erase (it);
+ }
+ }
+
+ WriteLog (lsDEBUG, LedgerConsensus) << "Pass: "
+ << pass << " finished " << changes << " changes";
+
+ // A non-retry pass made no changes
+ if (!changes && !certainRetry)
+ return;
+
+ // Stop retriable passes
+ if ((!changes) || (pass >= LEDGER_RETRY_PASSES))
+ certainRetry = false;
+ }
+
+ // If there are any transactions left, we must have
+ // tried them in at least one final pass
+ assert (retriableTransactions.empty() || !certainRetry);
+}
+
} // ripple
diff --git a/src/ripple/app/consensus/LedgerConsensus.h b/src/ripple/app/consensus/LedgerConsensus.h
index 100e72e3e..b009bac7b 100644
--- a/src/ripple/app/consensus/LedgerConsensus.h
+++ b/src/ripple/app/consensus/LedgerConsensus.h
@@ -22,6 +22,7 @@
#include
#include
+#include
#include
#include
#include
@@ -95,6 +96,11 @@ make_LedgerConsensus (LedgerConsensus::clock_type& clock, LocalTxs& localtx,
LedgerHash const & prevLCLHash, Ledger::ref previousLedger,
std::uint32_t closeTime, FeeVote& feeVote);
+void
+applyTransactions(SHAMap::ref set, Ledger::ref applyLedger,
+ Ledger::ref checkLedger,
+ CanonicalTXSet& retriableTransactions, bool openLgr);
+
} // ripple
#endif
diff --git a/src/ripple/app/ledger/Ledger.cpp b/src/ripple/app/ledger/Ledger.cpp
index 13bb0d325..f6b91cbb2 100644
--- a/src/ripple/app/ledger/Ledger.cpp
+++ b/src/ripple/app/ledger/Ledger.cpp
@@ -1899,43 +1899,6 @@ std::vector Ledger::getNeededAccountStateHashes (
return ret;
}
-//------------------------------------------------------------------------------
-
-class Ledger_test : public beast::unit_test::suite
-{
- void test_genesis_ledger ()
- {
- RippleAddress rootSeedMaster
- = RippleAddress::createSeedGeneric ("masterpassphrase");
- RippleAddress rootGeneratorMaster
- = RippleAddress::createGeneratorPublic (rootSeedMaster);
- RippleAddress rootAddress
- = RippleAddress::createAccountPublic (rootGeneratorMaster, 0);
- std::uint64_t startAmount (100000);
- Ledger::pointer ledger (std::make_shared (
- rootAddress, startAmount));
- ledger->updateHash();
- expect(ledger->assertSane());
- }
-
- void test_getQuality ()
- {
- uint256 uBig (
- "D2DC44E5DC189318DB36EF87D2104CDF0A0FE3A4B698BEEE55038D7EA4C68000");
-
- // VFALCO NOTE This fails in the original version as well.
- expect (6125895493223874560 == getQuality (uBig));
- }
-public:
- void run ()
- {
- test_genesis_ledger ();
- test_getQuality ();
- }
-};
-
-BEAST_DEFINE_TESTSUITE(Ledger,ripple_app,ripple);
-
Ledger::StaticLockType Ledger::sPendingSaveLock;
std::set Ledger::sPendingSaves;
diff --git a/src/ripple/app/ledger/Ledger.test.cpp b/src/ripple/app/ledger/Ledger.test.cpp
new file mode 100644
index 000000000..06a76b1e3
--- /dev/null
+++ b/src/ripple/app/ledger/Ledger.test.cpp
@@ -0,0 +1,318 @@
+//------------------------------------------------------------------------------
+/*
+ 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 {
+
+class Ledger_test : public beast::unit_test::suite
+{
+ using TestAccount = std::pair;
+
+ struct Amount
+ {
+ double value;
+ std::string currency;
+ TestAccount issuer;
+
+ Json::Value
+ getJson() const
+ {
+ Json::Value tx_json;
+ tx_json["currency"] = currency;
+ tx_json["issuer"] = issuer.first.humanAccountID();
+ tx_json["value"] = std::to_string(value);
+ return tx_json;
+ }
+ };
+
+ // Helper function to parse a transaction in Json, sign it with account,
+ // and return it as a STTx
+ STTx
+ parseTransaction(TestAccount& account, Json::Value const& tx_json)
+ {
+ STParsedJSONObject parsed("tx_json", tx_json);
+ std::unique_ptr sopTrans = std::move(parsed.object);
+ expect(sopTrans != nullptr);
+ sopTrans->setFieldVL(sfSigningPubKey, account.first.getAccountPublic());
+ return STTx{*sopTrans};
+ }
+
+ // Helper function to apply a transaction to a ledger
+ void
+ applyTransaction(Ledger::pointer const& ledger, STTx const& tx)
+ {
+ TransactionEngine engine(ledger);
+ bool didApply = false;
+ auto r = engine.applyTransaction(tx, tapOPEN_LEDGER | tapNO_CHECK_SIGN,
+ didApply);
+ expect(r == tesSUCCESS);
+ expect(didApply);
+ }
+
+ // Create genesis ledger from a start amount in drops, and the public
+ // master RippleAddress
+ Ledger::pointer
+ createGenesisLedger(std::uint64_t start_amount_drops, TestAccount const& master)
+ {
+ Ledger::pointer ledger = std::make_shared(master.first,
+ start_amount_drops);
+ ledger->updateHash();
+ ledger->setClosed();
+ expect(ledger->assertSane());
+ return ledger;
+ }
+
+ // Create an account represented by public RippleAddress and private
+ // RippleAddress
+ TestAccount
+ createAccount()
+ {
+ static RippleAddress const seed
+ = RippleAddress::createSeedGeneric ("masterpassphrase");
+ static RippleAddress const generator
+ = RippleAddress::createGeneratorPublic (seed);
+ static int iSeq = -1;
+ ++iSeq;
+ return std::make_pair(RippleAddress::createAccountPublic(generator, iSeq),
+ std::uint64_t(0));
+ }
+
+ void
+ freezeAccount(TestAccount& account, Ledger::pointer const& ledger)
+ {
+ Json::Value tx_json;
+ tx_json["TransactionType"] = "AccountSet";
+ tx_json["Fee"] = std::to_string(10);
+ tx_json["Account"] = account.first.humanAccountID();
+ tx_json["SetFlag"] = asfGlobalFreeze;
+ tx_json["Sequence"] = ++account.second;
+ STTx tx = parseTransaction(account, tx_json);
+ applyTransaction(ledger, tx);
+ }
+
+ void
+ unfreezeAccount(TestAccount& account, Ledger::pointer const& ledger)
+ {
+ Json::Value tx_json;
+ tx_json["TransactionType"] = "AccountSet";
+ tx_json["Fee"] = std::to_string(10);
+ tx_json["Account"] = account.first.humanAccountID();
+ tx_json["ClearFlag"] = asfGlobalFreeze;
+ tx_json["Sequence"] = ++account.second;
+ STTx tx = parseTransaction(account, tx_json);
+ applyTransaction(ledger, tx);
+ }
+
+ void
+ makePayment(TestAccount& from, TestAccount const& to,
+ std::uint64_t amountDrops,
+ Ledger::pointer const& ledger)
+ {
+ Json::Value tx_json;
+ tx_json["Account"] = from.first.humanAccountID();
+ tx_json["Amount"] = std::to_string(amountDrops);
+ tx_json["Destination"] = to.first.humanAccountID();
+ tx_json["TransactionType"] = "Payment";
+ tx_json["Fee"] = std::to_string(10);
+ tx_json["Sequence"] = ++from.second;
+ tx_json["Flags"] = tfUniversal;
+ STTx tx = parseTransaction(from, tx_json);
+ applyTransaction(ledger, tx);
+ }
+
+ void
+ makePayment(TestAccount& from, TestAccount const& to,
+ std::string const& currency, std::string const& amount,
+ Ledger::pointer const& ledger)
+ {
+ Json::Value tx_json;
+ tx_json["Account"] = from.first.humanAccountID();
+ tx_json["Amount"] = Amount{std::stod(amount), currency, to}.getJson();
+ tx_json["Destination"] = to.first.humanAccountID();
+ tx_json["TransactionType"] = "Payment";
+ tx_json["Fee"] = std::to_string(10);
+ tx_json["Sequence"] = ++from.second;
+ tx_json["Flags"] = tfUniversal;
+ STTx tx = parseTransaction(from, tx_json);
+ applyTransaction(ledger, tx);
+ }
+
+ void
+ createOffer(TestAccount& from, Amount const& in, Amount const& out,
+ Ledger::pointer ledger)
+ {
+ Json::Value tx_json;
+ tx_json["TransactionType"] = "OfferCreate";
+ tx_json["Fee"] = std::to_string(10);
+ tx_json["Account"] = from.first.humanAccountID();
+ tx_json["TakerPays"] = in.getJson();
+ tx_json["TakerGets"] = out.getJson();
+ tx_json["Sequence"] = ++from.second;
+ STTx tx = parseTransaction(from, tx_json);
+ applyTransaction(ledger, tx);
+ }
+
+ // As currently implemented, this will cancel only the last offer made
+ // from this account.
+ void
+ cancelOffer(TestAccount& from, Ledger::pointer ledger)
+ {
+ Json::Value tx_json;
+ tx_json["TransactionType"] = "OfferCancel";
+ tx_json["Fee"] = std::to_string(10);
+ tx_json["Account"] = from.first.humanAccountID();
+ tx_json["OfferSequence"] = from.second;
+ tx_json["Sequence"] = ++from.second;
+ STTx tx = parseTransaction(from, tx_json);
+ applyTransaction(ledger, tx);
+ }
+
+ void
+ makeTrustSet(TestAccount& from, TestAccount const& issuer,
+ std::string const& currency, double amount,
+ Ledger::pointer const& ledger)
+ {
+ Json::Value tx_json;
+ tx_json["Account"] = from.first.humanAccountID();
+ Json::Value& limitAmount = tx_json["LimitAmount"];
+ limitAmount["currency"] = currency;
+ limitAmount["issuer"] = issuer.first.humanAccountID();
+ limitAmount["value"] = std::to_string(amount);
+ tx_json["TransactionType"] = "TrustSet";
+ tx_json["Fee"] = std::to_string(10);
+ tx_json["Sequence"] = ++from.second;
+ tx_json["Flags"] = tfClearNoRipple;
+ STTx tx = parseTransaction(from, tx_json);
+ applyTransaction(ledger, tx);
+ }
+
+ Ledger::pointer
+ close_and_advance(Ledger::pointer ledger, Ledger::pointer LCL)
+ {
+ SHAMap::pointer set = ledger->peekTransactionMap();
+ CanonicalTXSet retriableTransactions{set->getHash()};
+ Ledger::pointer newLCL = std::make_shared(false, *LCL);
+ // Set up to write SHAMap changes to our database,
+ // perform updates, extract changes
+ applyTransactions(set, newLCL, newLCL, retriableTransactions, false);
+ newLCL->updateSkipList();
+ newLCL->setClosed();
+ int asf = newLCL->peekAccountStateMap()->flushDirty(hotACCOUNT_NODE,
+ newLCL->getLedgerSeq());
+ int tmf = newLCL->peekTransactionMap()->flushDirty(hotTRANSACTION_NODE,
+ newLCL->getLedgerSeq());
+ using namespace std::chrono;
+ auto const epoch_offset = days{10957}; // 2000-01-01
+ std::uint32_t closeTime = time_point_cast // now
+ (system_clock::now()-epoch_offset).
+ time_since_epoch().count();
+ int CloseResolution = seconds{LEDGER_TIME_ACCURACY}.count();
+ bool closeTimeCorrect = true;
+ newLCL->setAccepted(closeTime, CloseResolution, closeTimeCorrect);
+ return newLCL;
+ }
+
+ void test_genesisLedger ()
+ {
+ std::uint64_t const xrp = std::mega::num;
+
+ // Create master account
+ auto master = createAccount();
+
+ // Create genesis ledger
+ Ledger::pointer LCL = createGenesisLedger(100000*xrp, master);
+
+ // Create open scratch ledger
+ Ledger::pointer ledger = std::make_shared(false, *LCL);
+
+ // Create user accounts
+ auto gw1 = createAccount();
+ auto gw2 = createAccount();
+ auto gw3 = createAccount();
+ auto alice = createAccount();
+ auto mark = createAccount();
+
+ // Fund gw1, gw2, gw3, alice, mark from master
+ makePayment(master, gw1, 5000*xrp, ledger);
+ makePayment(master, gw2, 4000*xrp, ledger);
+ makePayment(master, gw3, 3000*xrp, ledger);
+ makePayment(master, alice, 2000*xrp, ledger);
+ makePayment(master, mark, 1000*xrp, ledger);
+
+ LCL = close_and_advance(ledger, LCL);
+ ledger = std::make_shared(false, *LCL);
+
+ // alice trusts FOO/gw1
+ makeTrustSet(alice, gw1, "FOO", 1, ledger);
+
+ // mark trusts FOO/gw2
+ makeTrustSet(mark, gw2, "FOO", 1, ledger);
+
+ // mark trusts FOO/gw3
+ makeTrustSet(mark, gw3, "FOO", 1, ledger);
+
+ // gw2 pays mark with FOO
+ makePayment(gw2, mark, "FOO", ".1", ledger);
+
+ // gw3 pays mark with FOO
+ makePayment(gw3, mark, "FOO", ".2", ledger);
+
+ // gw1 pays alice with FOO
+ makePayment(gw1, alice, "FOO", ".3", ledger);
+
+ LCL = close_and_advance(ledger, LCL);
+ ledger = std::make_shared(false, *LCL);
+
+ createOffer(mark, Amount{1, "FOO", gw1}, Amount{1, "FOO", gw2}, ledger);
+ createOffer(mark, Amount{1, "FOO", gw2}, Amount{1, "FOO", gw3}, ledger);
+ cancelOffer(mark, ledger);
+ freezeAccount(alice, ledger);
+
+ LCL = close_and_advance(ledger, LCL);
+ ledger = std::make_shared(false, *LCL);
+
+ makePayment(alice, mark, 1*xrp, ledger);
+
+ LCL = close_and_advance(ledger, LCL);
+ ledger = std::make_shared(false, *LCL);
+ }
+
+ void test_getQuality ()
+ {
+ uint256 uBig (
+ "D2DC44E5DC189318DB36EF87D2104CDF0A0FE3A4B698BEEE55038D7EA4C68000");
+ expect (6125895493223874560 == getQuality (uBig));
+ }
+public:
+ void run ()
+ {
+ test_genesisLedger ();
+ test_getQuality ();
+ }
+};
+
+BEAST_DEFINE_TESTSUITE(Ledger,ripple_app,ripple);
+
+} // ripple
diff --git a/src/ripple/app/tx/TransactionEngine.cpp b/src/ripple/app/tx/TransactionEngine.cpp
index b76b91fc4..326dcba11 100644
--- a/src/ripple/app/tx/TransactionEngine.cpp
+++ b/src/ripple/app/tx/TransactionEngine.cpp
@@ -42,7 +42,7 @@ void TransactionEngine::txnWrite ()
case taaCREATE:
{
- WriteLog (lsINFO, TransactionEngine) << "applyTransaction: taaCREATE: " << sleEntry->getText ();
+ WriteLog (lsDEBUG, TransactionEngine) << "applyTransaction: taaCREATE: " << sleEntry->getText ();
if (mLedger->writeBack (lepCREATE, sleEntry) & lepERROR)
assert (false);
@@ -51,7 +51,7 @@ void TransactionEngine::txnWrite ()
case taaMODIFY:
{
- WriteLog (lsINFO, TransactionEngine) << "applyTransaction: taaMODIFY: " << sleEntry->getText ();
+ WriteLog (lsDEBUG, TransactionEngine) << "applyTransaction: taaMODIFY: " << sleEntry->getText ();
if (mLedger->writeBack (lepNONE, sleEntry) & lepERROR)
assert (false);
@@ -60,7 +60,7 @@ void TransactionEngine::txnWrite ()
case taaDELETE:
{
- WriteLog (lsINFO, TransactionEngine) << "applyTransaction: taaDELETE: " << sleEntry->getText ();
+ WriteLog (lsDEBUG, TransactionEngine) << "applyTransaction: taaDELETE: " << sleEntry->getText ();
if (!mLedger->peekAccountStateMap ()->delItem (it.first))
assert (false);
@@ -117,14 +117,14 @@ TER TransactionEngine::applyTransaction (
return temUNKNOWN;
}
- if (ShouldLog (lsINFO, TransactionEngine))
+ if (ShouldLog (lsDEBUG, TransactionEngine))
{
std::string strToken;
std::string strHuman;
transResultInfo (terResult, strToken, strHuman);
- WriteLog (lsINFO, TransactionEngine) <<
+ WriteLog (lsDEBUG, TransactionEngine) <<
"applyTransaction: terResult=" << strToken <<
" : " << terResult <<
" : " << strHuman;
diff --git a/src/ripple/unity/app3.cpp b/src/ripple/unity/app3.cpp
index aa5a3b5f8..ffe265f14 100644
--- a/src/ripple/unity/app3.cpp
+++ b/src/ripple/unity/app3.cpp
@@ -22,6 +22,7 @@
#include
#include
+#include
#include
#include
#include