Format first-party source according to .clang-format

This commit is contained in:
Pretty Printer
2020-04-17 09:56:34 -05:00
committed by manojsdoshi
parent 65dfc5d19e
commit 50760c6935
1076 changed files with 86161 additions and 77449 deletions

View File

@@ -27,7 +27,8 @@ namespace test {
class AccountDelete_test : public beast::unit_test::suite
{
private:
std::uint32_t openLedgerSeq (jtx::Env& env)
std::uint32_t
openLedgerSeq(jtx::Env& env)
{
return env.current()->seq();
}
@@ -36,31 +37,33 @@ private:
//
// NOTE: the function _infers_ the transaction to operate on by calling
// env.tx(), which returns the result from the most recent transaction.
void verifyDeliveredAmount (jtx::Env& env, STAmount const& amount)
void
verifyDeliveredAmount(jtx::Env& env, STAmount const& amount)
{
// Get the hash for the most recent transaction.
std::string const txHash {
env.tx()->getJson (JsonOptions::none)[jss::hash].asString()};
std::string const txHash{
env.tx()->getJson(JsonOptions::none)[jss::hash].asString()};
// Verify DeliveredAmount and delivered_amount metadata are correct.
// We can't use env.meta() here, because meta() doesn't include
// delivered_amount.
env.close();
Json::Value const meta = env.rpc ("tx", txHash)[jss::result][jss::meta];
Json::Value const meta = env.rpc("tx", txHash)[jss::result][jss::meta];
// Expect there to be a DeliveredAmount field.
if (! BEAST_EXPECT(meta.isMember (sfDeliveredAmount.jsonName)))
if (!BEAST_EXPECT(meta.isMember(sfDeliveredAmount.jsonName)))
return;
// DeliveredAmount and delivered_amount should both be present and
// equal amount.
Json::Value const jsonExpect {amount.getJson (JsonOptions::none)};
BEAST_EXPECT (meta[sfDeliveredAmount.jsonName] == jsonExpect);
BEAST_EXPECT (meta[jss::delivered_amount] == jsonExpect);
Json::Value const jsonExpect{amount.getJson(JsonOptions::none)};
BEAST_EXPECT(meta[sfDeliveredAmount.jsonName] == jsonExpect);
BEAST_EXPECT(meta[jss::delivered_amount] == jsonExpect);
}
// Helper function to create a payment channel.
static Json::Value payChanCreate (
static Json::Value
payChanCreate(
jtx::Account const& account,
jtx::Account const& to,
STAmount const& amount,
@@ -72,11 +75,10 @@ private:
jv[jss::TransactionType] = jss::PaymentChannelCreate;
jv[jss::Account] = account.human();
jv[jss::Destination] = to.human();
jv[jss::Amount] = amount.getJson (JsonOptions::none);
jv[jss::Amount] = amount.getJson(JsonOptions::none);
jv[sfSettleDelay.jsonName] = settleDelay.count();
jv[sfCancelAfter.jsonName] =
cancelAfter.time_since_epoch().count() + 2;
jv[sfPublicKey.jsonName] = strHex (pk.slice());
jv[sfCancelAfter.jsonName] = cancelAfter.time_since_epoch().count() + 2;
jv[sfPublicKey.jsonName] = strHex(pk.slice());
return jv;
};
@@ -89,25 +91,26 @@ private:
jtx::Account const& acc,
std::uint32_t margin = 0)
{
int const delta = [&]()->int{
int const delta = [&]() -> int {
if (env.seq(acc) + 255 > openLedgerSeq(env))
return env.seq(acc) - openLedgerSeq(env) + 255 - margin;
return 0;
}();
BEAST_EXPECT(margin==0 || delta >= 0);
BEAST_EXPECT(margin == 0 || delta >= 0);
for (int i = 0; i < delta; ++i)
env.close();
BEAST_EXPECT(openLedgerSeq(env) == env.seq(acc) + 255 - margin);
}
public:
void testBasics()
void
testBasics()
{
using namespace jtx;
testcase("Basics");
Env env {*this};
Env env{*this};
Account const alice("alice");
Account const becky("becky");
Account const carol("carol");
@@ -117,44 +120,46 @@ public:
env.close();
// Alice can't delete her account and then give herself the XRP.
env (acctdelete (alice, alice), ter (temDST_IS_SRC));
env(acctdelete(alice, alice), ter(temDST_IS_SRC));
// Invalid flags.
env (acctdelete (alice, becky),
txflags (tfImmediateOrCancel), ter (temINVALID_FLAG));
env(acctdelete(alice, becky),
txflags(tfImmediateOrCancel),
ter(temINVALID_FLAG));
// Account deletion has a high fee. Make sure the fee requirement
// behaves as we expect.
auto const acctDelFee {drops (env.current()->fees().increment)};
env (acctdelete (alice, becky), ter (telINSUF_FEE_P));
auto const acctDelFee{drops(env.current()->fees().increment)};
env(acctdelete(alice, becky), ter(telINSUF_FEE_P));
// Try a fee one drop less than the required amount.
env (acctdelete (alice, becky),
fee (acctDelFee - drops(1)), ter (telINSUF_FEE_P));
env(acctdelete(alice, becky),
fee(acctDelFee - drops(1)),
ter(telINSUF_FEE_P));
// alice's account is created too recently to be deleted.
env (acctdelete (alice, becky), fee (acctDelFee), ter (tecTOO_SOON));
env(acctdelete(alice, becky), fee(acctDelFee), ter(tecTOO_SOON));
// Give becky a trustline. She is no longer deletable.
env (trust (becky, gw["USD"](1000)));
env(trust(becky, gw["USD"](1000)));
env.close();
// Give carol a deposit preauthorization, an offer, and a signer list.
// Even with all that she's still deletable.
env (deposit::auth (carol, becky));
std::uint32_t const carolOfferSeq {env.seq (carol)};
env (offer (carol, gw["USD"](51), XRP (51)));
env (signers (carol, 1, {{alice, 1}, {becky, 1}}));
env(deposit::auth(carol, becky));
std::uint32_t const carolOfferSeq{env.seq(carol)};
env(offer(carol, gw["USD"](51), XRP(51)));
env(signers(carol, 1, {{alice, 1}, {becky, 1}}));
// Deleting should fail with TOO_SOON, which is a relatively
// cheap check compared to validating the contents of her directory.
env (acctdelete (alice, becky), fee (acctDelFee), ter (tecTOO_SOON));
env(acctdelete(alice, becky), fee(acctDelFee), ter(tecTOO_SOON));
// Close enough ledgers to almost be able to delete alice's account.
incLgrSeqForAccDel(env, alice, 1);
// alice's account is still created too recently to be deleted.
env (acctdelete (alice, becky), fee (acctDelFee), ter (tecTOO_SOON));
env(acctdelete(alice, becky), fee(acctDelFee), ter(tecTOO_SOON));
// The most recent delete attempt advanced alice's sequence. So
// close two ledgers and her account should be deletable.
@@ -162,70 +167,72 @@ public:
env.close();
{
auto const aliceOldBalance {env.balance (alice)};
auto const beckyOldBalance {env.balance (becky)};
auto const aliceOldBalance{env.balance(alice)};
auto const beckyOldBalance{env.balance(becky)};
// Verify that alice's account exists but she has no directory.
BEAST_EXPECT (env.closed()->exists(keylet::account (alice.id())));
BEAST_EXPECT (! env.closed()->exists(keylet::ownerDir(alice.id())));
BEAST_EXPECT(env.closed()->exists(keylet::account(alice.id())));
BEAST_EXPECT(!env.closed()->exists(keylet::ownerDir(alice.id())));
env (acctdelete (alice, becky), fee (acctDelFee));
verifyDeliveredAmount (env, aliceOldBalance - acctDelFee);
env(acctdelete(alice, becky), fee(acctDelFee));
verifyDeliveredAmount(env, aliceOldBalance - acctDelFee);
env.close();
// Verify that alice's account and directory are actually gone.
BEAST_EXPECT (! env.closed()->exists(keylet::account (alice.id())));
BEAST_EXPECT (! env.closed()->exists(keylet::ownerDir(alice.id())));
BEAST_EXPECT(!env.closed()->exists(keylet::account(alice.id())));
BEAST_EXPECT(!env.closed()->exists(keylet::ownerDir(alice.id())));
// Verify that alice's XRP, minus the fee, was transferred to becky.
BEAST_EXPECT (env.balance (becky) ==
BEAST_EXPECT(
env.balance(becky) ==
aliceOldBalance + beckyOldBalance - acctDelFee);
}
// Attempt to delete becky's account but get stopped by the trust line.
env (acctdelete (becky, carol),
fee (acctDelFee), ter (tecHAS_OBLIGATIONS));
env(acctdelete(becky, carol), fee(acctDelFee), ter(tecHAS_OBLIGATIONS));
env.close();
// Verify that becky's account is still there.
env (noop (becky));
env(noop(becky));
{
auto const beckyOldBalance {env.balance (becky)};
auto const carolOldBalance {env.balance (carol)};
auto const beckyOldBalance{env.balance(becky)};
auto const carolOldBalance{env.balance(carol)};
// Verify that Carol's account, directory, deposit
// preauthorization, offer, and signer list exist.
BEAST_EXPECT (env.closed()->exists (keylet::account (carol.id())));
BEAST_EXPECT (env.closed()->exists (keylet::ownerDir(carol.id())));
BEAST_EXPECT (env.closed()->exists (keylet::depositPreauth(
carol.id(), becky.id())));
BEAST_EXPECT (env.closed()->exists (keylet::offer(
carol.id(), carolOfferSeq)));
BEAST_EXPECT (env.closed()->exists (keylet::signers (carol.id())));
BEAST_EXPECT(env.closed()->exists(keylet::account(carol.id())));
BEAST_EXPECT(env.closed()->exists(keylet::ownerDir(carol.id())));
BEAST_EXPECT(env.closed()->exists(
keylet::depositPreauth(carol.id(), becky.id())));
BEAST_EXPECT(
env.closed()->exists(keylet::offer(carol.id(), carolOfferSeq)));
BEAST_EXPECT(env.closed()->exists(keylet::signers(carol.id())));
// Delete carol's account even with stuff in her directory. Show
// that multisigning for the delete does not increase carol's fee.
env (acctdelete (carol, becky), fee (acctDelFee), msig (alice));
verifyDeliveredAmount (env, carolOldBalance - acctDelFee);
env(acctdelete(carol, becky), fee(acctDelFee), msig(alice));
verifyDeliveredAmount(env, carolOldBalance - acctDelFee);
env.close();
// Verify that Carol's account, directory, and other stuff are gone.
BEAST_EXPECT (! env.closed()->exists(keylet::account (carol.id())));
BEAST_EXPECT (! env.closed()->exists(keylet::ownerDir(carol.id())));
BEAST_EXPECT (! env.closed()->exists(keylet::depositPreauth (
carol.id(), becky.id())));
BEAST_EXPECT (! env.closed()->exists(keylet::offer (
carol.id(), carolOfferSeq)));
BEAST_EXPECT (! env.closed()->exists(keylet::signers (carol.id())));
BEAST_EXPECT(!env.closed()->exists(keylet::account(carol.id())));
BEAST_EXPECT(!env.closed()->exists(keylet::ownerDir(carol.id())));
BEAST_EXPECT(!env.closed()->exists(
keylet::depositPreauth(carol.id(), becky.id())));
BEAST_EXPECT(!env.closed()->exists(
keylet::offer(carol.id(), carolOfferSeq)));
BEAST_EXPECT(!env.closed()->exists(keylet::signers(carol.id())));
// Verify that Carol's XRP, minus the fee, was transferred to becky.
BEAST_EXPECT (env.balance (becky) ==
BEAST_EXPECT(
env.balance(becky) ==
carolOldBalance + beckyOldBalance - acctDelFee);
}
}
void testDirectories()
void
testDirectories()
{
// The code that deletes consecutive directory entries uses a
// peculiarity of the implementation. Make sure that peculiarity
@@ -234,7 +241,7 @@ public:
testcase("Directories");
Env env {*this};
Env env{*this};
Account const alice("alice");
Account const gw("gw");
@@ -242,35 +249,36 @@ public:
env.close();
// Alice creates enough offers to require two owner directories.
for (int i {0}; i < 45; ++i)
for (int i{0}; i < 45; ++i)
{
env (offer (alice, gw["USD"](1), XRP (1)));
env(offer(alice, gw["USD"](1), XRP(1)));
env.close();
}
env.require (offers (alice, 45));
env.require(offers(alice, 45));
// Close enough ledgers to be able to delete alice's account.
incLgrSeqForAccDel(env, alice);
// Verify that both directory nodes exist.
Keylet const aliceRootKey {keylet::ownerDir (alice.id())};
Keylet const alicePageKey {keylet::page (aliceRootKey, 1)};
BEAST_EXPECT (env.closed()->exists (aliceRootKey));
BEAST_EXPECT (env.closed()->exists (alicePageKey));
Keylet const aliceRootKey{keylet::ownerDir(alice.id())};
Keylet const alicePageKey{keylet::page(aliceRootKey, 1)};
BEAST_EXPECT(env.closed()->exists(aliceRootKey));
BEAST_EXPECT(env.closed()->exists(alicePageKey));
// Delete alice's account.
auto const acctDelFee {drops (env.current()->fees().increment)};
auto const aliceBalance {env.balance (alice)};
env (acctdelete (alice, gw), fee (acctDelFee));
verifyDeliveredAmount (env, aliceBalance - acctDelFee);
auto const acctDelFee{drops(env.current()->fees().increment)};
auto const aliceBalance{env.balance(alice)};
env(acctdelete(alice, gw), fee(acctDelFee));
verifyDeliveredAmount(env, aliceBalance - acctDelFee);
env.close();
// Both of alice's directory nodes should be gone.
BEAST_EXPECT (! env.closed()->exists (aliceRootKey));
BEAST_EXPECT (! env.closed()->exists (alicePageKey));
BEAST_EXPECT(!env.closed()->exists(aliceRootKey));
BEAST_EXPECT(!env.closed()->exists(alicePageKey));
}
void testOwnedTypes()
void
testOwnedTypes()
{
using namespace jtx;
@@ -281,7 +289,7 @@ public:
// o New-styled PayChannels with the backlink.
// So we start the test using old-style PayChannels. Then we pass
// the amendment to get new-style PayChannels.
Env env {*this, supported_amendments() - fixPayChanRecipientOwnerDir};
Env env{*this, supported_amendments() - fixPayChanRecipientOwnerDir};
Account const alice("alice");
Account const becky("becky");
Account const gw("gw");
@@ -292,14 +300,14 @@ public:
// Give alice and becky a bunch of offers that we have to search
// through before we figure out that there's a non-deletable
// entry in their directory.
for (int i {0}; i < 200; ++i)
for (int i{0}; i < 200; ++i)
{
env (offer (alice, gw["USD"](1), XRP (1)));
env (offer (becky, gw["USD"](1), XRP (1)));
env(offer(alice, gw["USD"](1), XRP(1)));
env(offer(becky, gw["USD"](1), XRP(1)));
env.close();
}
env.require (offers (alice, 200));
env.require (offers (becky, 200));
env.require(offers(alice, 200));
env.require(offers(becky, 200));
// Close enough ledgers to be able to delete alice's and becky's
// accounts.
@@ -309,26 +317,26 @@ public:
// alice writes a check to becky. Until that check is cashed or
// canceled it will prevent alice's and becky's accounts from being
// deleted.
uint256 const checkId {getCheckIndex (alice, env.seq (alice))};
env (check::create (alice, becky, XRP (1)));
uint256 const checkId{getCheckIndex(alice, env.seq(alice))};
env(check::create(alice, becky, XRP(1)));
env.close();
auto const acctDelFee {drops (env.current()->fees().increment)};
env (acctdelete (alice, gw), fee(acctDelFee), ter(tecHAS_OBLIGATIONS));
env (acctdelete (becky, gw), fee(acctDelFee), ter(tecHAS_OBLIGATIONS));
auto const acctDelFee{drops(env.current()->fees().increment)};
env(acctdelete(alice, gw), fee(acctDelFee), ter(tecHAS_OBLIGATIONS));
env(acctdelete(becky, gw), fee(acctDelFee), ter(tecHAS_OBLIGATIONS));
env.close();
// Cancel the check, but add an escrow. Again, with the escrow
// on board, alice and becky should not be able to delete their
// accounts.
env (check::cancel (becky, checkId));
env(check::cancel(becky, checkId));
env.close();
// Lambda to create an escrow.
auto escrowCreate = [] (
jtx::Account const& account, jtx::Account const& to,
STAmount const& amount, NetClock::time_point const& cancelAfter)
{
auto escrowCreate = [](jtx::Account const& account,
jtx::Account const& to,
STAmount const& amount,
NetClock::time_point const& cancelAfter) {
Json::Value jv;
jv[jss::TransactionType] = jss::EscrowCreate;
jv[jss::Flags] = tfUniversal;
@@ -343,101 +351,98 @@ public:
};
using namespace std::chrono_literals;
std::uint32_t const escrowSeq {env.seq (alice)};
env (escrowCreate (alice, becky, XRP(333), env.now() + 2s));
std::uint32_t const escrowSeq{env.seq(alice)};
env(escrowCreate(alice, becky, XRP(333), env.now() + 2s));
env.close();
// alice and becky should be unable to delete their accounts because
// of the escrow.
env (acctdelete (alice, gw), fee(acctDelFee), ter (tecHAS_OBLIGATIONS));
env (acctdelete (becky, gw), fee(acctDelFee), ter (tecHAS_OBLIGATIONS));
env(acctdelete(alice, gw), fee(acctDelFee), ter(tecHAS_OBLIGATIONS));
env(acctdelete(becky, gw), fee(acctDelFee), ter(tecHAS_OBLIGATIONS));
env.close();
// Now cancel the escrow, but create a payment channel between
// alice and becky.
// Lambda to cancel an escrow.
auto escrowCancel = [] (Account const& account,
Account const& from, std::uint32_t seq)
{
Json::Value jv;
jv[jss::TransactionType] = jss::EscrowCancel;
jv[jss::Flags] = tfUniversal;
jv[jss::Account] = account.human();
jv[sfOwner.jsonName] = from.human();
jv[sfOfferSequence.jsonName] = seq;
return jv;
};
env (escrowCancel (becky, alice, escrowSeq));
auto escrowCancel =
[](Account const& account, Account const& from, std::uint32_t seq) {
Json::Value jv;
jv[jss::TransactionType] = jss::EscrowCancel;
jv[jss::Flags] = tfUniversal;
jv[jss::Account] = account.human();
jv[sfOwner.jsonName] = from.human();
jv[sfOfferSequence.jsonName] = seq;
return jv;
};
env(escrowCancel(becky, alice, escrowSeq));
env.close();
Keylet const alicePayChanKey {
keylet::payChan (alice, becky, env.seq (alice))};
Keylet const alicePayChanKey{
keylet::payChan(alice, becky, env.seq(alice))};
env (payChanCreate (
env(payChanCreate(
alice, becky, XRP(57), 4s, env.now() + 2s, alice.pk()));
env.close();
// An old-style PayChannel does not add a back link from the
// destination. So with the PayChannel in place becky should be
// able to delete her account, but alice should not.
auto const beckyBalance {env.balance (becky)};
env (acctdelete (alice, gw), fee(acctDelFee), ter (tecHAS_OBLIGATIONS));
env (acctdelete (becky, gw), fee(acctDelFee));
verifyDeliveredAmount (env, beckyBalance - acctDelFee);
auto const beckyBalance{env.balance(becky)};
env(acctdelete(alice, gw), fee(acctDelFee), ter(tecHAS_OBLIGATIONS));
env(acctdelete(becky, gw), fee(acctDelFee));
verifyDeliveredAmount(env, beckyBalance - acctDelFee);
env.close();
// Alice cancels her PayChannel which will leave her with only offers
// in her directory.
// Lambda to close a PayChannel.
auto payChanClose = [] (
jtx::Account const& account,
Keylet const& payChanKeylet,
PublicKey const& pk)
{
auto payChanClose = [](jtx::Account const& account,
Keylet const& payChanKeylet,
PublicKey const& pk) {
Json::Value jv;
jv[jss::TransactionType] = jss::PaymentChannelClaim;
jv[jss::Flags] = tfClose;
jv[jss::Account] = account.human();
jv[sfPayChannel.jsonName] = to_string (payChanKeylet.key);
jv[sfPayChannel.jsonName] = to_string(payChanKeylet.key);
jv[sfPublicKey.jsonName] = strHex(pk.slice());
return jv;
};
env (payChanClose (alice, alicePayChanKey, alice.pk()));
env(payChanClose(alice, alicePayChanKey, alice.pk()));
env.close();
// Now enable the amendment so PayChannels add a backlink from the
// destination.
env.enableFeature (fixPayChanRecipientOwnerDir);
env.enableFeature(fixPayChanRecipientOwnerDir);
env.close();
// gw creates a PayChannel with alice as the destination. With the
// amendment passed this should prevent alice from deleting her
// account.
Keylet const gwPayChanKey {keylet::payChan (gw, alice, env.seq (gw))};
Keylet const gwPayChanKey{keylet::payChan(gw, alice, env.seq(gw))};
env (payChanCreate (
gw, alice, XRP(68), 4s, env.now() + 2s, alice.pk()));
env(payChanCreate(gw, alice, XRP(68), 4s, env.now() + 2s, alice.pk()));
env.close();
// alice can't delete her account because of the PayChannel.
env (acctdelete (alice, gw), fee(acctDelFee), ter (tecHAS_OBLIGATIONS));
env(acctdelete(alice, gw), fee(acctDelFee), ter(tecHAS_OBLIGATIONS));
env.close();
// alice closes the PayChannel which should (finally) allow her to
// delete her account.
env (payChanClose (alice, gwPayChanKey, alice.pk()));
env(payChanClose(alice, gwPayChanKey, alice.pk()));
env.close();
// Now alice can successfully delete her account.
auto const aliceBalance {env.balance (alice)};
env (acctdelete (alice, gw), fee(acctDelFee));
verifyDeliveredAmount (env, aliceBalance - acctDelFee);
auto const aliceBalance{env.balance(alice)};
env(acctdelete(alice, gw), fee(acctDelFee));
verifyDeliveredAmount(env, aliceBalance - acctDelFee);
env.close();
}
void testResurrection()
void
testResurrection()
{
// Create an account with an old-style PayChannel. Delete the
// destination of the PayChannel then resurrect the destination.
@@ -448,7 +453,7 @@ public:
// We need an old-style PayChannel that doesn't provide a backlink
// from the destination. So don't enable the amendment with that fix.
Env env {*this, supported_amendments() - fixPayChanRecipientOwnerDir};
Env env{*this, supported_amendments() - fixPayChanRecipientOwnerDir};
Account const alice("alice");
Account const becky("becky");
@@ -456,66 +461,64 @@ public:
env.close();
// Verify that becky's account root is present.
Keylet const beckyAcctKey {keylet::account (becky.id())};
BEAST_EXPECT (env.closed()->exists (beckyAcctKey));
Keylet const beckyAcctKey{keylet::account(becky.id())};
BEAST_EXPECT(env.closed()->exists(beckyAcctKey));
using namespace std::chrono_literals;
Keylet const payChanKey {
keylet::payChan (alice, becky, env.seq (alice))};
auto const payChanXRP = XRP (37);
Keylet const payChanKey{keylet::payChan(alice, becky, env.seq(alice))};
auto const payChanXRP = XRP(37);
env (payChanCreate (
env(payChanCreate(
alice, becky, payChanXRP, 4s, env.now() + 1h, alice.pk()));
env.close();
BEAST_EXPECT (env.closed()->exists (payChanKey));
BEAST_EXPECT(env.closed()->exists(payChanKey));
// Close enough ledgers to be able to delete becky's account.
incLgrSeqForAccDel(env, becky);
auto const beckyPreDelBalance {env.balance (becky)};
auto const beckyPreDelBalance{env.balance(becky)};
auto const acctDelFee {drops (env.current()->fees().increment)};
env (acctdelete (becky, alice), fee(acctDelFee));
verifyDeliveredAmount (
env, beckyPreDelBalance - acctDelFee);
auto const acctDelFee{drops(env.current()->fees().increment)};
env(acctdelete(becky, alice), fee(acctDelFee));
verifyDeliveredAmount(env, beckyPreDelBalance - acctDelFee);
env.close();
// Verify that becky's account root is gone.
BEAST_EXPECT (! env.closed()->exists (beckyAcctKey));
BEAST_EXPECT(!env.closed()->exists(beckyAcctKey));
// All it takes is a large enough XRP payment to resurrect
// becky's account. Try too small a payment.
env (pay (alice, becky, XRP (19)), ter (tecNO_DST_INSUF_XRP));
env(pay(alice, becky, XRP(19)), ter(tecNO_DST_INSUF_XRP));
env.close();
// Actually resurrect becky's account.
env (pay (alice, becky, XRP (20)));
env(pay(alice, becky, XRP(20)));
env.close();
// becky's account root should be back.
BEAST_EXPECT (env.closed()->exists (beckyAcctKey));
BEAST_EXPECT (env.balance (becky) == XRP (20));
BEAST_EXPECT(env.closed()->exists(beckyAcctKey));
BEAST_EXPECT(env.balance(becky) == XRP(20));
// becky's resurrected account can be the destination of alice's
// PayChannel.
auto payChanClaim = [&] ()
{
auto payChanClaim = [&]() {
Json::Value jv;
jv[jss::TransactionType] = jss::PaymentChannelClaim;
jv[jss::Flags] = tfUniversal;
jv[jss::Account] = alice.human ();
jv[sfPayChannel.jsonName] = to_string (payChanKey.key);
jv[jss::Account] = alice.human();
jv[sfPayChannel.jsonName] = to_string(payChanKey.key);
jv[sfBalance.jsonName] =
payChanXRP.value().getJson (JsonOptions::none);
payChanXRP.value().getJson(JsonOptions::none);
return jv;
};
env (payChanClaim());
env(payChanClaim());
env.close();
BEAST_EXPECT (env.balance (becky) == XRP (20) + payChanXRP);
BEAST_EXPECT(env.balance(becky) == XRP(20) + payChanXRP);
}
void testAmendmentEnable()
void
testAmendmentEnable()
{
// Start with the featureDeletableAccounts amendment disabled.
// Then enable the amendment and delete an account.
@@ -523,7 +526,7 @@ public:
testcase("Amendment enable");
Env env {*this, supported_amendments() - featureDeletableAccounts};
Env env{*this, supported_amendments() - featureDeletableAccounts};
Account const alice("alice");
Account const becky("becky");
@@ -534,48 +537,49 @@ public:
incLgrSeqForAccDel(env, alice);
// Verify that alice's account root is present.
Keylet const aliceAcctKey {keylet::account (alice.id())};
BEAST_EXPECT (env.closed()->exists (aliceAcctKey));
Keylet const aliceAcctKey{keylet::account(alice.id())};
BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
auto const alicePreDelBal {env.balance (alice)};
auto const beckyPreDelBal {env.balance (becky)};
auto const alicePreDelBal{env.balance(alice)};
auto const beckyPreDelBal{env.balance(becky)};
auto const acctDelFee {drops (env.current()->fees().increment)};
env (acctdelete (alice, becky), fee(acctDelFee), ter (temDISABLED));
auto const acctDelFee{drops(env.current()->fees().increment)};
env(acctdelete(alice, becky), fee(acctDelFee), ter(temDISABLED));
env.close();
// Verify that alice's account root is still present and alice and
// becky both have their XRP.
BEAST_EXPECT (env.current()->exists (aliceAcctKey));
BEAST_EXPECT (env.balance (alice) == alicePreDelBal);
BEAST_EXPECT (env.balance (becky) == beckyPreDelBal);
BEAST_EXPECT(env.current()->exists(aliceAcctKey));
BEAST_EXPECT(env.balance(alice) == alicePreDelBal);
BEAST_EXPECT(env.balance(becky) == beckyPreDelBal);
// When the amendment is enabled the previous transaction is
// retried into the new open ledger and succeeds.
env.enableFeature (featureDeletableAccounts);
env.enableFeature(featureDeletableAccounts);
env.close();
// alice's account is still in the most recently closed ledger.
BEAST_EXPECT (env.closed()->exists (aliceAcctKey));
BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
// Verify that alice's account root is gone from the current ledger
// and becky has alice's XRP.
BEAST_EXPECT (! env.current()->exists (aliceAcctKey));
BEAST_EXPECT (env.balance (becky) ==
alicePreDelBal + beckyPreDelBal - acctDelFee);
BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
BEAST_EXPECT(
env.balance(becky) == alicePreDelBal + beckyPreDelBal - acctDelFee);
env.close();
BEAST_EXPECT (! env.closed()->exists (aliceAcctKey));
BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
}
void testTooManyOffers()
void
testTooManyOffers()
{
// Put enough offers in an account that we refuse to delete the account.
using namespace jtx;
testcase("Too many offers");
Env env {*this};
Env env{*this};
Account const alice("alice");
Account const gw("gw");
@@ -585,15 +589,15 @@ public:
// To increase the number of Books affected, change the currency of
// each offer.
std::string currency {"AAA"};
std::string currency{"AAA"};
// Alice creates 1001 offers. This is one greater than the number of
// directory entries an AccountDelete will remove.
std::uint32_t const offerSeq0 {env.seq (alice)};
constexpr int offerCount {1001};
for (int i {0}; i < offerCount; ++i)
std::uint32_t const offerSeq0{env.seq(alice)};
constexpr int offerCount{1001};
for (int i{0}; i < offerCount; ++i)
{
env (offer (alice, gw[currency](1), XRP (1)));
env(offer(alice, gw[currency](1), XRP(1)));
env.close();
// Increment to next currency.
@@ -620,61 +624,61 @@ public:
incLgrSeqForAccDel(env, alice);
// Verify the existence of the expected ledger entries.
Keylet const aliceOwnerDirKey {keylet::ownerDir (alice.id())};
Keylet const aliceOwnerDirKey{keylet::ownerDir(alice.id())};
{
std::shared_ptr<ReadView const> closed {env.closed()};
BEAST_EXPECT (closed->exists (keylet::account (alice.id())));
BEAST_EXPECT (closed->exists (aliceOwnerDirKey));
std::shared_ptr<ReadView const> closed{env.closed()};
BEAST_EXPECT(closed->exists(keylet::account(alice.id())));
BEAST_EXPECT(closed->exists(aliceOwnerDirKey));
// alice's directory nodes.
for (std::uint32_t i {0}; i < ((offerCount / 32) + 1); ++i)
BEAST_EXPECT (closed->exists (
keylet::page (aliceOwnerDirKey, i)));
for (std::uint32_t i{0}; i < ((offerCount / 32) + 1); ++i)
BEAST_EXPECT(closed->exists(keylet::page(aliceOwnerDirKey, i)));
// alice's offers.
for (std::uint32_t i {0}; i < offerCount; ++i)
BEAST_EXPECT (closed->exists (
keylet::offer (alice.id(), offerSeq0 + i)));
for (std::uint32_t i{0}; i < offerCount; ++i)
BEAST_EXPECT(
closed->exists(keylet::offer(alice.id(), offerSeq0 + i)));
}
// Delete alice's account. Should fail because she has too many
// offers in her directory.
auto const acctDelFee {drops (env.current()->fees().increment)};
auto const acctDelFee{drops(env.current()->fees().increment)};
env (acctdelete (alice, gw), fee (acctDelFee), ter (tefTOO_BIG));
env(acctdelete(alice, gw), fee(acctDelFee), ter(tefTOO_BIG));
// Cancel one of alice's offers. Then the account delete can succeed.
env.require (offers (alice, offerCount));
env.require(offers(alice, offerCount));
env(offer_cancel(alice, offerSeq0));
env.close();
env.require (offers (alice, offerCount - 1));
env.require(offers(alice, offerCount - 1));
// alice successfully deletes her account.
auto const alicePreDelBal {env.balance (alice)};
env (acctdelete (alice, gw), fee (acctDelFee));
verifyDeliveredAmount (env, alicePreDelBal - acctDelFee);
auto const alicePreDelBal{env.balance(alice)};
env(acctdelete(alice, gw), fee(acctDelFee));
verifyDeliveredAmount(env, alicePreDelBal - acctDelFee);
env.close();
// Verify that alice's account root is gone as well as her directory
// nodes and all of her offers.
{
std::shared_ptr<ReadView const> closed {env.closed()};
BEAST_EXPECT (! closed->exists (keylet::account (alice.id())));
BEAST_EXPECT (! closed->exists (aliceOwnerDirKey));
std::shared_ptr<ReadView const> closed{env.closed()};
BEAST_EXPECT(!closed->exists(keylet::account(alice.id())));
BEAST_EXPECT(!closed->exists(aliceOwnerDirKey));
// alice's former directory nodes.
for (std::uint32_t i {0}; i < ((offerCount / 32) + 1); ++i)
BEAST_EXPECT (! closed->exists (
keylet::page (aliceOwnerDirKey, i)));
for (std::uint32_t i{0}; i < ((offerCount / 32) + 1); ++i)
BEAST_EXPECT(
!closed->exists(keylet::page(aliceOwnerDirKey, i)));
// alice's former offers.
for (std::uint32_t i {0}; i < offerCount; ++i)
BEAST_EXPECT (! closed->exists (
keylet::offer (alice.id(), offerSeq0 + i)));
for (std::uint32_t i{0}; i < offerCount; ++i)
BEAST_EXPECT(
!closed->exists(keylet::offer(alice.id(), offerSeq0 + i)));
}
}
void testImplicitlyCreatedTrustline()
void
testImplicitlyCreatedTrustline()
{
// Show that a trust line that is implicitly created by offer crossing
// prevents an account from being deleted.
@@ -682,43 +686,44 @@ public:
testcase("Implicitly created trust line");
Env env {*this};
Env env{*this};
Account const alice{"alice"};
Account const gw{"gw"};
auto const BUX {gw["BUX"]};
auto const BUX{gw["BUX"]};
env.fund(XRP(10000), alice, gw);
env.close();
// alice creates an offer that, if crossed, will implicitly create
// a trust line.
env (offer (alice, BUX(30), XRP(30)));
env(offer(alice, BUX(30), XRP(30)));
env.close();
// gw crosses alice's offer. alice should end up with BUX(30).
env (offer (gw, XRP(30), BUX(30)));
env(offer(gw, XRP(30), BUX(30)));
env.close();
env.require (balance (alice, BUX(30)));
env.require(balance(alice, BUX(30)));
// Close enough ledgers to be able to delete alice's account.
incLgrSeqForAccDel(env, alice);
// alice and gw can't delete their accounts because of the implicitly
// created trust line.
auto const acctDelFee {drops (env.current()->fees().increment)};
env (acctdelete (alice, gw), fee (acctDelFee), ter(tecHAS_OBLIGATIONS));
auto const acctDelFee{drops(env.current()->fees().increment)};
env(acctdelete(alice, gw), fee(acctDelFee), ter(tecHAS_OBLIGATIONS));
env.close();
env (acctdelete (gw, alice), fee (acctDelFee), ter(tecHAS_OBLIGATIONS));
env(acctdelete(gw, alice), fee(acctDelFee), ter(tecHAS_OBLIGATIONS));
env.close();
{
std::shared_ptr<ReadView const> closed {env.closed()};
BEAST_EXPECT (closed->exists (keylet::account (alice.id())));
BEAST_EXPECT (closed->exists (keylet::account (gw.id())));
std::shared_ptr<ReadView const> closed{env.closed()};
BEAST_EXPECT(closed->exists(keylet::account(alice.id())));
BEAST_EXPECT(closed->exists(keylet::account(gw.id())));
}
}
void testBalanceTooSmallForFee()
void
testBalanceTooSmallForFee()
{
// See what happens when an account with a balance less than the
// incremental reserve tries to delete itself.
@@ -726,51 +731,52 @@ public:
testcase("Balance too small for fee");
Env env {*this};
Env env{*this};
Account const alice("alice");
// Note that the fee structure for unit tests does not match the fees
// on the production network (October 2019). Unit tests have a base
// reserve of 200 XRP.
env.fund (env.current()->fees().accountReserve(0), noripple (alice));
env.fund(env.current()->fees().accountReserve(0), noripple(alice));
env.close();
// Burn a chunk of alice's funds so she only has 1 XRP remaining in
// her account.
env (noop (alice), fee (env.balance(alice) - XRP(1)));
env(noop(alice), fee(env.balance(alice) - XRP(1)));
env.close();
auto const acctDelFee {drops (env.current()->fees().increment)};
BEAST_EXPECT (acctDelFee > env.balance (alice));
auto const acctDelFee{drops(env.current()->fees().increment)};
BEAST_EXPECT(acctDelFee > env.balance(alice));
// alice attempts to delete her account even though she can't pay
// the full fee. She specifies a fee that is larger than her balance.
//
// The balance of env.master should not change.
auto const masterBalance {env.balance (env.master)};
env (acctdelete (alice, env.master), fee(acctDelFee),
ter (terINSUF_FEE_B));
auto const masterBalance{env.balance(env.master)};
env(acctdelete(alice, env.master),
fee(acctDelFee),
ter(terINSUF_FEE_B));
env.close();
{
std::shared_ptr<ReadView const> const closed {env.closed()};
BEAST_EXPECT (closed->exists (keylet::account (alice.id())));
BEAST_EXPECT (env.balance (env.master) == masterBalance);
std::shared_ptr<ReadView const> const closed{env.closed()};
BEAST_EXPECT(closed->exists(keylet::account(alice.id())));
BEAST_EXPECT(env.balance(env.master) == masterBalance);
}
// alice again attempts to delete her account. This time she specifies
// her current balance in XRP. Again the transaction fails.
BEAST_EXPECT (env.balance (alice) == XRP (1));
env (acctdelete (alice, env.master), fee(XRP (1)),
ter (telINSUF_FEE_P));
BEAST_EXPECT(env.balance(alice) == XRP(1));
env(acctdelete(alice, env.master), fee(XRP(1)), ter(telINSUF_FEE_P));
env.close();
{
std::shared_ptr<ReadView const> closed {env.closed()};
BEAST_EXPECT (closed->exists (keylet::account (alice.id())));
BEAST_EXPECT (env.balance (env.master) == masterBalance);
std::shared_ptr<ReadView const> closed{env.closed()};
BEAST_EXPECT(closed->exists(keylet::account(alice.id())));
BEAST_EXPECT(env.balance(env.master) == masterBalance);
}
}
void run() override
void
run() override
{
testBasics();
testDirectories();
@@ -783,7 +789,7 @@ public:
}
};
BEAST_DEFINE_TESTSUITE(AccountDelete,app,ripple);
BEAST_DEFINE_TESTSUITE(AccountDelete, app, ripple);
} // test
} // ripple
} // namespace test
} // namespace ripple