20 #include <ripple/app/tx/apply.h>
21 #include <ripple/app/tx/impl/ApplyContext.h>
22 #include <ripple/app/tx/impl/Transactor.h>
23 #include <ripple/beast/utility/Journal.h>
24 #include <ripple/protocol/STLedgerEntry.h>
25 #include <boost/algorithm/string/predicate.hpp>
27 #include <test/jtx/Env.h>
51 using namespace test::jtx;
56 env.fund(
XRP(1000), A1, A2);
59 OpenView ov{*env.current()};
67 env.current()->fees().base,
71 BEAST_EXPECT(precheck(A1, A2, ac));
74 if (!BEAST_EXPECT(ters.
size() == 2))
78 for (
TER const& terExpect : ters)
80 terActual = ac.checkInvariants(terActual, fee);
81 BEAST_EXPECT(terExpect == terActual);
84 sink.messages().str(),
"Invariant failed:") ||
86 sink.messages().str(),
"Transaction caused an exception"));
89 for (
auto const& m : expect_logs)
92 sink.messages().str().find(m) != std::string::npos);
100 using namespace test::jtx;
101 testcase <<
"XRP created";
103 {{
"XRP net change was positive: 500"}},
104 [](Account
const& A1, Account
const&,
ApplyContext& ac) {
109 auto amt = sle->getFieldAmount(
sfBalance);
111 ac.view().update(sle);
119 using namespace test::jtx;
120 testcase <<
"account root removed";
124 {{
"an account root was deleted"}},
125 [](Account
const& A1, Account
const&,
ApplyContext& ac) {
130 ac.view().erase(sle);
140 {{
"account deletion succeeded without deleting an account"}},
150 {{
"account deletion succeeded but deleted multiple accounts"}},
151 [](Account
const& A1, Account
const& A2,
ApplyContext& ac) {
155 if (!sleA1 || !sleA2)
157 ac.view().erase(sleA1);
158 ac.view().erase(sleA2);
168 using namespace test::jtx;
169 testcase <<
"ledger entry types don't match";
171 {{
"ledger entry type mismatch"},
172 {
"XRP net change of -1000000000 doesn't match fee 0"}},
173 [](Account
const& A1, Account
const&,
ApplyContext& ac) {
178 auto sleNew = std::make_shared<SLE>(
ltTICKET, sle->key());
179 ac.rawView().rawReplace(sleNew);
184 {{
"invalid ledger entry type added"}},
185 [](Account
const& A1, Account
const&,
ApplyContext& ac) {
194 auto sleNew = std::make_shared<SLE>(
200 ac.view().insert(sleNew);
208 using namespace test::jtx;
209 testcase <<
"trust lines with XRP not allowed";
211 {{
"an XRP trust line was created"}},
212 [](Account
const& A1, Account
const& A2,
ApplyContext& ac) {
214 auto const sleNew = std::make_shared<SLE>(
216 ac.view().insert(sleNew);
224 using namespace test::jtx;
225 testcase <<
"XRP balance checks";
228 {{
"Cannot return non-native STAmount as XRPAmount"}},
229 [](Account
const& A1, Account
const& A2,
ApplyContext& ac) {
235 sle->setFieldAmount(
sfBalance, nonNative);
236 ac.view().update(sle);
241 {{
"incorrect account XRP balance"},
242 {
"XRP net change was positive: 99999999000000001"}},
243 [
this](Account
const& A1, Account
const&,
ApplyContext& ac) {
251 BEAST_EXPECT(!sle->getFieldAmount(
sfBalance).negative());
252 ac.view().update(sle);
257 {{
"incorrect account XRP balance"},
258 {
"XRP net change of -1000000001 doesn't match fee 0"}},
259 [
this](Account
const& A1, Account
const&,
ApplyContext& ac) {
265 BEAST_EXPECT(sle->getFieldAmount(
sfBalance).negative());
266 ac.view().update(sle);
274 using namespace test::jtx;
275 using namespace std::string_literals;
276 testcase <<
"Transaction fee checks";
279 {{
"fee paid was negative: -1"},
280 {
"XRP net change of 0 doesn't match fee -1"}},
281 [](Account
const&, Account
const&,
ApplyContext&) {
return true; },
286 {
"XRP net change of 0 doesn't match fee "s +
288 [](Account
const&, Account
const&,
ApplyContext&) {
return true; },
292 {{
"fee paid is 20 exceeds fee specified in transaction."},
293 {
"XRP net change of 0 doesn't match fee 20"}},
294 [](Account
const&, Account
const&,
ApplyContext&) {
return true; },
304 using namespace test::jtx;
305 testcase <<
"no bad offers";
308 {{
"offer with a bad amount"}},
309 [](Account
const& A1, Account
const&,
ApplyContext& ac) {
314 auto sleNew = std::make_shared<SLE>(
316 sleNew->setAccountID(
sfAccount, A1.id());
319 ac.view().insert(sleNew);
324 {{
"offer with a bad amount"}},
325 [](Account
const& A1, Account
const&,
ApplyContext& ac) {
330 auto sleNew = std::make_shared<SLE>(
332 sleNew->setAccountID(
sfAccount, A1.id());
334 sleNew->setFieldAmount(
sfTakerPays, A1[
"USD"](10));
336 ac.view().insert(sleNew);
341 {{
"offer with a bad amount"}},
342 [](Account
const& A1, Account
const&,
ApplyContext& ac) {
347 auto sleNew = std::make_shared<SLE>(
349 sleNew->setAccountID(
sfAccount, A1.id());
353 ac.view().insert(sleNew);
361 using namespace test::jtx;
362 testcase <<
"no zero escrow";
365 {{
"Cannot return non-native STAmount as XRPAmount"}},
366 [](Account
const& A1, Account
const& A2,
ApplyContext& ac) {
371 auto sleNew = std::make_shared<SLE>(
374 sleNew->setFieldAmount(
sfAmount, nonNative);
375 ac.view().insert(sleNew);
380 {{
"XRP net change of -1000000 doesn't match fee 0"},
381 {
"escrow specifies invalid amount"}},
382 [](Account
const& A1, Account
const&,
ApplyContext& ac) {
387 auto sleNew = std::make_shared<SLE>(
389 sleNew->setFieldAmount(
sfAmount, XRP(-1));
390 ac.view().insert(sleNew);
395 {{
"XRP net change was positive: 100000000000000001"},
396 {
"escrow specifies invalid amount"}},
397 [](Account
const& A1, Account
const&,
ApplyContext& ac) {
402 auto sleNew = std::make_shared<SLE>(
407 ac.view().insert(sleNew);
415 using namespace test::jtx;
416 testcase <<
"valid new account root";
419 {{
"account root created by a non-Payment"}},
423 const Account A3{
"A3"};
425 auto const sleNew = std::make_shared<SLE>(acctKeylet);
426 ac.view().insert(sleNew);
431 {{
"multiple accounts created in a single transaction"}},
435 const Account A3{
"A3"};
437 auto const sleA3 = std::make_shared<SLE>(acctKeylet);
438 ac.view().insert(sleA3);
441 const Account A4{
"A4"};
443 auto const sleA4 = std::make_shared<SLE>(acctKeylet);
444 ac.view().insert(sleA4);
450 {{
"account created with wrong starting sequence number"}},
453 const Account A3{
"A3"};
455 auto const sleNew = std::make_shared<SLE>(acctKeylet);
456 sleNew->setFieldU32(
sfSequence, ac.view().seq() + 1);
457 ac.view().insert(sleNew);
@ ttACCOUNT_DELETE
This transaction type deletes an existing account.
const XRP_t XRP
Converts to XRP Issue or STAmount.
@ ltTICKET
A ledger object which describes a ticket.
A pair of SHAMap key and LedgerEntryType.
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, ripple)
void testValidNewAccountRoot()
const SF_UINT32 sfSequence
void testXRPBalanceCheck()
Keylet offer(AccountID const &id, std::uint32_t seq) noexcept
An offer from an account.
constexpr XRPAmount INITIAL_XRP
Configure the native currency.
void testAccountRootsNotRemoved()
@ ttPAYMENT
This transaction type executes a payment.
const SF_AMOUNT sfTakerPays
Keylet escrow(AccountID const &src, std::uint32_t seq) noexcept
An escrow entry.
Keylet account(AccountID const &id) noexcept
AccountID root.
void testNoXRPTrustLine()
TERSubset< CanCvtToTER > TER
const SF_AMOUNT sfTakerGets
State information when applying a tx.
A generic endpoint for log messages.
Keylet line(AccountID const &id0, AccountID const &id1, Currency const ¤cy) noexcept
The index of a trust line for a given currency.
@ ttACCOUNT_SET
This transaction type adjusts various account settings.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
LedgerEntryType
Identifiers for on-ledger objects.
void doInvariantCheck(std::vector< std::string > const &expect_logs, Precheck const &precheck, XRPAmount fee=XRPAmount{}, STTx tx=STTx{ttACCOUNT_SET, [](STObject &) {}}, std::initializer_list< TER > ters={ tecINVARIANT_FAILED, tefINVARIANT_FAILED})
const SF_AMOUNT sfBalance
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Immutable cryptographic account descriptor.
const SF_ACCOUNT sfAccount
void testTransactionFeeCheck()