diff --git a/Builds/VisualStudio2013/RippleD.vcxproj b/Builds/VisualStudio2013/RippleD.vcxproj index deec70bf1..5785290a2 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj +++ b/Builds/VisualStudio2013/RippleD.vcxproj @@ -1440,9 +1440,6 @@ - - True - True @@ -1487,6 +1484,9 @@ + + True + True @@ -1681,6 +1681,11 @@ + + True + + + True diff --git a/Builds/VisualStudio2013/RippleD.vcxproj.filters b/Builds/VisualStudio2013/RippleD.vcxproj.filters index 9f89b82bd..2117a5a2a 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2013/RippleD.vcxproj.filters @@ -286,6 +286,9 @@ {CE126498-A44D-30A2-345B-0F672BCDF947} + + {55A76B5B-A18E-E655-1A07-9492C6F8F356} + {91D5931B-D981-52BC-BC12-08DA9F7BF606} @@ -307,6 +310,9 @@ {07831F2A-6752-E81C-87AF-4D47D425BE8E} + + {2E791662-6ED0-D1E1-03A4-0CB35473EC56} + {418BEF0D-AAAB-C368-7D9E-0A97636DE5A6} @@ -2259,9 +2265,6 @@ ripple\app\ledger - - ripple\app\ledger - ripple\app\ledger @@ -2316,6 +2319,9 @@ ripple\app\ledger + + ripple\app\ledger\tests + ripple\app\ledger @@ -2547,6 +2553,12 @@ ripple\app\peers + + ripple\app\tests + + + ripple\app\tests + ripple\app\transactors diff --git a/src/ripple/app/ledger/Ledger.test.cpp b/src/ripple/app/ledger/Ledger.test.cpp deleted file mode 100644 index 4a3e4c098..000000000 --- a/src/ripple/app/ledger/Ledger.test.cpp +++ /dev/null @@ -1,330 +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 -#include -#include - -namespace ripple { - -class Ledger_test : public beast::unit_test::suite -{ - using TestAccount = std::pair; - - struct Amount - { - Amount (double value_, std::string currency_, TestAccount issuer_) - : value(value_) - , currency(currency_) - , issuer(issuer_) - { - } - - 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(); - newLCL->peekAccountStateMap()->flushDirty( - hotACCOUNT_NODE, newLCL->getLedgerSeq()); - 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/ledger/tests/Ledger_test.cpp b/src/ripple/app/ledger/tests/Ledger_test.cpp new file mode 100644 index 000000000..70597aa52 --- /dev/null +++ b/src/ripple/app/ledger/tests/Ledger_test.cpp @@ -0,0 +1,149 @@ +//------------------------------------------------------------------------------ +/* + 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 + +namespace ripple { +namespace test { + +class Ledger_test : public beast::unit_test::suite +{ + void test_genesisLedger (bool sign) + { + std::uint64_t const xrp = std::mega::num; + + auto master = createAccount ("masterpassphrase"); + + Ledger::pointer LCL = createGenesisLedger(100000*xrp, master); + + Ledger::pointer ledger = std::make_shared(false, *LCL); + + // User accounts + auto gw1 = createAccount ("gw1"); + expect (gw1.pk != master.pk, "gw1.pk != master.pk"); + expect (gw1.sk != master.sk, "gw1.sk != master.sk"); + auto gw2 = createAccount ("gw2"); + auto gw3 = createAccount ("gw3"); + auto alice = createAccount ("alice"); + auto mark = createAccount ("mark"); + + // Fund gw1, gw2, gw3, alice, mark from master + makeAndApplyPayment(master, gw1, 5000 * xrp, ledger, sign); + makeAndApplyPayment(master, gw2, 4000 * xrp, ledger, sign); + makeAndApplyPayment(master, gw3, 3000 * xrp, ledger, sign); + makeAndApplyPayment(master, alice, 2000 * xrp, ledger, sign); + makeAndApplyPayment(master, mark, 1000 * xrp, ledger, sign); + + LCL = close_and_advance(ledger, LCL); + ledger = std::make_shared(false, *LCL); + + // alice trusts FOO/gw1 + makeTrustSet (alice, gw1, "FOO", 1, ledger, sign); + + // mark trusts FOO/gw2 + makeTrustSet (mark, gw2, "FOO", 1, ledger, sign); + + // mark trusts FOO/gw3 + makeTrustSet (mark, gw3, "FOO", 1, ledger, sign); + + // gw2 pays mark with FOO + makeAndApplyPayment(gw2, mark, "FOO", ".1", ledger, sign); + + // gw3 pays mark with FOO + makeAndApplyPayment(gw3, mark, "FOO", ".2", ledger, sign); + + // gw1 pays alice with FOO + makeAndApplyPayment(gw1, alice, "FOO", ".3", ledger, sign); + + LCL = close_and_advance(ledger, LCL); + ledger = std::make_shared(false, *LCL); + + createOffer (mark, Amount (1, "FOO", gw1), Amount (1, "FOO", gw2), ledger, sign); + createOffer (mark, Amount (1, "FOO", gw2), Amount (1, "FOO", gw3), ledger, sign); + cancelOffer (mark, ledger, sign); + freezeAccount (alice, ledger, sign); + + LCL = close_and_advance(ledger, LCL); + ledger = std::make_shared(false, *LCL); + + makeAndApplyPayment(alice, mark, 1 * xrp, ledger, sign); + + LCL = close_and_advance(ledger, LCL); + ledger = std::make_shared(false, *LCL); + + pass (); + } + + void test_unsigned_fails () + { + std::uint64_t const xrp = std::mega::num; + + auto master = createAccount ("masterpassphrase"); + + Ledger::pointer LCL = createGenesisLedger (100000 * xrp, master); + + Ledger::pointer ledger = std::make_shared (false, *LCL); + + auto gw1 = createAccount ("gw1"); + + auto tx = getPaymentTx(master, gw1, 5000 * xrp, false); + + try + { + applyTransaction (ledger, tx, true); + fail ("apply unsigned transaction should fail"); + } + catch (std::runtime_error const& e) + { + if (std::string (e.what()) != "r != tesSUCCESS") + throw std::runtime_error(e.what()); + } + + pass (); + } + + void test_getQuality () + { + uint256 uBig ( + "D2DC44E5DC189318DB36EF87D2104CDF0A0FE3A4B698BEEE55038D7EA4C68000"); + expect (6125895493223874560 == getQuality (uBig)); + + pass (); + } +public: + void run () + { + testcase ("genesisLedger signed transactions"); + test_genesisLedger (true); + + testcase ("genesisLedger unsigned transactions"); + test_genesisLedger (false); + + testcase ("unsigned invalid"); + test_unsigned_fails (); + + testcase ("getQuality"); + test_getQuality (); + } +}; + +BEAST_DEFINE_TESTSUITE(Ledger,ripple_app,ripple); + +} // test +} // ripple diff --git a/src/ripple/app/tests/common_ledger.cpp b/src/ripple/app/tests/common_ledger.cpp new file mode 100644 index 000000000..46f2d5fb8 --- /dev/null +++ b/src/ripple/app/tests/common_ledger.cpp @@ -0,0 +1,262 @@ +//------------------------------------------------------------------------------ +/* +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 + +namespace ripple { +namespace test { + +Amount::Amount(double value_, std::string currency_, TestAccount issuer_) + : value(value_) + , currency(currency_) + , issuer(issuer_) +{ +} + +Json::Value +Amount::getJson() const +{ + Json::Value tx_json; + tx_json["currency"] = currency; + tx_json["issuer"] = issuer.pk.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, bool sign) +{ + STParsedJSONObject parsed("tx_json", tx_json); + std::unique_ptr sopTrans = std::move(parsed.object); + if (sopTrans == nullptr) + throw std::runtime_error( + "sopTrans == nullptr"); + sopTrans->setFieldVL(sfSigningPubKey, account.pk.getAccountPublic()); + auto tx = STTx(*sopTrans); + if (sign) + tx.sign(account.sk); + return tx; +} + +// Helper function to apply a transaction to a ledger +void +applyTransaction(Ledger::pointer const& ledger, STTx const& tx, bool check) +{ + TransactionEngine engine(ledger); + bool didApply = false; + auto r = engine.applyTransaction(tx, tapOPEN_LEDGER | (check ? tapNONE : tapNO_CHECK_SIGN), + didApply); + if (r != tesSUCCESS) + throw std::runtime_error( + "r != tesSUCCESS"); + if (!didApply) + throw std::runtime_error( + "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.pk, + start_amount_drops); + ledger->updateHash(); + ledger->setClosed(); + if (!ledger->assertSane()) + throw std::runtime_error( + "! ledger->assertSane()"); + return ledger; +} + +// Create an account represented by public RippleAddress and private +// RippleAddress +TestAccount +createAccount(std::string const& passphrase) +{ + RippleAddress const seed + = RippleAddress::createSeedGeneric(passphrase); + RippleAddress const generator + = RippleAddress::createGeneratorPublic(seed); + + return { + std::move(RippleAddress::createAccountPublic(generator, 0)), + std::move(RippleAddress::createAccountPrivate(generator, seed, 0)), + std::uint64_t(0) + }; +} + +void +freezeAccount(TestAccount& account, Ledger::pointer const& ledger, bool sign) +{ + Json::Value tx_json; + tx_json["TransactionType"] = "AccountSet"; + tx_json["Fee"] = std::to_string(10); + tx_json["Account"] = account.pk.humanAccountID(); + tx_json["SetFlag"] = asfGlobalFreeze; + tx_json["Sequence"] = ++account.sequence; + STTx tx = parseTransaction(account, tx_json, sign); + applyTransaction(ledger, tx, sign); +} + +void +unfreezeAccount(TestAccount& account, Ledger::pointer const& ledger, bool sign) +{ + Json::Value tx_json; + tx_json["TransactionType"] = "AccountSet"; + tx_json["Fee"] = std::to_string(10); + tx_json["Account"] = account.pk.humanAccountID(); + tx_json["ClearFlag"] = asfGlobalFreeze; + tx_json["Sequence"] = ++account.sequence; + STTx tx = parseTransaction(account, tx_json, sign); + applyTransaction(ledger, tx, sign); +} + +STTx +getPaymentTx(TestAccount& from, TestAccount const& to, + std::uint64_t amountDrops, + bool sign) +{ + Json::Value tx_json; + tx_json["Account"] = from.pk.humanAccountID(); + tx_json["Amount"] = std::to_string(amountDrops); + tx_json["Destination"] = to.pk.humanAccountID(); + tx_json["TransactionType"] = "Payment"; + tx_json["Fee"] = std::to_string(10); + tx_json["Sequence"] = ++from.sequence; + tx_json["Flags"] = tfUniversal; + return parseTransaction(from, tx_json, sign); +} + +STTx +makeAndApplyPayment(TestAccount& from, TestAccount const& to, + std::uint64_t amountDrops, + Ledger::pointer const& ledger, bool sign) +{ + auto tx = getPaymentTx(from, to, amountDrops, sign); + applyTransaction(ledger, tx, sign); + return tx; +} + +STTx +getPaymentTx(TestAccount& from, TestAccount const& to, + std::string const& currency, std::string const& amount, + bool sign) +{ + Json::Value tx_json; + tx_json["Account"] = from.pk.humanAccountID(); + tx_json["Amount"] = Amount(std::stod(amount), currency, to).getJson(); + tx_json["Destination"] = to.pk.humanAccountID(); + tx_json["TransactionType"] = "Payment"; + tx_json["Fee"] = std::to_string(10); + tx_json["Sequence"] = ++from.sequence; + tx_json["Flags"] = tfUniversal; + return parseTransaction(from, tx_json, sign); +} + +STTx +makeAndApplyPayment(TestAccount& from, TestAccount const& to, + std::string const& currency, std::string const& amount, + Ledger::pointer const& ledger, bool sign) +{ + auto tx = getPaymentTx(from, to, currency, amount, sign); + applyTransaction(ledger, tx, sign); + return tx; +} + +void +createOffer(TestAccount& from, Amount const& in, Amount const& out, + Ledger::pointer ledger, bool sign) +{ + Json::Value tx_json; + tx_json["TransactionType"] = "OfferCreate"; + tx_json["Fee"] = std::to_string(10); + tx_json["Account"] = from.pk.humanAccountID(); + tx_json["TakerPays"] = in.getJson(); + tx_json["TakerGets"] = out.getJson(); + tx_json["Sequence"] = ++from.sequence; + STTx tx = parseTransaction(from, tx_json, sign); + applyTransaction(ledger, tx, sign); +} + +// As currently implemented, this will cancel only the last offer made +// from this account. +void +cancelOffer(TestAccount& from, Ledger::pointer ledger, bool sign) +{ + Json::Value tx_json; + tx_json["TransactionType"] = "OfferCancel"; + tx_json["Fee"] = std::to_string(10); + tx_json["Account"] = from.pk.humanAccountID(); + tx_json["OfferSequence"] = from.sequence; + tx_json["Sequence"] = ++from.sequence; + STTx tx = parseTransaction(from, tx_json, sign); + applyTransaction(ledger, tx, sign); +} + +void +makeTrustSet(TestAccount& from, TestAccount const& issuer, + std::string const& currency, double amount, + Ledger::pointer const& ledger, bool sign) +{ + Json::Value tx_json; + tx_json["Account"] = from.pk.humanAccountID(); + Json::Value& limitAmount = tx_json["LimitAmount"]; + limitAmount["currency"] = currency; + limitAmount["issuer"] = issuer.pk.humanAccountID(); + limitAmount["value"] = std::to_string(amount); + tx_json["TransactionType"] = "TrustSet"; + tx_json["Fee"] = std::to_string(10); + tx_json["Sequence"] = ++from.sequence; + tx_json["Flags"] = tfClearNoRipple; + STTx tx = parseTransaction(from, tx_json, sign); + applyTransaction(ledger, tx, sign); +} + +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(); + newLCL->peekAccountStateMap()->flushDirty( + hotACCOUNT_NODE, newLCL->getLedgerSeq()); + 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; +} + + +} +} \ No newline at end of file diff --git a/src/ripple/app/tests/common_ledger.h b/src/ripple/app/tests/common_ledger.h new file mode 100644 index 000000000..403113069 --- /dev/null +++ b/src/ripple/app/tests/common_ledger.h @@ -0,0 +1,126 @@ +//------------------------------------------------------------------------------ +/* + 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_APP_TESTS_COMMON_LEDGER_H_INCLUDED +#define RIPPLE_APP_TESTS_COMMON_LEDGER_H_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ripple { +namespace test { + +struct TestAccount +{ + RippleAddress pk; + RippleAddress sk; + unsigned sequence; +}; + +struct Amount +{ + Amount(double value_, std::string currency_, TestAccount issuer_); + + Json::Value + getJson() const; + +private: + double value; + std::string currency; + TestAccount issuer; +}; + +// 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, bool sign = true); + +// Helper function to apply a transaction to a ledger +void +applyTransaction(Ledger::pointer const& ledger, STTx const& tx, bool check = true); + +// 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); + +// Create an account represented by public RippleAddress and private +// RippleAddress +TestAccount +createAccount(std::string const& passphrase); + +void +freezeAccount(TestAccount& account, Ledger::pointer const& ledger, bool sign = true); + +void +unfreezeAccount(TestAccount& account, Ledger::pointer const& ledger, bool sign = true); + +STTx +getPaymentTx(TestAccount& from, TestAccount const& to, + std::uint64_t amountDrops, + bool sign = true); + +STTx +makeAndApplyPayment(TestAccount& from, TestAccount const& to, + std::uint64_t amountDrops, + Ledger::pointer const& ledger, bool sign = true); + +STTx +getPaymentTx(TestAccount& from, TestAccount const& to, + std::string const& currency, std::string const& amount, + bool sign = true); + +STTx +makeAndApplyPayment(TestAccount& from, TestAccount const& to, + std::string const& currency, std::string const& amount, + Ledger::pointer const& ledger, bool sign = true); + +void +createOffer(TestAccount& from, Amount const& in, Amount const& out, + Ledger::pointer ledger, bool sign = true); + +// As currently implemented, this will cancel only the last offer made +// from this account. +void +cancelOffer(TestAccount& from, Ledger::pointer ledger, bool sign = true); + +void +makeTrustSet(TestAccount& from, TestAccount const& issuer, + std::string const& currency, double amount, + Ledger::pointer const& ledger, bool sign = true); + +Ledger::pointer +close_and_advance(Ledger::pointer ledger, Ledger::pointer LCL); + +} // test +} // ripple + +#endif diff --git a/src/ripple/unity/app3.cpp b/src/ripple/unity/app3.cpp index dc7973d6e..ba6b58c25 100644 --- a/src/ripple/unity/app3.cpp +++ b/src/ripple/unity/app3.cpp @@ -20,5 +20,7 @@ #include #include -#include #include + +#include +#include