1#include <test/jtx/Account.h>
2#include <test/jtx/Env.h>
3#include <test/jtx/acctdelete.h>
4#include <test/jtx/amount.h>
5#include <test/jtx/attester.h>
6#include <test/jtx/envconfig.h>
7#include <test/jtx/fee.h>
8#include <test/jtx/flags.h>
9#include <test/jtx/multisign.h>
10#include <test/jtx/pay.h>
11#include <test/jtx/regkey.h>
12#include <test/jtx/ter.h>
13#include <test/jtx/trust.h>
14#include <test/jtx/txflags.h>
15#include <test/jtx/xchain_bridge.h>
17#include <xrpld/core/Config.h>
19#include <xrpl/basics/Log.h>
20#include <xrpl/basics/base_uint.h>
21#include <xrpl/beast/unit_test/suite.h>
22#include <xrpl/beast/utility/Journal.h>
23#include <xrpl/core/ServiceRegistry.h>
24#include <xrpl/json/json_value.h>
25#include <xrpl/protocol/Feature.h>
26#include <xrpl/protocol/Indexes.h>
27#include <xrpl/protocol/Issue.h>
28#include <xrpl/protocol/KeyType.h>
29#include <xrpl/protocol/SField.h>
30#include <xrpl/protocol/STAmount.h>
31#include <xrpl/protocol/STXChainBridge.h>
32#include <xrpl/protocol/TER.h>
33#include <xrpl/protocol/TxFlags.h>
34#include <xrpl/protocol/XRPAmount.h>
73 :
env(s,
std::move(config), features,
std::move(logs), thresh)
87 env.enableFeature(feature);
94 env.app().config().features.erase(feature);
98 template <
class Arg,
class... Args>
102 env.fund(amount, arg, args...);
106 template <
class JsonValue,
class... FN>
108 tx(JsonValue&& jv, FN
const&... fN)
114 template <
class... FN>
118 for (
auto const& jv : jvv)
144 return env.current()->fees().accountReserve(count);
150 return env.current()->fees().base;
167 if ((*r)[sfXChainBridge] == b)
180 return (*
bridge(jvb))[sfXChainAccountClaimCount];
186 return (*
bridge(jvb))[sfXChainClaimID];
221 this->
fund(xrpFunds, s.account);
228 this->
fund(xrpFunds, ra);
231 this->
fund(xrpFunds, s.account);
281 :
from(env, fromAcct)
287 for (
size_t i = 0; i < numPayees; ++i)
324 (!checkPayer ||
payer.diff() == -(rewardCost +
txFees));
386 bool exceptionPresent =
false;
389 exceptionPresent =
false;
394 exceptionPresent =
true;
397 BEAST_EXPECT(!exceptionPresent);
401 exceptionPresent =
false;
402 jBridge[
"Extra"] = 1;
407 exceptionPresent =
true;
410 BEAST_EXPECT(exceptionPresent);
568 testcase(
"Bridge create constraints");
569 XEnv env(*
this,
true);
573 auto ausd = a[
"USD"];
574 auto busd = b[
"USD"];
575 auto cusd = c[
"USD"];
576 auto gusd =
scGw[
"USD"];
577 auto aeur = a[
"EUR"];
578 auto beur = b[
"EUR"];
579 auto ceur = c[
"EUR"];
580 auto geur =
scGw[
"EUR"];
590 env.
fund(
XRP(10000), a1, a2, a3, a4, a5, a6);
609 auto const goodBridge1 =
bridge(a, gusd, b, busd);
610 auto const goodBridge2 =
bridge(a, busd, c, cusd);
625 .
tx(
pay(b, c, busd(1000)))
627 auto const aBalanceStart = env.
balance(a, busd);
628 auto const cBalanceStart = env.
balance(c, busd);
630 BEAST_EXPECT(env.
balance(a, busd) - aBalanceStart == busd(0));
631 BEAST_EXPECT(env.
balance(c, busd) - cBalanceStart == busd(-50));
633 BEAST_EXPECT(env.
balance(a, busd) - aBalanceStart == busd(60));
634 BEAST_EXPECT(env.
balance(c, busd) - cBalanceStart == busd(-50 - 60));
638 BEAST_EXPECT((*env.
bridge(goodBridge1))[sfSignatureReward] ==
XRP(33));
640 BEAST_EXPECT((*env.
bridge(goodBridge2))[sfSignatureReward] ==
XRP(44));
690 "Locking chain is IOU(locking chain door)",
691 [&](
auto& env,
bool) {
696 "Locking chain is IOU(issuing chain door funded on locking "
698 [&](
auto& env,
bool shouldFund) {
705 "Locking chain is IOU(issuing chain door account unfunded "
707 [&](
auto& env,
bool) {
712 "Locking chain is IOU(bob funded on locking chain)",
713 [&](
auto& env,
bool) {
718 "Locking chain is IOU(bob unfunded on locking chain)",
719 [&](
auto& env,
bool) {
730 "Issuing chain is IOU(issuing chain door account)",
731 [&](
auto& env,
bool) {
736 "Issuing chain is IOU(locking chain door funded on issuing "
738 [&](
auto& env,
bool shouldFund) {
745 "Issuing chain is IOU(locking chain door unfunded on "
747 [&](
auto& env,
bool) {
752 "Issuing chain is IOU(bob funded on issuing chain)",
753 [&](
auto& env,
bool) {
758 "Issuing chain is IOU(bob unfunded on issuing chain)",
759 [&](
auto& env,
bool) {
764 "Issuing chain is XRP and issuing chain door account is "
765 "not the root account",
766 [&](
auto& env,
bool) {
771 "Issuing chain is XRP and issuing chain door account is "
773 [&](
auto& env,
bool) {
824 auto testcase = [&](
auto const& lc,
auto const& ic) {
826 XEnv scEnv(*
this,
true);
828 lc.second(mcEnv,
true);
829 lc.second(scEnv,
false);
831 ic.second(mcEnv,
false);
832 ic.second(scEnv,
true);
834 auto const& expected = expectedResult[testResult.
size()];
847 auto applyIcs = [&](
auto const& lc,
auto const& ics) {
851 std::apply([&](
auto const&... lc) { (applyIcs(lc, ics), ...); }, lcs);
853#if GENERATE_MTX_OUTPUT
858 std::cout <<
"Markdown output for matrix test: " << fname <<
"\n";
864 if (std::get<2>(tup))
873 auto output_table = [&](
auto print_res) {
879 res +=
"| `issuing ->` | ";
880 std::apply([&](
auto const&... ic) { ((res += ic.first, res +=
" | "), ...); }, ics);
885 [&](
auto const&... ic) { (((void)ic.first, res +=
":---: | "), ...); }, ics);
888 auto output = [&](
auto const& lc,
auto const& ic) {
889 res += print_res(test_result[test_idx]);
894 auto output_ics = [&](
auto const& lc,
auto const& ics) {
898 std::apply([&](
auto const&... ic) { (output(lc, ic), ...); }, ics);
902 std::apply([&](
auto const&... lc) { (output_ics(lc, ics), ...); }, lcs);
910 std::cout <<
"ter output for matrix test: " << ter_fname <<
"\n";
913 for (
auto& t : test_result)
969 for (
auto withClaim : {
false,
true})
972 XEnv scEnv(*
this,
true);
983 auto const amt =
XRP(1000);
1015 for (
auto withClaim : {
false,
true})
1018 XEnv scEnv(*
this,
true);
1029 auto const amt =
XRP(1000);
1068 for (
auto withClaim : {
false,
true})
1071 XEnv scEnv(*
this,
true);
1082 auto const amt =
XRP(1000);
1171 Txflags(tfClearAccountCreateAmount),
1184 using namespace jtx;
1201 XEnv xenv(*
this,
true);
1209 BEAST_EXPECT(scAliceBal.
diff() == -fee);
1268 using namespace jtx;
1282 auto const amt =
XRP(1000);
1290 BEAST_EXPECT(aliceBal.
diff() == -(claimCost + fee));
1395 using namespace jtx;
1411 for (
auto withClaim : {
true})
1414 XEnv scEnv(*
this,
true);
1428 auto const amt =
XRP(1000);
1478 for (
auto withClaim : {
false,
true})
1481 XEnv scEnv(*
this,
true);
1485 static constexpr int kNumSigners = 4;
1490 for (
int i = 0; i < kNumSigners; ++i)
1510 auto const amt =
XRP(1000);
1536 for (
auto withClaim : {
false,
true})
1539 XEnv scEnv(*
this,
true);
1543 static constexpr int kNumSigners = 4;
1548 for (
int i = 0; i < kNumSigners; ++i)
1569 auto const amt =
XRP(1000);
1578 scAttester,
jvb,
mcAlice, amt,
payees,
true, claimID, dst,
signers, 2, 2))
1595 for (
auto withClaim : {
false,
true})
1598 XEnv scEnv(*
this,
true);
1602 static constexpr int kNumSigners = 4;
1607 for (
int i = 0; i < kNumSigners; ++i)
1628 auto const amt =
XRP(1000);
1654 for (
auto withClaim : {
false,
true})
1657 XEnv scEnv(*
this,
true);
1661 static constexpr int kNumSigners = 4;
1666 for (
int i = 0; i < kNumSigners; ++i)
1687 auto const amt =
XRP(1000);
1696 scAttester,
jvb,
mcAlice, amt,
payees,
true, claimID, dst,
signers, 2, 1))
1720 XEnv scEnv(*
this,
true);
1721 auto const amt =
XRP(1000);
1722 auto const amtPlusReward = amt +
reward;
1737 BEAST_EXPECT(carol.
diff() == -(amt +
reward + fee));
1757 BEAST_EXPECT(attester.
diff() == -multiTtxFee(6));
1775 BEAST_EXPECT(attester.
diff() == -multiTtxFee(3));
1791 BEAST_EXPECT(attester.
diff() == -multiTtxFee(3));
1805 BEAST_EXPECT(door.
diff() == -amtPlusReward);
1807 BEAST_EXPECT(attester.
diff() == -multiTtxFee(3));
1826 BEAST_EXPECT(attester.
diff() == -multiTtxFee(3));
1841 BEAST_EXPECT(door.
diff() == -amtPlusReward);
1842 BEAST_EXPECT(attester.
diff() == -fee);
1857 BEAST_EXPECT(door.
diff() == -amtPlusReward);
1858 BEAST_EXPECT(attester.
diff() == -fee);
1870 XEnv scEnv(*
this,
true);
1872 auto const amt = res0 -
XRP(1);
1873 auto const amtPlusReward = amt +
reward;
1883 BEAST_EXPECT(door.
diff() == amtPlusReward);
1884 BEAST_EXPECT(carol.
diff() == -(amtPlusReward + fee));
1902 BEAST_EXPECT(attester.
diff() == -multiTtxFee(4));
1911 XEnv scEnv(*
this,
true);
1913 auto const amt =
XRP(111);
1914 auto const amtPlusReward = amt +
reward;
1924 BEAST_EXPECT(door.
diff() == amtPlusReward);
1925 BEAST_EXPECT(carol.
diff() == -(amtPlusReward + fee));
1944 BEAST_EXPECT(door.
diff() == -amtPlusReward);
1945 BEAST_EXPECT(attester.
diff() == -multiTtxFee(4));
1946 BEAST_EXPECT(alice.
diff() == amt);
1953 XEnv scEnv(*
this,
true);
1955 auto const amt =
XRP(1000);
1956 auto const amtPlusReward = amt +
reward;
1966 BEAST_EXPECT(door.
diff() == amtPlusReward);
1967 BEAST_EXPECT(carol.
diff() == -(amtPlusReward + fee));
1972 .
tx(
fset(
"scAlice", asfDepositAuth))
1988 BEAST_EXPECT(attester.
diff() == -multiTtxFee(4));
1999 XEnv scEnv(*
this,
true);
2000 auto const amt =
XRP(1000);
2001 auto const amtPlusReward = amt +
reward;
2018 BEAST_EXPECT(carol.
diff() == -(amt +
reward + fee));
2029 auto const badAmt =
XRP(10);
2040 BEAST_EXPECTS(!!scEnv.
caClaimID(
jvb, 1),
"claim id 1 created");
2041 BEAST_EXPECTS(!!scEnv.
caClaimID(
jvb, 2),
"claim id 2 created");
2042 BEAST_EXPECTS(!!scEnv.
caClaimID(
jvb, 3),
"claim id 3 created");
2054 BEAST_EXPECTS(!!scEnv.
caClaimID(
jvb, 1),
"claim id 1 still there");
2055 BEAST_EXPECTS(!!scEnv.
caClaimID(
jvb, 2),
"claim id 2 still there");
2056 BEAST_EXPECTS(!!scEnv.
caClaimID(
jvb, 3),
"claim id 3 still there");
2057 BEAST_EXPECTS(scEnv.
claimCount(
jvb) == 0,
"No account created yet");
2062 BEAST_EXPECTS(!!scEnv.
caClaimID(
jvb, 3),
"claim id 3 still there");
2063 BEAST_EXPECTS(scEnv.
claimCount(
jvb) == 0,
"No account created yet");
2068 BEAST_EXPECTS(!scEnv.
caClaimID(
jvb, 1),
"claim id 1 deleted");
2069 BEAST_EXPECTS(scEnv.
claimCount(
jvb) == 1,
"scuAlice created");
2078 BEAST_EXPECTS(!scEnv.
caClaimID(
jvb, 2),
"claim id 2 deleted");
2079 BEAST_EXPECTS(!scEnv.
caClaimID(
jvb, 1),
"claim id 1 not added");
2080 BEAST_EXPECTS(scEnv.
claimCount(
jvb) == 2,
"scuAlice & scuBob created");
2085 BEAST_EXPECTS(!scEnv.
caClaimID(
jvb, 3),
"claim id 3 deleted");
2086 BEAST_EXPECTS(scEnv.
claimCount(
jvb) == 3,
"All 3 accounts created");
2093 BEAST_EXPECT(attester.
diff() == -multiTtxFee(txCount));
2106 XEnv scEnv(*
this,
true);
2120 XEnv scEnv(*
this,
true);
2135 using namespace jtx;
2137 testcase(
"Add Non Batch Claim Attestation");
2141 XEnv scEnv(*
this,
true);
2155 auto const amt =
XRP(1000);
2158 auto const dstStartBalance = scEnv.
env.
balance(dst);
2160 for (
int i = 0; i <
signers.size(); ++i)
2170 BEAST_EXPECT(dstStartBalance == scEnv.
env.
balance(dst));
2174 BEAST_EXPECT(dstStartBalance + amt == scEnv.
env.
balance(dst));
2177 BEAST_EXPECT(dstStartBalance + amt == scEnv.
env.
balance(dst));
2198 XEnv scEnv(*
this,
true);
2199 auto const amt =
XRP(1000);
2215 auto const dstStartBalance = scEnv.
env.
balance(dst);
2230 att[sfAttestationSignerAccount.getJsonName()] =
altSigners[1].account.human();
2248 att[sfAttestationSignerAccount.getJsonName()] = unfundedSigner2.account.human();
2250 att[sfAttestationSignerAccount.getJsonName()] = unfundedSigner1.
account.human();
2266 tempSignerList.
front());
2267 att[sfAttestationSignerAccount.getJsonName()] =
altSigners[2].account.human();
2288 att.removeMember(sfAttestationSignerAccount.getJsonName());
2290 BEAST_EXPECT(dstStartBalance == scEnv.
env.
balance(dst));
2291 att[sfAttestationSignerAccount.getJsonName()] =
altSigners[3].account.human();
2293 BEAST_EXPECT(dstStartBalance + amt == scEnv.
env.
balance(dst));
2301 using namespace jtx;
2303 testcase(
"Add Non Batch Account Create Attestation");
2306 XEnv scEnv(*
this,
true);
2314 mcEnv.
fund(funds, a);
2315 mcEnv.
fund(funds, doorA);
2325 .minAccountCreate =
XRP(20),
2332 auto const amt =
XRP(777);
2333 auto const amtPlusReward = amt + xrpB.
reward;
2340 BEAST_EXPECT(balDoorA.
diff() == amtPlusReward);
2341 BEAST_EXPECT(balA.
diff() == -(amtPlusReward +
txFee));
2344 for (
int i = 0; i <
signers.size(); ++i)
2357 TER const expectedTER =
2363 BEAST_EXPECT(!scEnv.
env.
le(ua));
2367 BEAST_EXPECT(scEnv.
env.
le(ua));
2370 BEAST_EXPECT(scEnv.
env.
le(ua));
2376 using namespace jtx;
2387 for (
auto withClaim : {
false,
true})
2390 XEnv scEnv(*
this,
true);
2401 auto const amt =
XRP(1000);
2432 for (
auto withClaim : {
false,
true})
2435 XEnv scEnv(*
this,
true);
2447 auto const amt =
XRP(1000);
2468 for (
auto withClaim : {
false,
true})
2471 XEnv scEnv(*
this,
true);
2484 auto const amt =
XRP(1000);
2503 for (
auto withClaim : {
false,
true})
2506 XEnv scEnv(*
this,
true);
2519 auto const amt =
XRP(1000);
2553 for (
auto withClaim : {
false,
true})
2556 XEnv scEnv(*
this,
true);
2567 auto const amt =
XRP(1000);
2593 for (
auto withClaim : {
false,
true})
2596 XEnv scEnv(*
this,
true);
2607 auto const amt =
XRP(1000);
2642 for (
auto withClaim : {
false,
true})
2645 XEnv scEnv(*
this,
true);
2656 auto const amt =
XRP(1000);
2681 for (
auto withClaim : {
false,
true})
2684 XEnv scEnv(*
this,
true);
2695 auto const amt =
XRP(1000);
2701 auto tooFew =
quorum - 1;
2722 for (
auto withClaim : {
false,
true})
2725 XEnv scEnv(*
this,
true);
2736 auto const amt =
XRP(1000);
2764 for (
auto withClaim : {
true})
2767 XEnv scEnv(*
this,
true);
2778 auto const amt =
XRP(1000);
2810 for (
auto withClaim : {
true})
2813 XEnv scEnv(*
this,
true);
2824 auto const amt =
XRP(1000);
2855 for (
auto withClaim : {
false,
true})
2858 XEnv scEnv(*
this,
true);
2871 auto const amt =
XRP(1000);
2904 scEnv.
tx(txns.back());
2919 for (
auto withClaim : {
false,
true})
2922 XEnv scEnv(*
this,
true);
2937 auto const amt =
XRP(1000);
2963 for (
auto withClaim : {
false,
true})
2966 XEnv scEnv(*
this,
true);
2972 .
tx(
fset(
"scBob", asfDepositAuth))
2978 auto const amt =
XRP(1000);
2998 scEnv.
tx(txns.back()).
close();
3011 BEAST_EXPECT(scCarolBal.
diff() == amt);
3015 scEnv.
tx(txns.back()).
close();
3022 .
tx(
fset(
"scBob", 0, asfDepositAuth))
3026 scEnv.
tx(txns.back()).
close();
3027 BEAST_EXPECT(scBobBal.
diff() == amt);
3033 for (
auto withClaim : {
false,
true})
3036 XEnv scEnv(*
this,
true);
3042 .
tx(
fset(
"scBob", asfRequireDest))
3048 auto const amt =
XRP(1000);
3068 scEnv.
tx(txns.back()).
close();
3080 BEAST_EXPECT(scCarolBal.
diff() == amt);
3084 scEnv.
tx(txns.back()).
close();
3091 .
tx(
fset(
"scBob", 0, asfRequireDest))
3096 scEnv.
tx(txns.back()).
close();
3097 BEAST_EXPECT(scBobBal.
diff() == amt);
3107 XEnv scEnv(*
this,
true);
3113 .
tx(
fset(
"scBob", asfDepositAuth))
3119 auto const amt =
XRP(1000);
3136 BEAST_EXPECT(scCarolBal.
diff() == amt);
3141 for (
auto withClaim : {
true})
3144 XEnv scEnv(*
this,
true);
3155 auto const amt =
XRP(1000);
3186 for (
auto withClaim : {
false,
true})
3189 XEnv scEnv(*
this,
true);
3200 auto const amt =
XRP(1000);
3228 BEAST_EXPECT(scAliceBal.
diff() == -claimCost);
3234 for (
auto withClaim : {
false,
true})
3237 XEnv scEnv(*
this,
true);
3248 auto const amt =
XRP(1000);
3283 for (
auto withClaim : {
false,
true})
3286 XEnv scEnv(*
this,
true);
3300 auto const amt =
XRP(1000);
3329 for (
auto withClaim : {
false,
true})
3332 XEnv scEnv(*
this,
true);
3338 .
tx(
fset(unpaid, asfDepositAuth))
3344 auto const amt =
XRP(1000);
3410 using namespace jtx;
3417 XEnv scEnv(*
this,
true);
3419 auto const amt =
XRP(111);
3420 auto const amtPlusReward = amt +
reward;
3459 BEAST_EXPECT(carol.
diff() == -fee);
3541 BEAST_EXPECT(door.
diff() == -fee);
3564 using namespace jtx;
3585 auto const minAccountCreate =
XRP(20);
3609 using namespace jtx;
3611 testcase(
"Bridge Delete Door Account");
3623 for (
size_t i = 0; i < 256; ++i)
3632 XEnv scEnv(*
this,
true);
3641 for (
size_t i = 0; i < 256; ++i)
3652 using namespace jtx;
3657 XEnv scEnv(*
this,
true);
3660 auto const amt =
XRP(1000);
3677 auto k = jvAtt[
"PublicKey"].asString();
3679 jvAtt[
"PublicKey"] = k;
3686 XEnv scEnv(*
this,
true);
3689 auto const amt =
XRP(1000);
3690 auto const rewardAmt =
XRP(1);
3707 auto k = jvAtt[
"PublicKey"].asString();
3709 jvAtt[
"PublicKey"] = k;
3808 for (
auto const& c : claims)
3819 size_t numSuccessful = 0;
3820 for (
auto const& c : claims)
3831 return numSuccessful;
3837 bool callbackCalled =
false;
3844 callbackCalled =
false;
3853 auto& createClaims = claims.createClaims[c.claimCount];
3854 auto numAttns = createClaims.size();
3859 assert(claims.createClaims[c.claimCount].empty());
3864 if (c.numCreateAttnSent >=
bridge->quorum)
3866 callbackCalled =
true;
3867 c.createCallbacks[c.claimCount](c.signers);
3869 c.numCreateAttnSent = 0;
3873 }
while (callbackCalled);
3895 it->second.expectedDiff +=
3926 for (
auto const& [acct, state] :
accounts)
3928 if (!state.verify(
env, acct))
3973 return a.verify() &&
b.verify();
3979 a.sendAttestations();
3980 b.sendAttestations();
4018 return static_cast<T&
>(*this).a2b() ?
st_->a :
st_->b;
4024 return static_cast<T&
>(*this).a2b() ?
st_->b :
st_->a;
4094 if (!(
cr_.attested[signerIdx]))
4097 cr_.attested[signerIdx] =
true;
4101 bridge_.signers[signerIdx].account,
4106 bridge_.signers[signerIdx].account,
4119 if (counters.createCallbacks.size() <
cr_.claimId)
4120 counters.createCallbacks.resize(
cr_.claimId);
4123 auto numAttestors =
signers.size();
4125 assert(numAttestors <=
std::count(
cr_.attested.begin(),
cr_.attested.end(),
true));
4126 assert(numAttestors >=
bridge_.quorum);
4127 assert(
cr_.claimId - 1 == counters.claimCount);
4129 auto r =
cr_.reward;
4141 counters.createCallbacks[
cr_.claimId - 1] = std::move(completeCb);
4235 if (
xfer_.attested[i])
4250 if (!(
xfer_.attested[signerIdx]))
4253 xfer_.attested[signerIdx] =
true;
4256 bridge_.signers[signerIdx].account,
4260 bridge_.signers[signerIdx].account,
4368 using namespace jtx;
4374 while (!
sm_.empty())
4377 for (
auto it =
sm_.begin(); it !=
sm_.end();)
4379 auto vis = [&](
auto& sm) {
4381 return sm.advance(
time, rnd);
4383 auto& [t, sm] = *it;
4395 st->sendAttestations();
4403 BEAST_EXPECT(st->verify());
4411 using namespace jtx;
4413 testcase(
"Bridge usage simulation");
4416 XEnv scEnv(*
this,
true);
4422 Account doorXRPLocking(
"doorXRPLocking"), doorUSDLocking(
"doorUSDLocking"),
4423 doorUSDIssuing(
"doorUSDIssuing");
4425 static constexpr size_t kNumAcct = 10;
4426 auto a = [&doorXRPLocking, &doorUSDLocking, &doorUSDIssuing]() {
4430 for (
int i = 0; i < kNumAcct; ++i)
4436 doorXRPLocking = result.
back();
4438 doorUSDLocking = result.
back();
4440 doorUSDIssuing = result.
back();
4444 for (
auto& acct : a)
4448 mcEnv.
fund(amt, acct);
4449 scEnv.
fund(amt, acct);
4451 Account const usdLockingAcc{
"USDLocking"};
4452 IOU const usdLocking{usdLockingAcc[
"USD"]};
4453 IOU const usdIssuing{doorUSDIssuing[
"USD"]};
4455 mcEnv.
fund(
XRP(100000), usdLockingAcc);
4457 mcEnv.
tx(
trust(doorUSDLocking, usdLocking(100000)));
4459 mcEnv.
tx(
pay(usdLockingAcc, doorUSDLocking, usdLocking(50000)));
4461 for (
int i = 0; i < a.size(); ++i)
4466 mcEnv.
tx(
trust(acct, usdLocking(100000)));
4467 scEnv.
tx(
trust(acct, usdIssuing(100000)));
4472 st->init(s.account);
4477 static constexpr size_t kNumUa = 20;
4482 for (
int i = 0; i < kNumUa; ++i)
4491 auto initBridge = [&mcEnv, &scEnv, &st](
BridgeDef& bd) {
4492 bd.initBridge(mcEnv, scEnv);
4493 st->a.spendFee(bd.doorA, 2);
4494 st->b.spendFee(bd.doorB, 2);
4500 .doorA = doorXRPLocking,
4505 .minAccountCreate =
XRP(20),
4515 .doorA = doorUSDLocking,
4516 .issueA = usdLocking,
4517 .doorB = doorUSDIssuing,
4518 .issueB = usdIssuing,
4520 .minAccountCreate =
XRP(20),
4535 {.from = a[0], .to = ua[0], .amt =
XRP(777), .reward = xrpB.
reward, .a2b =
true});
4540 {.from = a[0], .to = ua[0], .finaldest = a[2], .amt =
XRP(3), .a2b =
true});
4548 {.from = a[0], .to = ua[0], .amt =
XRP(777), .reward = xrpB.
reward, .a2b =
false});
4553 {.from = a[0], .to = ua[0], .finaldest = a[2], .amt =
XRP(3), .a2b =
false});
4579 1, st, xrpB, {.from = a[1], .to = a[1], .finaldest = a[1], .amt =
XRP(1), .a2b =
true});
4584 {.from = a[0], .to = a[0], .finaldest = a[1], .amt =
XRP(3), .a2b =
false});
4589 {.from = a[1], .to = a[1], .finaldest = a[1], .amt =
XRP(5), .a2b =
false});
4601 2, st, xrpB, {.from = a[1], .to = a[1], .finaldest = a[1], .amt =
XRP(9), .a2b =
true});
4610 {.from = a[0], .to = a[1], .finaldest = a[2], .amt = usdLocking(3), .a2b =
true});
4619 {.from = a[0], .to = a[0], .finaldest = a[1], .amt = usdLocking(6), .a2b =
true});
4624 {.from = a[0], .to = a[0], .finaldest = a[1], .amt = usdIssuing(8), .a2b =
false});
4629 {.from = a[1], .to = a[1], .finaldest = a[1], .amt = usdLocking(1), .a2b =
true});
4634 {.from = a[0], .to = a[0], .finaldest = a[1], .amt = usdIssuing(3), .a2b =
false});
4639 {.from = a[1], .to = a[1], .finaldest = a[1], .amt = usdIssuing(5), .a2b =
false});
4644 {.from = a[0], .to = a[0], .finaldest = a[1], .amt = usdIssuing(7), .a2b =
false});
4649 {.from = a[1], .to = a[1], .finaldest = a[1], .amt = usdLocking(9), .a2b =
true});
4655 0, st, xrpB, {.from = a[0], .to = a[0], .finaldest = a[0], .amt =
XRP(1), .a2b =
true});
4660 {.from = a[1], .to = a[3], .finaldest = a[3], .amt = usdIssuing(3), .a2b =
false});
4665 {.from = a[3], .to = a[2], .finaldest = a[1], .amt = usdIssuing(5), .a2b =
false});
4671 {.from = a[0], .to = a[0], .finaldest = a[0], .amt =
XRP(4), .a2b =
false});
4673 1, st, xrpB, {.from = a[1], .to = a[1], .finaldest = a[0], .amt =
XRP(8), .a2b =
true});
4678 {.from = a[4], .to = a[1], .finaldest = a[1], .amt = usdLocking(7), .a2b =
true});
4681 3, st, xrpB, {.from = a[1], .to = a[1], .finaldest = a[0], .amt =
XRP(7), .a2b =
true});
4686 {.from = a[0], .to = a[4], .finaldest = a[3], .amt =
XRP(2), .a2b =
false});
4688 3, st, xrpB, {.from = a[1], .to = a[1], .finaldest = a[0], .amt =
XRP(9), .a2b =
true});
4693 {.from = a[3], .to = a[1], .finaldest = a[1], .amt = usdIssuing(11), .a2b =
false});
4701 {.from = a[0], .to = ua[1], .amt =
XRP(301), .reward = xrpB.
reward, .a2b =
true});
4705 {.from = a[1], .to = ua[2], .amt =
XRP(302), .reward = xrpB.
reward, .a2b =
true});
4709 {.from = a[0], .to = ua[3], .amt =
XRP(303), .reward = xrpB.
reward, .a2b =
true});
4713 {.from = a[1], .to = ua[4], .amt =
XRP(304), .reward = xrpB.
reward, .a2b =
true});
4717 {.from = a[0], .to = ua[5], .amt =
XRP(305), .reward = xrpB.
reward, .a2b =
true});
4721 {.from = a[1], .to = ua[6], .amt =
XRP(306), .reward = xrpB.
reward, .a2b =
true});
4725 {.from = a[0], .to = ua[7], .amt =
XRP(307), .reward = xrpB.
reward, .a2b =
true});
4729 {.from = a[2], .to = ua[8], .amt =
XRP(308), .reward = xrpB.
reward, .a2b =
true});
4733 {.from = a[0], .to = ua[9], .amt =
XRP(309), .reward = xrpB.
reward, .a2b =
true});
4737 {.from = a[0], .to = ua[9], .amt =
XRP(309), .reward = xrpB.
reward, .a2b =
true});
4741 {.from = a[0], .to = ua[10], .amt =
XRP(310), .reward = xrpB.
reward, .a2b =
true});
4745 {.from = a[0], .to = ua[11], .amt =
XRP(311), .reward = xrpB.
reward, .a2b =
true});
4749 {.from = a[3], .to = ua[12], .amt =
XRP(312), .reward = xrpB.
reward, .a2b =
true});
4753 {.from = a[4], .to = ua[13], .amt =
XRP(313), .reward = xrpB.
reward, .a2b =
true});
4757 {.from = a[3], .to = ua[14], .amt =
XRP(314), .reward = xrpB.
reward, .a2b =
true});
4761 {.from = a[6], .to = ua[15], .amt =
XRP(315), .reward = xrpB.
reward, .a2b =
true});
4765 {.from = a[7], .to = ua[16], .amt =
XRP(316), .reward = xrpB.
reward, .a2b =
true});
4769 {.from = a[3], .to = ua[17], .amt =
XRP(317), .reward = xrpB.
reward, .a2b =
true});
void pass()
Record a successful test condition.
TestcaseT testcase
Memberspace for declaring test cases.
A currency issued by an account.
Asset const & asset() const
std::shared_ptr< STLedgerEntry const > const_pointer
static constexpr TERSubset fromInt(int from)
static Account const kMaster
The master account that holds all XRP in genesis.
std::shared_ptr< ChainStateTracker > st_
ChainStateTrack & srcState()
SmBase(std::shared_ptr< ChainStateTracker > const &chainstate, BridgeDef const &bridge)
jtx::Account const & dstDoor()
BridgeDef const & bridge_
ChainStateTrack & destState()
jtx::Account const & srcDoor()
SmCreateAccount(std::shared_ptr< ChainStateTracker > const &chainstate, BridgeDef const &bridge, AccountCreate create)
void attest(uint64_t time, uint32_t rnd)
uint32_t issueAccountCreate()
SmBase< SmCreateAccount > Base
SmState advance(uint64_t time, uint32_t rnd)
SmBase< SmTransfer > Base
SmState advance(uint64_t time, uint32_t rnd)
void distributeReward(ChainStateTrack &st)
bool attest(uint64_t time, uint32_t rnd)
SmTransfer(std::shared_ptr< ChainStateTracker > const &chainstate, BridgeDef const &bridge, Transfer xfer)
Immutable cryptographic account descriptor.
A transaction testing environment.
TER ter() const
Return the TER for the last JTx.
SLE::const_pointer le(Account const &account) const
Return an account root.
PrettyAmount balance(Account const &account) const
Returns the XRP balance on an account.
void memoize(Account const &account)
Associate AccountID with account.
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Converts to IOU Issue or STAmount.
Set the expected result code for a JTx The test will fail if the code doesn't match.
T emplace_back(T... args)
Severity
Severity level / threshold of a Journal message.
Keylet bridge(STXChainBridge const &bridge, STXChainBridge::ChainType chainType)
Keylet xChainCreateAccountClaimID(STXChainBridge const &bridge, std::uint64_t seq)
Keylet xChainClaimID(STXChainBridge const &bridge, std::uint64_t seq)
json::Value create(AccountID const &account, AccountID const &to, STAmount const &amount, NetClock::duration const &settleDelay, PublicKey const &pk, std::optional< NetClock::time_point > const &cancelAfter, std::optional< std::uint32_t > const &dstTag)
json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
json::Value regkey(Account const &account, DisabledT)
Disable the regular key.
std::vector< json::Value > JValueVec
json::Value sidechainXchainAccountCreate(Account const &acc, json::Value const &bridge, Account const &dst, AnyAmount const &amt, AnyAmount const &reward)
XrpT const XRP
Converts to XRP Issue or STAmount.
json::Value xchainCommit(Account const &acc, json::Value const &bridge, std::uint32_t claimID, AnyAmount const &amt, std::optional< Account > const &dst)
FeatureBitset testableAmendments()
json::Value bridgeCreate(Account const &acc, json::Value const &bridge, STAmount const &reward, std::optional< STAmount > const &minAccountCreate)
json::Value bridge(Account const &lockingChainDoor, Issue const &lockingChainIssue, Account const &issuingChainDoor, Issue const &issuingChainIssue)
constexpr std::size_t kUtXchainDefaultNumSigners
json::Value acctdelete(Account const &account, Account const &dest)
Delete account.
JValueVec claimAttestations(jtx::Account const &submittingAccount, json::Value const &jvBridge, jtx::Account const &sendingAccount, jtx::AnyAmount const &sendingAmount, std::vector< jtx::Account > const &rewardAccounts, bool wasLockingChainSend, std::uint64_t claimID, std::optional< jtx::Account > const &dst, std::vector< jtx::Signer > const &signers, std::size_t const numAtts, std::size_t const fromIdx)
json::Value claimAttestation(jtx::Account const &submittingAccount, json::Value const &jvBridge, jtx::Account const &sendingAccount, jtx::AnyAmount const &sendingAmount, jtx::Account const &rewardAccount, bool wasLockingChainSend, std::uint64_t claimID, std::optional< jtx::Account > const &dst, jtx::Signer const &signer)
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
json::Value createAccountAttestation(jtx::Account const &submittingAccount, json::Value const &jvBridge, jtx::Account const &sendingAccount, jtx::AnyAmount const &sendingAmount, jtx::AnyAmount const &rewardAmount, jtx::Account const &rewardAccount, bool wasLockingChainSend, std::uint64_t createCount, jtx::Account const &dst, jtx::Signer const &signer)
json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
json::Value xchainClaim(Account const &acc, json::Value const &bridge, std::uint32_t claimID, AnyAmount const &amt, Account const &dst)
constexpr std::size_t kUtXchainDefaultQuorum
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
json::Value bridgeModify(Account const &acc, json::Value const &bridge, std::optional< STAmount > const &reward, std::optional< STAmount > const &minAccountCreate)
json::Value xchainCreateClaimId(Account const &acc, json::Value const &bridge, STAmount const &reward, Account const &otherChainSource)
json::Value signers(Account const &account, std::uint32_t quorum, std::vector< Signer > const &v)
json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
BEAST_DEFINE_TESTSUITE(AMMClawback, app, xrpl)
constexpr XRPAmount
Convert XRP to drops (integral types).
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
STAmount divide(STAmount const &amount, Rate const &rate)
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
std::string transToken(TER code)
@ temXCHAIN_BRIDGE_BAD_MIN_ACCOUNT_CREATE_AMOUNT
@ temXCHAIN_BRIDGE_NONDOOR_OWNER
@ temXCHAIN_BRIDGE_BAD_ISSUES
@ temXCHAIN_BRIDGE_BAD_REWARD_AMOUNT
@ temXCHAIN_EQUAL_DOOR_ACCOUNTS
bool isTesSuccess(TER x) noexcept
TERSubset< CanCvtToTER > TER
@ tecXCHAIN_INSUFF_CREATE_AMOUNT
@ tecXCHAIN_NO_SIGNERS_LIST
@ tecXCHAIN_ACCOUNT_CREATE_PAST
@ tecXCHAIN_BAD_PUBLIC_KEY_ACCOUNT_PAIR
@ tecXCHAIN_CREATE_ACCOUNT_DISABLED
@ tecINSUFFICIENT_RESERVE
@ tecXCHAIN_CLAIM_NO_QUORUM
@ tecXCHAIN_REWARD_MISMATCH
STAmount multiply(STAmount const &amount, Number const &frac, Number::RoundingMode rm)
std::vector< balance > rewardAccounts
bool checkMostBalances(STAmount const &amt, STAmount const &reward)
bool hasHappened(STAmount const &amt, STAmount const &reward, bool checkPayer=true)
BalanceTransfer(T &env, jtx::Account const &fromAcct, jtx::Account const &toAcct, jtx::Account const &payer, std::vector< jtx::Account > const &payees, bool withClaim)
bool payeesReceived(STAmount const &reward) const
BalanceTransfer(T &env, jtx::Account const &fromAcct, jtx::Account const &toAcct, jtx::Account const &payer, jtx::Account const *payees, size_t numPayees, bool withClaim)
Balance(T &env, jtx::Account const &account)
jtx::Account const & account
void initBridge(ENV &mcEnv, ENV &scEnv)
STAmount minAccountCreate
std::vector< jtx::Signer > const & signers
SEnv & enableFeature(uint256 const feature)
STAmount balance(jtx::Account const &account, Issue const &issue) const
std::uint64_t claimID(json::Value const &jvb)
SLE::const_pointer account(jtx::Account const &account)
SEnv & tx(JsonValue &&jv, FN const &... fN)
XRPAmount reserve(std::uint32_t count)
std::uint64_t claimCount(json::Value const &jvb)
SEnv & fund(STAmount const &amount, Arg const &arg, Args const &... args)
SEnv & disableFeature(uint256 const feature)
SEnv(T &s, std::unique_ptr< Config > config, FeatureBitset features, std::unique_ptr< Logs > logs=nullptr, beast::Severity thresh=beast::Severity::Error)
SLE::const_pointer bridge(json::Value const &jvb)
SLE::const_pointer caClaimID(json::Value const &jvb, std::uint64_t seq)
STAmount balance(jtx::Account const &account) const
SEnv & multiTx(jtx::JValueVec const &jvv, FN const &... fN)
SLE::const_pointer claimID(json::Value const &jvb, std::uint64_t seq)
std::array< bool, kNumSigners > attested
bool verify(ENV &env, jtx::Account const &acct) const
void init(ENV &env, jtx::Account const &acct)
uint32_t numCreateAttnSent
std::vector< complete_cb > createCallbacks
std::vector< size_t > signers
std::function< void(std::vector< size_t > const &signers)> complete_cb
CreateClaimMap createClaims
std::map< BridgeID, BridgeCounters > counters
void spend(jtx::Account const &acct, STAmount amt, std::uint64_t times=1)
void sendAttestations(size_t signerIdx, BridgeID bridge, ClaimVec &claims)
void spendFee(jtx::Account const &acct, size_t times=1)
std::map< uint32_t, CreateClaimVec > CreateClaimMap
std::map< jtx::Account, AccountStateTrack > accounts
jtx::JValueVec CreateClaimVec
ChainStateTrack(ENV &env)
SignersAttns signersAttns
void transfer(jtx::Account const &from, jtx::Account const &to, STAmount amt)
void init(jtx::Account const &acct)
std::unordered_map< BridgeID, Claims > SignerAttns
uint32_t sendCreateAttestations(size_t signerIdx, BridgeID bridge, CreateClaimVec &claims)
std::array< SignerAttns, kNumSigners > SignersAttns
void receive(jtx::Account const &acct, STAmount amt, std::uint64_t divisor=1)
ChainStateTracker(ENV &aEnv, ENV &bEnv)
void init(jtx::Account const &acct)
std::array< bool, kNumSigners > attested
BridgeDef const * BridgeID
std::variant< SmCreateAccount, SmTransfer > Sm
void xfer(uint64_t time, std::shared_ptr< ChainStateTracker > const &chainstate, BridgeDef const &bridge, Transfer transfer)
XEnv< XChainSim_test > ENV
static constexpr size_t kNumSigners
void ac(uint64_t time, std::shared_ptr< ChainStateTracker > const &chainstate, BridgeDef const &bridge, AccountCreate ac)
void run() override
Runs the suite.
void runSimulation(std::shared_ptr< ChainStateTracker > const &st, bool verifyBalances=true)
void testXChainSimulation()
std::list< std::pair< uint64_t, Sm > > SmCont
void testXChainBridgeCreateConstraints()
void testXChainCreateBridgeMatrix()
void run() override
Runs the suite.
XRPAmount reserve(std::uint32_t count)
void testXChainCreateAccount()
void testFeeDipsIntoReserve()
void testXChainModifyBridge()
void testXChainCreateClaimID()
void testXChainDeleteDoor()
void testXChainCreateBridge()
void testXChainBridgeExtraFields()
void testXChainAddClaimNonBatchAttestation()
void testXChainAddAttestation()
void testXChainAddAccountCreateNonBatchAttestation()
XEnv(T &s, bool side=false)
A signer in a SignerList.
std::vector< Signer > const altSigners
STAmount const tinyRewardSplit
std::uint32_t const quorum
STAmount const splitRewardQuorum
FeatureBitset const features
std::vector< Account > const payees
json::Value createBridge(Account const &acc, json::Value const &bridge=json::ValueType::Null, STAmount const &reward=XRP(1), std::optional< STAmount > const &minAccountCreate=std::nullopt) const
std::vector< Signer > const signers
STAmount const tinyRewardRemainder
JValueVec attCreateAcctVec(std::uint64_t createCount, jtx::AnyAmount const &amt, jtx::Account const &dst, std::size_t const numAtts, std::size_t const fromIdx=0)
STAmount const splitRewardEveryone
STAmount const tinyReward