20 #include <ripple/beast/unit_test/suite.hpp>
21 #include <ripple/protocol/Feature.h>
22 #include <ripple/protocol/Indexes.h>
23 #include <ripple/protocol/Issue.h>
24 #include <ripple/protocol/SField.h>
25 #include <ripple/protocol/STXChainBridge.h>
26 #include <ripple/protocol/Serializer.h>
27 #include <ripple/protocol/TER.h>
28 #include <ripple/protocol/XChainAttestations.h>
31 #include <test/jtx/Env.h>
32 #include <test/jtx/attester.h>
33 #include <test/jtx/multisign.h>
34 #include <test/jtx/xchain_bridge.h>
66 :
env_(s,
std::move(config), features,
std::move(logs), thresh)
91 template <
class Arg,
class... Args>
99 template <
class JsonValue,
class... FN>
101 tx(JsonValue&& jv, FN
const&... fN)
103 env_(std::forward<JsonValue>(jv), fN...);
107 template <
class... FN>
111 for (
auto const& jv : jvv)
137 return env_.
current()->fees().accountReserve(count);
220 this->
fund(xrp_funds, s.account);
235 this->
fund(xrp_funds, ra);
238 this->
fund(xrp_funds, s.account);
288 : from_(env, from_acct)
291 , reward_accounts([&]() {
294 for (
size_t i = 0; i < num_payees; ++i)
298 , txFees_(withClaim ? env.env_.current()->fees().base :
XRPAmount(0))
324 reward_accounts.begin(),
325 reward_accounts.end(),
326 [&](
const balance& b) { return b.diff() == reward; });
332 return from_.diff() == -amt && to_.diff() == amt &&
340 bool check_payer =
true)
344 return check_most_balances(amt,
reward) &&
345 (!check_payer || payor_.diff() == -(reward_cost + txFees_));
352 payor_.diff() <= txFees_;
372 jvb =
bridge(doorA, issueA, doorB, issueB);
377 return minAccountCreate;
395 return XEnv(*this).env_.current()->fees().accountReserve(count);
401 return XEnv(*this).env_.current()->fees().base;
408 bool exceptionPresent =
false;
411 exceptionPresent =
false;
416 exceptionPresent =
true;
419 BEAST_EXPECT(!exceptionPresent);
423 exceptionPresent =
false;
424 jBridge[
"Extra"] = 1;
429 exceptionPresent =
true;
432 BEAST_EXPECT(exceptionPresent);
441 testcase(
"Create Bridge");
607 testcase(
"Bridge create constraints");
608 XEnv env(*
this,
true);
612 auto AUSD = A[
"USD"];
613 auto BUSD = B[
"USD"];
614 auto CUSD = C[
"USD"];
615 auto GUSD =
scGw[
"USD"];
616 auto AEUR = A[
"EUR"];
617 auto BEUR = B[
"EUR"];
618 auto CEUR = C[
"EUR"];
619 auto GEUR =
scGw[
"EUR"];
629 env.
fund(
XRP(10000), a1, a2, a3, a4, a5, a6);
652 auto const goodBridge1 =
bridge(A, GUSD, B, BUSD);
653 auto const goodBridge2 =
bridge(A, BUSD, C, CUSD);
668 env.
tx(trust(C, BUSD(1000)))
669 .
tx(trust(A, BUSD(1000)))
671 .
tx(pay(B, C, BUSD(1000)))
673 auto const aBalanceStart = env.
balance(A, BUSD);
674 auto const cBalanceStart = env.
balance(C, BUSD);
676 BEAST_EXPECT(env.
balance(A, BUSD) - aBalanceStart == BUSD(0));
677 BEAST_EXPECT(env.
balance(C, BUSD) - cBalanceStart == BUSD(-50));
679 BEAST_EXPECT(env.
balance(A, BUSD) - aBalanceStart == BUSD(60));
680 BEAST_EXPECT(env.
balance(C, BUSD) - cBalanceStart == BUSD(-50 - 60));
693 testcase(
"Create Bridge Matrix");
736 "Locking chain is IOU(locking chain door)",
737 [&](
auto& env,
bool) {
742 "Locking chain is IOU(issuing chain door funded on locking "
744 [&](
auto& env,
bool shouldFund) {
751 "Locking chain is IOU(issuing chain door account unfunded "
753 [&](
auto& env,
bool) {
758 "Locking chain is IOU(bob funded on locking chain)",
759 [&](
auto& env,
bool) {
764 "Locking chain is IOU(bob unfunded on locking chain)",
765 [&](
auto& env,
bool) {
776 "Issuing chain is IOU(issuing chain door account)",
777 [&](
auto& env,
bool) {
782 "Issuing chain is IOU(locking chain door funded on issuing "
784 [&](
auto& env,
bool shouldFund) {
791 "Issuing chain is IOU(locking chain door unfunded on "
793 [&](
auto& env,
bool) {
798 "Issuing chain is IOU(bob funded on issuing chain)",
799 [&](
auto& env,
bool) {
804 "Issuing chain is IOU(bob unfunded on issuing chain)",
805 [&](
auto& env,
bool) {
810 "Issuing chain is XRP and issuing chain door account is "
811 "not the root account",
812 [&](
auto& env,
bool) {
817 "Issuing chain is XRP and issuing chain door account is "
819 [&](
auto& env,
bool) {
870 auto testcase = [&](
auto const& lc,
auto const& ic) {
872 XEnv scEnv(*
this,
true);
874 lc.second(mcEnv,
true);
875 lc.second(scEnv,
false);
877 ic.second(mcEnv,
false);
878 ic.second(scEnv,
true);
880 auto const& expected = expected_result[test_result.
size()];
897 auto apply_ics = [&](
auto const& lc,
auto const& ics) {
899 [&](
auto const&... ic) { (testcase(lc, ic), ...); }, ics);
902 std::apply([&](
auto const&... lc) { (apply_ics(lc, ics), ...); }, lcs);
904 #if GENERATE_MTX_OUTPUT
909 std::cout <<
"Markdown output for matrix test: " << fname <<
"\n";
915 if (std::get<2>(tup))
924 auto output_table = [&](
auto print_res) {
930 res +=
"| `issuing ->` | ";
932 [&](
auto const&... ic) {
933 ((res += ic.first, res +=
" | "), ...);
940 [&](
auto const&... ic) {
941 (((void)ic.first, res +=
":---: | "), ...);
946 auto output = [&](
auto const& lc,
auto const& ic) {
947 res += print_res(test_result[test_idx]);
952 auto output_ics = [&](
auto const& lc,
auto const& ics) {
957 [&](
auto const&... ic) { (output(lc, ic), ...); }, ics);
962 [&](
auto const&... lc) { (output_ics(lc, ics), ...); }, lcs);
970 std::cout <<
"ter output for matrix test: " << ter_fname <<
"\n";
973 for (
auto& t : test_result)
985 testcase(
"Modify Bridge");
1034 for (
auto withClaim : {
false,
true})
1037 XEnv scEnv(*
this,
true);
1048 auto const amt =
XRP(1000);
1089 for (
auto withClaim : {
false,
true})
1092 XEnv scEnv(*
this,
true);
1103 auto const amt =
XRP(1000);
1152 for (
auto withClaim : {
false,
true})
1155 XEnv scEnv(*
this,
true);
1166 auto const amt =
XRP(1000);
1291 using namespace jtx;
1295 testcase(
"Create ClaimID");
1308 XEnv xenv(*
this,
true);
1316 BEAST_EXPECT(scAlice_bal.
diff() == -tx_fee);
1381 using namespace jtx;
1396 auto const amt =
XRP(1000);
1404 BEAST_EXPECT(alice_bal.
diff() == -(claim_cost + tx_fee));
1517 using namespace jtx;
1519 testcase(
"Add Attestation");
1533 for (
auto withClaim : {
true})
1536 XEnv scEnv(*
this,
true);
1550 auto const amt =
XRP(1000);
1602 for (
auto withClaim : {
false,
true})
1605 XEnv scEnv(*
this,
true);
1609 constexpr
int numSigners = 4;
1614 for (
int i = 0; i < numSigners; ++i)
1616 using namespace std::literals;
1634 auto const amt =
XRP(1000);
1677 for (
auto withClaim : {
false,
true})
1680 XEnv scEnv(*
this,
true);
1684 constexpr
int numSigners = 4;
1689 for (
int i = 0; i < numSigners; ++i)
1691 using namespace std::literals;
1711 auto const amt =
XRP(1000);
1755 for (
auto withClaim : {
false,
true})
1758 XEnv scEnv(*
this,
true);
1762 constexpr
int numSigners = 4;
1767 for (
int i = 0; i < numSigners; ++i)
1769 using namespace std::literals;
1788 auto const amt =
XRP(1000);
1830 for (
auto withClaim : {
false,
true})
1833 XEnv scEnv(*
this,
true);
1837 constexpr
int numSigners = 4;
1842 for (
int i = 0; i < numSigners; ++i)
1844 using namespace std::literals;
1863 auto const amt =
XRP(1000);
1913 XEnv scEnv(*
this,
true);
1914 auto const amt =
XRP(1000);
1915 auto const amt_plus_reward = amt +
reward;
1935 BEAST_EXPECT(carol.
diff() == -(amt +
reward + tx_fee));
1955 BEAST_EXPECT(attester.
diff() == -multiTtxFee(6));
1975 BEAST_EXPECT(attester.
diff() == -multiTtxFee(3));
1993 BEAST_EXPECT(attester.
diff() == -multiTtxFee(3));
2009 BEAST_EXPECT(door.
diff() == -amt_plus_reward);
2011 BEAST_EXPECT(attester.
diff() == -multiTtxFee(3));
2031 BEAST_EXPECT(attester.
diff() == -multiTtxFee(3));
2047 BEAST_EXPECT(door.
diff() == -amt_plus_reward);
2048 BEAST_EXPECT(attester.
diff() == -tx_fee);
2063 BEAST_EXPECT(door.
diff() == -amt_plus_reward);
2064 BEAST_EXPECT(attester.
diff() == -tx_fee);
2076 XEnv scEnv(*
this,
true);
2078 auto const amt = res0 -
XRP(1);
2079 auto const amt_plus_reward = amt +
reward;
2092 BEAST_EXPECT(door.
diff() == amt_plus_reward);
2093 BEAST_EXPECT(carol.
diff() == -(amt_plus_reward + tx_fee));
2113 BEAST_EXPECT(attester.
diff() == -multiTtxFee(4));
2122 XEnv scEnv(*
this,
true);
2124 auto const amt =
XRP(111);
2125 auto const amt_plus_reward = amt +
reward;
2138 BEAST_EXPECT(door.
diff() == amt_plus_reward);
2139 BEAST_EXPECT(carol.
diff() == -(amt_plus_reward + tx_fee));
2160 BEAST_EXPECT(door.
diff() == -amt_plus_reward);
2161 BEAST_EXPECT(attester.
diff() == -multiTtxFee(4));
2162 BEAST_EXPECT(alice.
diff() == amt);
2169 XEnv scEnv(*
this,
true);
2171 auto const amt =
XRP(1000);
2172 auto const amt_plus_reward = amt +
reward;
2185 BEAST_EXPECT(door.
diff() == amt_plus_reward);
2186 BEAST_EXPECT(carol.
diff() == -(amt_plus_reward + tx_fee));
2209 BEAST_EXPECT(attester.
diff() == -multiTtxFee(4));
2220 XEnv scEnv(*
this,
true);
2221 auto const amt =
XRP(1000);
2222 auto const amt_plus_reward = amt +
reward;
2244 BEAST_EXPECT(carol.
diff() == -(amt +
reward + tx_fee));
2255 auto const bad_amt =
XRP(10);
2266 BEAST_EXPECTS(!!scEnv.
caClaimID(
jvb, 1),
"claim id 1 created");
2267 BEAST_EXPECTS(!!scEnv.
caClaimID(
jvb, 2),
"claim id 2 created");
2268 BEAST_EXPECTS(!!scEnv.
caClaimID(
jvb, 3),
"claim id 3 created");
2302 BEAST_EXPECTS(!scEnv.
caClaimID(
jvb, 1),
"claim id 1 deleted");
2303 BEAST_EXPECTS(scEnv.
claimCount(
jvb) == 1,
"scuAlice created");
2312 BEAST_EXPECTS(!scEnv.
caClaimID(
jvb, 2),
"claim id 2 deleted");
2313 BEAST_EXPECTS(!scEnv.
caClaimID(
jvb, 1),
"claim id 1 not added");
2321 BEAST_EXPECTS(!scEnv.
caClaimID(
jvb, 3),
"claim id 3 deleted");
2332 BEAST_EXPECT(attester.
diff() == -multiTtxFee(txCount));
2345 XEnv scEnv(*
this,
true);
2367 XEnv scEnv(*
this,
true);
2390 using namespace jtx;
2392 testcase(
"Add Non Batch Claim Attestation");
2396 XEnv scEnv(*
this,
true);
2410 auto const amt =
XRP(1000);
2413 auto const dstStartBalance = scEnv.
env_.
balance(dst);
2415 for (
int i = 0; i <
signers.size(); ++i)
2428 TER const expectedTER =
2436 BEAST_EXPECT(dstStartBalance == scEnv.
env_.
balance(dst));
2439 dstStartBalance + amt == scEnv.
env_.
balance(dst));
2441 BEAST_EXPECT(dstStartBalance + amt == scEnv.
env_.
balance(dst));
2462 XEnv scEnv(*
this,
true);
2463 auto const amt =
XRP(1000);
2479 auto const dstStartBalance = scEnv.
env_.
balance(dst);
2520 auto const unfundedSigner1 =
2522 auto const unfundedSigner2 =
2535 unfundedSigner2.account.human();
2539 unfundedSigner1.
account.human();
2556 tempSignerList.
front());
2607 BEAST_EXPECT(dstStartBalance == scEnv.
env_.
balance(dst));
2611 BEAST_EXPECT(dstStartBalance + amt == scEnv.
env_.
balance(dst));
2619 using namespace jtx;
2621 testcase(
"Add Non Batch Account Create Attestation");
2624 XEnv scEnv(*
this,
true);
2632 mcEnv.
fund(funds, a);
2633 mcEnv.
fund(funds, doorA);
2648 xrp_b.initBridge(mcEnv, scEnv);
2650 auto const amt =
XRP(777);
2651 auto const amt_plus_reward = amt + xrp_b.reward;
2653 Balance bal_doorA(mcEnv, doorA);
2658 a, xrp_b.jvb, ua, amt, xrp_b.reward))
2661 BEAST_EXPECT(bal_doorA.
diff() == amt_plus_reward);
2662 BEAST_EXPECT(bal_a.
diff() == -(amt_plus_reward + tx_fee));
2665 for (
int i = 0; i <
signers.size(); ++i)
2678 TER const expectedTER = i < xrp_b.quorum
2683 if (i + 1 < xrp_b.quorum)
2684 BEAST_EXPECT(!scEnv.
env_.
le(ua));
2686 BEAST_EXPECT(scEnv.
env_.
le(ua));
2688 BEAST_EXPECT(scEnv.
env_.
le(ua));
2694 using namespace jtx;
2705 for (
auto withClaim : {
false,
true})
2708 XEnv scEnv(*
this,
true);
2719 auto const amt =
XRP(1000);
2759 for (
auto withClaim : {
false,
true})
2762 XEnv scEnv(*
this,
true);
2774 auto const amt =
XRP(1000);
2809 for (
auto withClaim : {
false,
true})
2812 XEnv scEnv(*
this,
true);
2825 auto const amt =
XRP(1000);
2858 for (
auto withClaim : {
false,
true})
2861 XEnv scEnv(*
this,
true);
2877 auto const amt =
XRP(1000);
2916 for (
auto withClaim : {
false,
true})
2919 XEnv scEnv(*
this,
true);
2930 auto const amt =
XRP(1000);
2967 for (
auto withClaim : {
false,
true})
2970 XEnv scEnv(*
this,
true);
2981 auto const amt =
XRP(1000);
3026 for (
auto withClaim : {
false,
true})
3029 XEnv scEnv(*
this,
true);
3040 auto const amt =
XRP(1000);
3066 for (
auto withClaim : {
false,
true})
3069 XEnv scEnv(*
this,
true);
3080 auto const amt =
XRP(1000);
3087 auto tooFew =
quorum - 1;
3117 for (
auto withClaim : {
false,
true})
3120 XEnv scEnv(*
this,
true);
3131 auto const amt =
XRP(1000);
3171 for (
auto withClaim : {
true})
3174 XEnv scEnv(*
this,
true);
3185 auto const amt =
XRP(1000);
3227 for (
auto withClaim : {
true})
3230 XEnv scEnv(*
this,
true);
3241 auto const amt =
XRP(1000);
3283 for (
auto withClaim : {
false,
true})
3286 XEnv scEnv(*
this,
true);
3299 auto const amt =
XRP(1000);
3350 scEnv.
tx(txns.back());
3367 for (
auto withClaim : {
false,
true})
3370 XEnv scEnv(*
this,
true);
3385 auto const amt =
XRP(1000);
3421 for (
auto withClaim : {
false,
true})
3424 XEnv scEnv(*
this,
true);
3436 auto const amt =
XRP(1000);
3464 scEnv.
tx(txns.back()).
close();
3480 BEAST_EXPECT(scCarol_bal.
diff() == amt);
3484 scEnv.
tx(txns.back()).
close();
3497 scEnv.
tx(txns.back()).
close();
3498 BEAST_EXPECT(scBob_bal.
diff() == amt);
3504 for (
auto withClaim : {
false,
true})
3507 XEnv scEnv(*
this,
true);
3519 auto const amt =
XRP(1000);
3547 scEnv.
tx(txns.back()).
close();
3562 BEAST_EXPECT(scCarol_bal.
diff() == amt);
3566 scEnv.
tx(txns.back()).
close();
3580 scEnv.
tx(txns.back()).
close();
3581 BEAST_EXPECT(scBob_bal.
diff() == amt);
3591 XEnv scEnv(*
this,
true);
3603 auto const amt =
XRP(1000);
3628 BEAST_EXPECT(scCarol_bal.
diff() == amt);
3633 for (
auto withClaim : {
true})
3636 XEnv scEnv(*
this,
true);
3647 auto const amt =
XRP(1000);
3686 for (
auto withClaim : {
false,
true})
3689 XEnv scEnv(*
this,
true);
3700 auto const amt =
XRP(1000);
3733 claim_cost += tx_fee;
3738 scAlice_bal.
diff() == -claim_cost);
3744 for (
auto withClaim : {
false,
true})
3747 XEnv scEnv(*
this,
true);
3758 auto const amt =
XRP(1000);
3790 claim_cost += tx_fee;
3803 for (
auto withClaim : {
false,
true})
3806 XEnv scEnv(*
this,
true);
3811 alt_payees.back() =
Account(
"inexistent");
3820 auto const amt =
XRP(1000);
3858 for (
auto withClaim : {
false,
true})
3861 XEnv scEnv(*
this,
true);
3873 auto const amt =
XRP(1000);
3878 Balance last_signer(scEnv, unpaid);
3950 using namespace jtx;
3952 testcase(
"Bridge Create Account");
3957 XEnv scEnv(*
this,
true);
3959 auto const amt =
XRP(111);
3960 auto const amt_plus_reward = amt +
reward;
4004 BEAST_EXPECT(carol.
diff() == -tx_fee);
4091 BEAST_EXPECT(door.
diff() == -tx_fee);
4115 using namespace jtx;
4119 testcase(
"Fee dips into reserve");
4138 auto const minAccountCreate =
XRP(20);
4165 using namespace jtx;
4167 testcase(
"Bridge Delete Door Account");
4169 auto const acctDelFee{
4170 drops(
XEnv(*this).env_.current()->fees().increment)};
4180 for (
size_t i = 0; i < 256; ++i)
4192 XEnv scEnv(*
this,
true);
4201 for (
size_t i = 0; i < 256; ++i)
4215 using namespace jtx;
4217 testcase(
"Bad attestations");
4220 XEnv scEnv(*
this,
true);
4223 auto const amt =
XRP(1000);
4241 auto k = jvAtt[
"PublicKey"].asString();
4243 jvAtt[
"PublicKey"] = k;
4250 XEnv scEnv(*
this,
true);
4253 auto const amt =
XRP(1000);
4254 auto const rewardAmt =
XRP(1);
4271 auto k = jvAtt[
"PublicKey"].asString();
4273 jvAtt[
"PublicKey"] = k;
4282 testXChainBridgeExtraFields();
4283 testXChainCreateBridge();
4284 testXChainBridgeCreateConstraints();
4285 testXChainCreateBridgeMatrix();
4286 testXChainModifyBridge();
4287 testXChainCreateClaimID();
4289 testXChainAddAttestation();
4290 testXChainAddClaimNonBatchAttestation();
4291 testXChainAddAccountCreateNonBatchAttestation();
4293 testXChainCreateAccount();
4294 testFeeDipsIntoReserve();
4295 testXChainDeleteDoor();
4306 static constexpr
size_t num_signers = 5;
4318 uint32_t claim_id{0};
4329 uint32_t claim_id{0};
4346 startAmount = env.
balance(acct);
4354 bool check = diff == expectedDiff;
4367 : env(env), tx_fee(env.
env_.
current()->fees().base)
4374 for (
auto const& c : claims)
4377 spendFee(
bridge->signers[signer_idx].account);
4388 size_t num_successful = 0;
4389 for (
auto const& c : claims)
4394 counters[
bridge].signers.push_back(signer_idx);
4397 spendFee(
bridge->signers[signer_idx].account);
4400 return num_successful;
4406 bool callback_called;
4413 callback_called =
false;
4414 for (
size_t i = 0; i < signers_attns.size(); ++i)
4416 for (
auto& [
bridge, claims] : signers_attns[i])
4418 sendAttestations(i,
bridge, claims.xfer_claims);
4420 auto& c = counters[
bridge];
4421 auto& create_claims =
4422 claims.create_claims[c.claim_count];
4423 auto num_attns = create_claims.size();
4426 c.num_create_attn_sent += sendCreateAttestations(
4427 i,
bridge, create_claims);
4429 assert(claims.create_claims[c.claim_count].empty());
4432 for (
auto& [
bridge, c] : counters)
4434 if (c.num_create_attn_sent >=
bridge->quorum)
4436 callback_called =
true;
4437 c.create_callbacks[c.claim_count](c.signers);
4439 c.num_create_attn_sent = 0;
4443 }
while (callback_called);
4449 accounts[acct].init(env, acct);
4460 auto it = accounts.find(acct);
4461 if (it == accounts.end())
4463 accounts[acct].init(env, acct);
4468 it->second.expectedDiff +=
4500 spend(acct, tx_fee, times);
4506 for (
auto const& [acct, state] : accounts)
4507 if (!state.verify(env, acct))
4517 uint32_t claim_id{0};
4518 uint32_t create_count{0};
4519 uint32_t claim_count{
4523 uint32_t num_create_attn_sent{0};
4553 return a_.verify() && b_.verify();
4559 a_.sendAttestations();
4560 b_.sendAttestations();
4593 : bridge_(
bridge), st_(chainstate)
4600 return static_cast<T&
>(*this).a2b() ? st_->a_ : st_->b_;
4606 return static_cast<T&
>(*this).a2b() ? st_->b_ : st_->a_;
4612 return static_cast<T&
>(*this).a2b() ? bridge_.doorA : bridge_.doorB;
4618 return static_cast<T&
>(*this).a2b() ? bridge_.doorB : bridge_.doorA;
4637 , sm_state(st_initial)
4656 cr.from, bridge_.jvb, cr.to, cr.amt, cr.reward))
4659 st.
transfer(cr.from, srcdoor, cr.amt);
4660 st.
transfer(cr.from, srcdoor, cr.reward);
4662 return ++st.
counters[&bridge_].create_count;
4672 for (i = 0; i < num_signers; ++i)
4674 size_t signer_idx = (rnd + i) % num_signers;
4676 if (!(cr.attested[signer_idx]))
4679 cr.attested[signer_idx] =
true;
4682 .create_claims[cr.claim_id - 1]
4684 bridge_.signers[signer_idx].account,
4689 bridge_.signers[signer_idx].account,
4693 bridge_.signers[signer_idx]));
4698 if (i == num_signers)
4701 auto& counters = st.
counters[&bridge_];
4702 if (counters.create_callbacks.size() < cr.claim_id)
4703 counters.create_callbacks.resize(cr.claim_id);
4706 auto num_attestors =
signers.size();
4710 std::count(cr.attested.begin(), cr.attested.end(),
true));
4711 assert(num_attestors >= bridge_.quorum);
4712 assert(cr.claim_id - 1 == counters.claim_count);
4721 st.
transfer(dstDoor(), cr.to, cr.amt);
4723 sm_state = st_completed;
4726 counters.create_callbacks[cr.claim_id - 1] = std::move(complete_cb);
4735 cr.claim_id = issue_account_create();
4736 sm_state = st_attesting;
4769 , xfer(
std::move(xfer))
4770 , sm_state(st_initial)
4787 xfer.to, bridge_.jvb, bridge_.reward, xfer.from))
4791 return ++st.
counters[&bridge_].claim_id;
4800 if (xfer.amt.issue() !=
xrpIssue())
4802 st.
env.
tx(pay(srcdoor, xfer.from, xfer.amt));
4810 xfer.with_claim == WithClaim::yes
4814 st.
transfer(xfer.from, srcdoor, xfer.amt);
4820 auto r = bridge_.reward;
4823 for (
size_t i = 0; i < num_signers; ++i)
4825 if (xfer.attested[i])
4837 for (
size_t i = 0; i < num_signers; ++i)
4839 size_t signer_idx = (rnd + i) % num_signers;
4840 if (!(xfer.attested[signer_idx]))
4843 xfer.attested[signer_idx] =
true;
4847 bridge_.signers[signer_idx].account,
4851 bridge_.signers[signer_idx].account,
4854 xfer.with_claim == WithClaim::yes
4857 bridge_.signers[signer_idx]));
4864 std::count(xfer.attested.begin(), xfer.attested.end(),
true) >=
4866 if (
quorum && xfer.with_claim == WithClaim::no)
4868 distribute_reward(st);
4869 st.
transfer(dstDoor(), xfer.finaldest, xfer.amt);
4879 xfer.to, bridge_.jvb, xfer.claim_id, xfer.amt, xfer.finaldest));
4880 distribute_reward(st);
4881 st.
transfer(dstDoor(), xfer.finaldest, xfer.amt);
4891 xfer.claim_id = create_claim_id();
4892 sm_state = st_claimid_created;
4895 case st_claimid_created:
4897 sm_state = st_attesting;
4901 sm_state = attest(time, rnd)
4902 ? (xfer.with_claim == WithClaim::yes ? st_attested
4908 assert(xfer.with_claim == WithClaim::yes);
4910 sm_state = st_completed;
4957 bool verify_balances =
true)
4959 using namespace jtx;
4964 while (!sm_.
empty())
4967 for (
auto it = sm_.
begin(); it != sm_.
end();)
4969 auto vis = [&](
auto& sm) {
4970 uint32_t rnd = distrib(gen);
4971 return sm.advance(time, rnd);
4973 auto& [t, sm] = *it;
4974 if (t <= time &&
std::visit(vis, sm) == st_completed)
4981 st->sendAttestations();
4987 if (verify_balances)
4989 BEAST_EXPECT(st->verify());
4997 using namespace jtx;
4999 testcase(
"Bridge usage simulation");
5002 XEnv scEnv(*
this,
true);
5004 auto st = std::make_shared<ChainStateTracker>(mcEnv, scEnv);
5008 Account doorXRPLocking, doorUSDLocking, doorUSDIssuing;
5010 constexpr
size_t num_acct = 10;
5011 auto a = [&doorXRPLocking, &doorUSDLocking, &doorUSDIssuing]() {
5012 using namespace std::literals;
5015 for (
int i = 0; i < num_acct; ++i)
5020 doorXRPLocking = result.
back();
5022 doorUSDLocking = result.
back();
5024 doorUSDIssuing = result.
back();
5028 for (
auto& acct : a)
5032 mcEnv.
fund(amt, acct);
5033 scEnv.
fund(amt, acct);
5035 Account USDLocking{
"USDLocking"};
5036 IOU usdLocking{USDLocking[
"USD"]};
5037 IOU usdIssuing{doorUSDIssuing[
"USD"]};
5039 mcEnv.
fund(
XRP(100000), USDLocking);
5041 mcEnv.
tx(trust(doorUSDLocking, usdLocking(100000)));
5043 mcEnv.
tx(pay(USDLocking, doorUSDLocking, usdLocking(50000)));
5045 for (
int i = 0; i < a.size(); ++i)
5050 mcEnv.
tx(trust(acct, usdLocking(100000)));
5051 scEnv.
tx(trust(acct, usdIssuing(100000)));
5056 st->init(s.account);
5061 constexpr
size_t num_ua = 20;
5063 using namespace std::literals;
5066 for (
int i = 0; i < num_ua; ++i)
5074 auto initBridge = [&mcEnv, &scEnv, &st](
BridgeDef& bd) {
5075 bd.initBridge(mcEnv, scEnv);
5076 st->a_.spendFee(bd.doorA, 2);
5077 st->b_.spendFee(bd.doorB, 2);
5115 ac(0, st, xrp_b, {a[0], ua[0],
XRP(777), xrp_b.reward,
true});
5116 xfer(8, st, xrp_b, {a[0], ua[0], a[2],
XRP(3),
true});
5121 ac(0, st, xrp_b, {a[0], ua[0],
XRP(777), xrp_b.reward,
false});
5122 xfer(8, st, xrp_b, {a[0], ua[0], a[2],
XRP(3),
false});
5127 xfer(0, st, xrp_b, {a[0], a[0], a[1],
XRP(6),
true, WithClaim::no});
5128 xfer(1, st, xrp_b, {a[0], a[0], a[1],
XRP(8),
false, WithClaim::no});
5129 xfer(1, st, xrp_b, {a[1], a[1], a[1],
XRP(1),
true});
5130 xfer(2, st, xrp_b, {a[0], a[0], a[1],
XRP(3),
false});
5131 xfer(2, st, xrp_b, {a[1], a[1], a[1],
XRP(5),
false});
5132 xfer(2, st, xrp_b, {a[0], a[0], a[1],
XRP(7),
false, WithClaim::no});
5133 xfer(2, st, xrp_b, {a[1], a[1], a[1],
XRP(9),
true});
5138 xfer(0, st, usd_b, {a[0], a[1], a[2], usdLocking(3),
true});
5143 xfer(0, st, usd_b, {a[0], a[0], a[1], usdLocking(6),
true});
5144 xfer(1, st, usd_b, {a[0], a[0], a[1], usdIssuing(8),
false});
5145 xfer(1, st, usd_b, {a[1], a[1], a[1], usdLocking(1),
true});
5146 xfer(2, st, usd_b, {a[0], a[0], a[1], usdIssuing(3),
false});
5147 xfer(2, st, usd_b, {a[1], a[1], a[1], usdIssuing(5),
false});
5148 xfer(2, st, usd_b, {a[0], a[0], a[1], usdIssuing(7),
false});
5149 xfer(2, st, usd_b, {a[1], a[1], a[1], usdLocking(9),
true});
5154 xfer(0, st, xrp_b, {a[0], a[0], a[0],
XRP(1),
true});
5155 xfer(0, st, usd_b, {a[1], a[3], a[3], usdIssuing(3),
false});
5156 xfer(0, st, usd_b, {a[3], a[2], a[1], usdIssuing(5),
false});
5158 xfer(1, st, xrp_b, {a[0], a[0], a[0],
XRP(4),
false});
5159 xfer(1, st, xrp_b, {a[1], a[1], a[0],
XRP(8),
true});
5160 xfer(1, st, usd_b, {a[4], a[1], a[1], usdLocking(7),
true});
5162 xfer(3, st, xrp_b, {a[1], a[1], a[0],
XRP(7),
true});
5163 xfer(3, st, xrp_b, {a[0], a[4], a[3],
XRP(2),
false});
5164 xfer(3, st, xrp_b, {a[1], a[1], a[0],
XRP(9),
true});
5165 xfer(3, st, usd_b, {a[3], a[1], a[1], usdIssuing(11),
false});
5170 ac(0, st, xrp_b, {a[0], ua[1],
XRP(301), xrp_b.reward,
true});
5171 ac(0, st, xrp_b, {a[1], ua[2],
XRP(302), xrp_b.reward,
true});
5172 ac(1, st, xrp_b, {a[0], ua[3],
XRP(303), xrp_b.reward,
true});
5173 ac(2, st, xrp_b, {a[1], ua[4],
XRP(304), xrp_b.reward,
true});
5174 ac(3, st, xrp_b, {a[0], ua[5],
XRP(305), xrp_b.reward,
true});
5175 ac(4, st, xrp_b, {a[1], ua[6],
XRP(306), xrp_b.reward,
true});
5176 ac(6, st, xrp_b, {a[0], ua[7],
XRP(307), xrp_b.reward,
true});
5177 ac(7, st, xrp_b, {a[2], ua[8],
XRP(308), xrp_b.reward,
true});
5178 ac(9, st, xrp_b, {a[0], ua[9],
XRP(309), xrp_b.reward,
true});
5179 ac(9, st, xrp_b, {a[0], ua[9],
XRP(309), xrp_b.reward,
true});
5180 ac(10, st, xrp_b, {a[0], ua[10],
XRP(310), xrp_b.reward,
true});
5181 ac(12, st, xrp_b, {a[0], ua[11],
XRP(311), xrp_b.reward,
true});
5182 ac(12, st, xrp_b, {a[3], ua[12],
XRP(312), xrp_b.reward,
true});
5183 ac(12, st, xrp_b, {a[4], ua[13],
XRP(313), xrp_b.reward,
true});
5184 ac(12, st, xrp_b, {a[3], ua[14],
XRP(314), xrp_b.reward,
true});
5185 ac(12, st, xrp_b, {a[6], ua[15],
XRP(315), xrp_b.reward,
true});
5186 ac(13, st, xrp_b, {a[7], ua[16],
XRP(316), xrp_b.reward,
true});
5187 ac(15, st, xrp_b, {a[3], ua[17],
XRP(317), xrp_b.reward,
true});
5188 runSimulation(st,
true);
5194 testXChainSimulation();