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");
606 testcase(
"Bridge create constraints");
607 XEnv env(*
this,
true);
611 auto AUSD = A[
"USD"];
612 auto BUSD = B[
"USD"];
613 auto CUSD = C[
"USD"];
614 auto GUSD =
scGw[
"USD"];
615 auto AEUR = A[
"EUR"];
616 auto BEUR = B[
"EUR"];
617 auto CEUR = C[
"EUR"];
618 auto GEUR =
scGw[
"EUR"];
626 env.
fund(
XRP(10000), a1, a2, a3, a4);
640 auto const goodBridge1 =
bridge(A, GUSD, B, BUSD);
641 auto const goodBridge2 =
bridge(A, BUSD, C, CUSD);
656 env.
tx(trust(C, BUSD(1000)))
657 .
tx(trust(A, BUSD(1000)))
659 .
tx(pay(B, C, BUSD(1000)))
661 auto const aBalanceStart = env.
balance(A, BUSD);
662 auto const cBalanceStart = env.
balance(C, BUSD);
664 BEAST_EXPECT(env.
balance(A, BUSD) - aBalanceStart == BUSD(0));
665 BEAST_EXPECT(env.
balance(C, BUSD) - cBalanceStart == BUSD(-50));
667 BEAST_EXPECT(env.
balance(A, BUSD) - aBalanceStart == BUSD(60));
668 BEAST_EXPECT(env.
balance(C, BUSD) - cBalanceStart == BUSD(-50 - 60));
681 testcase(
"Create Bridge Matrix");
724 "Locking chain is IOU(locking chain door)",
725 [&](
auto& env,
bool) {
730 "Locking chain is IOU(issuing chain door funded on locking "
732 [&](
auto& env,
bool shouldFund) {
739 "Locking chain is IOU(issuing chain door account unfunded "
741 [&](
auto& env,
bool) {
746 "Locking chain is IOU(bob funded on locking chain)",
747 [&](
auto& env,
bool) {
752 "Locking chain is IOU(bob unfunded on locking chain)",
753 [&](
auto& env,
bool) {
764 "Issuing chain is IOU(issuing chain door account)",
765 [&](
auto& env,
bool) {
770 "Issuing chain is IOU(locking chain door funded on issuing "
772 [&](
auto& env,
bool shouldFund) {
779 "Issuing chain is IOU(locking chain door unfunded on "
781 [&](
auto& env,
bool) {
786 "Issuing chain is IOU(bob funded on issuing chain)",
787 [&](
auto& env,
bool) {
792 "Issuing chain is IOU(bob unfunded on issuing chain)",
793 [&](
auto& env,
bool) {
798 "Issuing chain is XRP and issuing chain door account is "
799 "not the root account",
800 [&](
auto& env,
bool) {
805 "Issuing chain is XRP and issuing chain door account is "
807 [&](
auto& env,
bool) {
858 auto testcase = [&](
auto const& lc,
auto const& ic) {
860 XEnv scEnv(*
this,
true);
862 lc.second(mcEnv,
true);
863 lc.second(scEnv,
false);
865 ic.second(mcEnv,
false);
866 ic.second(scEnv,
true);
868 auto const& expected = expected_result[test_result.
size()];
885 auto apply_ics = [&](
auto const& lc,
auto const& ics) {
887 [&](
auto const&... ic) { (testcase(lc, ic), ...); }, ics);
890 std::apply([&](
auto const&... lc) { (apply_ics(lc, ics), ...); }, lcs);
892 #if GENERATE_MTX_OUTPUT
897 std::cout <<
"Markdown output for matrix test: " << fname <<
"\n";
903 if (std::get<2>(tup))
912 auto output_table = [&](
auto print_res) {
918 res +=
"| `issuing ->` | ";
920 [&](
auto const&... ic) {
921 ((res += ic.first, res +=
" | "), ...);
928 [&](
auto const&... ic) {
929 (((void)ic.first, res +=
":---: | "), ...);
934 auto output = [&](
auto const& lc,
auto const& ic) {
935 res += print_res(test_result[test_idx]);
940 auto output_ics = [&](
auto const& lc,
auto const& ics) {
945 [&](
auto const&... ic) { (output(lc, ic), ...); }, ics);
950 [&](
auto const&... lc) { (output_ics(lc, ics), ...); }, lcs);
958 std::cout <<
"ter output for matrix test: " << ter_fname <<
"\n";
961 for (
auto& t : test_result)
973 testcase(
"Modify Bridge");
1022 for (
auto withClaim : {
false,
true})
1025 XEnv scEnv(*
this,
true);
1036 auto const amt =
XRP(1000);
1077 for (
auto withClaim : {
false,
true})
1080 XEnv scEnv(*
this,
true);
1091 auto const amt =
XRP(1000);
1140 for (
auto withClaim : {
false,
true})
1143 XEnv scEnv(*
this,
true);
1154 auto const amt =
XRP(1000);
1279 using namespace jtx;
1283 testcase(
"Create ClaimID");
1296 XEnv xenv(*
this,
true);
1304 BEAST_EXPECT(scAlice_bal.
diff() == -tx_fee);
1369 using namespace jtx;
1384 auto const amt =
XRP(1000);
1392 BEAST_EXPECT(alice_bal.
diff() == -(claim_cost + tx_fee));
1505 using namespace jtx;
1507 testcase(
"Add Attestation");
1521 for (
auto withClaim : {
true})
1524 XEnv scEnv(*
this,
true);
1538 auto const amt =
XRP(1000);
1590 for (
auto withClaim : {
false,
true})
1593 XEnv scEnv(*
this,
true);
1597 constexpr
int numSigners = 4;
1602 for (
int i = 0; i < numSigners; ++i)
1604 using namespace std::literals;
1622 auto const amt =
XRP(1000);
1665 for (
auto withClaim : {
false,
true})
1668 XEnv scEnv(*
this,
true);
1672 constexpr
int numSigners = 4;
1677 for (
int i = 0; i < numSigners; ++i)
1679 using namespace std::literals;
1699 auto const amt =
XRP(1000);
1743 for (
auto withClaim : {
false,
true})
1746 XEnv scEnv(*
this,
true);
1750 constexpr
int numSigners = 4;
1755 for (
int i = 0; i < numSigners; ++i)
1757 using namespace std::literals;
1776 auto const amt =
XRP(1000);
1818 for (
auto withClaim : {
false,
true})
1821 XEnv scEnv(*
this,
true);
1825 constexpr
int numSigners = 4;
1830 for (
int i = 0; i < numSigners; ++i)
1832 using namespace std::literals;
1851 auto const amt =
XRP(1000);
1901 XEnv scEnv(*
this,
true);
1902 auto const amt =
XRP(1000);
1903 auto const amt_plus_reward = amt +
reward;
1923 BEAST_EXPECT(carol.
diff() == -(amt +
reward + tx_fee));
1943 BEAST_EXPECT(attester.
diff() == -multiTtxFee(6));
1963 BEAST_EXPECT(attester.
diff() == -multiTtxFee(3));
1981 BEAST_EXPECT(attester.
diff() == -multiTtxFee(3));
1997 BEAST_EXPECT(door.
diff() == -amt_plus_reward);
1999 BEAST_EXPECT(attester.
diff() == -multiTtxFee(3));
2019 BEAST_EXPECT(attester.
diff() == -multiTtxFee(3));
2035 BEAST_EXPECT(door.
diff() == -amt_plus_reward);
2036 BEAST_EXPECT(attester.
diff() == -tx_fee);
2051 BEAST_EXPECT(door.
diff() == -amt_plus_reward);
2052 BEAST_EXPECT(attester.
diff() == -tx_fee);
2064 XEnv scEnv(*
this,
true);
2066 auto const amt = res0 -
XRP(1);
2067 auto const amt_plus_reward = amt +
reward;
2080 BEAST_EXPECT(door.
diff() == amt_plus_reward);
2081 BEAST_EXPECT(carol.
diff() == -(amt_plus_reward + tx_fee));
2101 BEAST_EXPECT(attester.
diff() == -multiTtxFee(4));
2110 XEnv scEnv(*
this,
true);
2112 auto const amt =
XRP(111);
2113 auto const amt_plus_reward = amt +
reward;
2126 BEAST_EXPECT(door.
diff() == amt_plus_reward);
2127 BEAST_EXPECT(carol.
diff() == -(amt_plus_reward + tx_fee));
2148 BEAST_EXPECT(door.
diff() == -amt_plus_reward);
2149 BEAST_EXPECT(attester.
diff() == -multiTtxFee(4));
2150 BEAST_EXPECT(alice.
diff() == amt);
2157 XEnv scEnv(*
this,
true);
2159 auto const amt =
XRP(1000);
2160 auto const amt_plus_reward = amt +
reward;
2173 BEAST_EXPECT(door.
diff() == amt_plus_reward);
2174 BEAST_EXPECT(carol.
diff() == -(amt_plus_reward + tx_fee));
2197 BEAST_EXPECT(attester.
diff() == -multiTtxFee(4));
2208 XEnv scEnv(*
this,
true);
2209 auto const amt =
XRP(1000);
2210 auto const amt_plus_reward = amt +
reward;
2232 BEAST_EXPECT(carol.
diff() == -(amt +
reward + tx_fee));
2243 auto const bad_amt =
XRP(10);
2254 BEAST_EXPECTS(!!scEnv.
caClaimID(
jvb, 1),
"claim id 1 created");
2255 BEAST_EXPECTS(!!scEnv.
caClaimID(
jvb, 2),
"claim id 2 created");
2256 BEAST_EXPECTS(!!scEnv.
caClaimID(
jvb, 3),
"claim id 3 created");
2290 BEAST_EXPECTS(!scEnv.
caClaimID(
jvb, 1),
"claim id 1 deleted");
2291 BEAST_EXPECTS(scEnv.
claimCount(
jvb) == 1,
"scuAlice created");
2300 BEAST_EXPECTS(!scEnv.
caClaimID(
jvb, 2),
"claim id 2 deleted");
2301 BEAST_EXPECTS(!scEnv.
caClaimID(
jvb, 1),
"claim id 1 not added");
2309 BEAST_EXPECTS(!scEnv.
caClaimID(
jvb, 3),
"claim id 3 deleted");
2320 BEAST_EXPECT(attester.
diff() == -multiTtxFee(txCount));
2333 XEnv scEnv(*
this,
true);
2355 XEnv scEnv(*
this,
true);
2378 using namespace jtx;
2380 testcase(
"Add Non Batch Claim Attestation");
2384 XEnv scEnv(*
this,
true);
2398 auto const amt =
XRP(1000);
2401 auto const dstStartBalance = scEnv.
env_.
balance(dst);
2403 for (
int i = 0; i <
signers.size(); ++i)
2416 TER const expectedTER =
2424 BEAST_EXPECT(dstStartBalance == scEnv.
env_.
balance(dst));
2427 dstStartBalance + amt == scEnv.
env_.
balance(dst));
2429 BEAST_EXPECT(dstStartBalance + amt == scEnv.
env_.
balance(dst));
2450 XEnv scEnv(*
this,
true);
2451 auto const amt =
XRP(1000);
2467 auto const dstStartBalance = scEnv.
env_.
balance(dst);
2508 auto const unfundedSigner1 =
2510 auto const unfundedSigner2 =
2523 unfundedSigner2.account.human();
2527 unfundedSigner1.
account.human();
2544 tempSignerList.
front());
2595 BEAST_EXPECT(dstStartBalance == scEnv.
env_.
balance(dst));
2599 BEAST_EXPECT(dstStartBalance + amt == scEnv.
env_.
balance(dst));
2607 using namespace jtx;
2609 testcase(
"Add Non Batch Account Create Attestation");
2612 XEnv scEnv(*
this,
true);
2620 mcEnv.
fund(funds, a);
2621 mcEnv.
fund(funds, doorA);
2636 xrp_b.initBridge(mcEnv, scEnv);
2638 auto const amt =
XRP(777);
2639 auto const amt_plus_reward = amt + xrp_b.reward;
2641 Balance bal_doorA(mcEnv, doorA);
2646 a, xrp_b.jvb, ua, amt, xrp_b.reward))
2649 BEAST_EXPECT(bal_doorA.
diff() == amt_plus_reward);
2650 BEAST_EXPECT(bal_a.
diff() == -(amt_plus_reward + tx_fee));
2653 for (
int i = 0; i <
signers.size(); ++i)
2666 TER const expectedTER = i < xrp_b.quorum
2671 if (i + 1 < xrp_b.quorum)
2672 BEAST_EXPECT(!scEnv.
env_.
le(ua));
2674 BEAST_EXPECT(scEnv.
env_.
le(ua));
2676 BEAST_EXPECT(scEnv.
env_.
le(ua));
2682 using namespace jtx;
2693 for (
auto withClaim : {
false,
true})
2696 XEnv scEnv(*
this,
true);
2707 auto const amt =
XRP(1000);
2747 for (
auto withClaim : {
false,
true})
2750 XEnv scEnv(*
this,
true);
2762 auto const amt =
XRP(1000);
2797 for (
auto withClaim : {
false,
true})
2800 XEnv scEnv(*
this,
true);
2813 auto const amt =
XRP(1000);
2846 for (
auto withClaim : {
false,
true})
2849 XEnv scEnv(*
this,
true);
2865 auto const amt =
XRP(1000);
2904 for (
auto withClaim : {
false,
true})
2907 XEnv scEnv(*
this,
true);
2918 auto const amt =
XRP(1000);
2955 for (
auto withClaim : {
false,
true})
2958 XEnv scEnv(*
this,
true);
2969 auto const amt =
XRP(1000);
3014 for (
auto withClaim : {
false,
true})
3017 XEnv scEnv(*
this,
true);
3028 auto const amt =
XRP(1000);
3054 for (
auto withClaim : {
false,
true})
3057 XEnv scEnv(*
this,
true);
3068 auto const amt =
XRP(1000);
3075 auto tooFew =
quorum - 1;
3105 for (
auto withClaim : {
false,
true})
3108 XEnv scEnv(*
this,
true);
3119 auto const amt =
XRP(1000);
3159 for (
auto withClaim : {
true})
3162 XEnv scEnv(*
this,
true);
3173 auto const amt =
XRP(1000);
3215 for (
auto withClaim : {
true})
3218 XEnv scEnv(*
this,
true);
3229 auto const amt =
XRP(1000);
3271 for (
auto withClaim : {
false,
true})
3274 XEnv scEnv(*
this,
true);
3287 auto const amt =
XRP(1000);
3338 scEnv.
tx(txns.back());
3355 for (
auto withClaim : {
false,
true})
3358 XEnv scEnv(*
this,
true);
3373 auto const amt =
XRP(1000);
3409 for (
auto withClaim : {
false,
true})
3412 XEnv scEnv(*
this,
true);
3424 auto const amt =
XRP(1000);
3452 scEnv.
tx(txns.back()).
close();
3468 BEAST_EXPECT(scCarol_bal.
diff() == amt);
3472 scEnv.
tx(txns.back()).
close();
3485 scEnv.
tx(txns.back()).
close();
3486 BEAST_EXPECT(scBob_bal.
diff() == amt);
3492 for (
auto withClaim : {
false,
true})
3495 XEnv scEnv(*
this,
true);
3507 auto const amt =
XRP(1000);
3535 scEnv.
tx(txns.back()).
close();
3550 BEAST_EXPECT(scCarol_bal.
diff() == amt);
3554 scEnv.
tx(txns.back()).
close();
3568 scEnv.
tx(txns.back()).
close();
3569 BEAST_EXPECT(scBob_bal.
diff() == amt);
3579 XEnv scEnv(*
this,
true);
3591 auto const amt =
XRP(1000);
3616 BEAST_EXPECT(scCarol_bal.
diff() == amt);
3621 for (
auto withClaim : {
true})
3624 XEnv scEnv(*
this,
true);
3635 auto const amt =
XRP(1000);
3674 for (
auto withClaim : {
false,
true})
3677 XEnv scEnv(*
this,
true);
3688 auto const amt =
XRP(1000);
3721 claim_cost += tx_fee;
3726 scAlice_bal.
diff() == -claim_cost);
3732 for (
auto withClaim : {
false,
true})
3735 XEnv scEnv(*
this,
true);
3746 auto const amt =
XRP(1000);
3778 claim_cost += tx_fee;
3791 for (
auto withClaim : {
false,
true})
3794 XEnv scEnv(*
this,
true);
3799 alt_payees.back() =
Account(
"inexistent");
3808 auto const amt =
XRP(1000);
3846 for (
auto withClaim : {
false,
true})
3849 XEnv scEnv(*
this,
true);
3861 auto const amt =
XRP(1000);
3866 Balance last_signer(scEnv, unpaid);
3938 using namespace jtx;
3940 testcase(
"Bridge Create Account");
3945 XEnv scEnv(*
this,
true);
3947 auto const amt =
XRP(111);
3948 auto const amt_plus_reward = amt +
reward;
3992 BEAST_EXPECT(carol.
diff() == -tx_fee);
4079 BEAST_EXPECT(door.
diff() == -tx_fee);
4103 using namespace jtx;
4107 testcase(
"Fee dips into reserve");
4126 auto const minAccountCreate =
XRP(20);
4153 using namespace jtx;
4155 testcase(
"Bridge Delete Door Account");
4157 auto const acctDelFee{
4158 drops(
XEnv(*this).env_.current()->fees().increment)};
4168 for (
size_t i = 0; i < 256; ++i)
4180 XEnv scEnv(*
this,
true);
4189 for (
size_t i = 0; i < 256; ++i)
4203 testXChainBridgeExtraFields();
4204 testXChainCreateBridge();
4205 testXChainBridgeCreateConstraints();
4206 testXChainCreateBridgeMatrix();
4207 testXChainModifyBridge();
4208 testXChainCreateClaimID();
4210 testXChainAddAttestation();
4211 testXChainAddClaimNonBatchAttestation();
4212 testXChainAddAccountCreateNonBatchAttestation();
4214 testXChainCreateAccount();
4215 testFeeDipsIntoReserve();
4216 testXChainDeleteDoor();
4226 static constexpr
size_t num_signers = 5;
4238 uint32_t claim_id{0};
4249 uint32_t claim_id{0};
4266 startAmount = env.
balance(acct);
4274 bool check = diff == expectedDiff;
4287 : env(env), tx_fee(env.
env_.
current()->fees().base)
4294 for (
auto const& c : claims)
4297 spendFee(
bridge->signers[signer_idx].account);
4308 size_t num_successful = 0;
4309 for (
auto const& c : claims)
4314 counters[
bridge].signers.push_back(signer_idx);
4317 spendFee(
bridge->signers[signer_idx].account);
4320 return num_successful;
4326 bool callback_called;
4333 callback_called =
false;
4334 for (
size_t i = 0; i < signers_attns.size(); ++i)
4336 for (
auto& [
bridge, claims] : signers_attns[i])
4338 sendAttestations(i,
bridge, claims.xfer_claims);
4340 auto& c = counters[
bridge];
4341 auto& create_claims =
4342 claims.create_claims[c.claim_count];
4343 auto num_attns = create_claims.size();
4346 c.num_create_attn_sent += sendCreateAttestations(
4347 i,
bridge, create_claims);
4349 assert(claims.create_claims[c.claim_count].empty());
4352 for (
auto& [
bridge, c] : counters)
4354 if (c.num_create_attn_sent >=
bridge->quorum)
4356 callback_called =
true;
4357 c.create_callbacks[c.claim_count](c.signers);
4359 c.num_create_attn_sent = 0;
4363 }
while (callback_called);
4369 accounts[acct].init(env, acct);
4380 auto it = accounts.find(acct);
4381 if (it == accounts.end())
4383 accounts[acct].init(env, acct);
4388 it->second.expectedDiff +=
4420 spend(acct, tx_fee, times);
4426 for (
auto const& [acct, state] : accounts)
4427 if (!state.verify(env, acct))
4437 uint32_t claim_id{0};
4438 uint32_t create_count{0};
4439 uint32_t claim_count{
4443 uint32_t num_create_attn_sent{0};
4473 return a_.verify() && b_.verify();
4479 a_.sendAttestations();
4480 b_.sendAttestations();
4513 : bridge_(
bridge), st_(chainstate)
4520 return static_cast<T&
>(*this).a2b() ? st_->a_ : st_->b_;
4526 return static_cast<T&
>(*this).a2b() ? st_->b_ : st_->a_;
4532 return static_cast<T&
>(*this).a2b() ? bridge_.doorA : bridge_.doorB;
4538 return static_cast<T&
>(*this).a2b() ? bridge_.doorB : bridge_.doorA;
4557 , sm_state(st_initial)
4576 cr.from, bridge_.jvb, cr.to, cr.amt, cr.reward))
4579 st.
transfer(cr.from, srcdoor, cr.amt);
4580 st.
transfer(cr.from, srcdoor, cr.reward);
4582 return ++st.
counters[&bridge_].create_count;
4592 for (i = 0; i < num_signers; ++i)
4594 size_t signer_idx = (rnd + i) % num_signers;
4596 if (!(cr.attested[signer_idx]))
4599 cr.attested[signer_idx] =
true;
4602 .create_claims[cr.claim_id - 1]
4604 bridge_.signers[signer_idx].account,
4609 bridge_.signers[signer_idx].account,
4613 bridge_.signers[signer_idx]));
4618 if (i == num_signers)
4621 auto& counters = st.
counters[&bridge_];
4622 if (counters.create_callbacks.size() < cr.claim_id)
4623 counters.create_callbacks.resize(cr.claim_id);
4626 auto num_attestors =
signers.size();
4630 std::count(cr.attested.begin(), cr.attested.end(),
true));
4631 assert(num_attestors >= bridge_.quorum);
4632 assert(cr.claim_id - 1 == counters.claim_count);
4641 st.
transfer(dstDoor(), cr.to, cr.amt);
4643 sm_state = st_completed;
4646 counters.create_callbacks[cr.claim_id - 1] = std::move(complete_cb);
4655 cr.claim_id = issue_account_create();
4656 sm_state = st_attesting;
4689 , xfer(
std::move(xfer))
4690 , sm_state(st_initial)
4707 xfer.to, bridge_.jvb, bridge_.reward, xfer.from))
4711 return ++st.
counters[&bridge_].claim_id;
4720 if (xfer.amt.issue() !=
xrpIssue())
4722 st.
env.
tx(pay(srcdoor, xfer.from, xfer.amt));
4730 xfer.with_claim == WithClaim::yes
4734 st.
transfer(xfer.from, srcdoor, xfer.amt);
4740 auto r = bridge_.reward;
4743 for (
size_t i = 0; i < num_signers; ++i)
4745 if (xfer.attested[i])
4757 for (
size_t i = 0; i < num_signers; ++i)
4759 size_t signer_idx = (rnd + i) % num_signers;
4760 if (!(xfer.attested[signer_idx]))
4763 xfer.attested[signer_idx] =
true;
4767 bridge_.signers[signer_idx].account,
4771 bridge_.signers[signer_idx].account,
4774 xfer.with_claim == WithClaim::yes
4777 bridge_.signers[signer_idx]));
4784 std::count(xfer.attested.begin(), xfer.attested.end(),
true) >=
4786 if (
quorum && xfer.with_claim == WithClaim::no)
4788 distribute_reward(st);
4789 st.
transfer(dstDoor(), xfer.finaldest, xfer.amt);
4799 xfer.to, bridge_.jvb, xfer.claim_id, xfer.amt, xfer.finaldest));
4800 distribute_reward(st);
4801 st.
transfer(dstDoor(), xfer.finaldest, xfer.amt);
4811 xfer.claim_id = create_claim_id();
4812 sm_state = st_claimid_created;
4815 case st_claimid_created:
4817 sm_state = st_attesting;
4821 sm_state = attest(time, rnd)
4822 ? (xfer.with_claim == WithClaim::yes ? st_attested
4828 assert(xfer.with_claim == WithClaim::yes);
4830 sm_state = st_completed;
4877 bool verify_balances =
true)
4879 using namespace jtx;
4884 while (!sm_.
empty())
4887 for (
auto it = sm_.
begin(); it != sm_.
end();)
4889 auto vis = [&](
auto& sm) {
4890 uint32_t rnd = distrib(gen);
4891 return sm.advance(time, rnd);
4893 auto& [t, sm] = *it;
4894 if (t <= time &&
std::visit(vis, sm) == st_completed)
4901 st->sendAttestations();
4907 if (verify_balances)
4909 BEAST_EXPECT(st->verify());
4917 using namespace jtx;
4919 testcase(
"Bridge usage simulation");
4922 XEnv scEnv(*
this,
true);
4924 auto st = std::make_shared<ChainStateTracker>(mcEnv, scEnv);
4928 Account doorXRPLocking, doorUSDLocking, doorUSDIssuing;
4930 constexpr
size_t num_acct = 10;
4931 auto a = [&doorXRPLocking, &doorUSDLocking, &doorUSDIssuing]() {
4932 using namespace std::literals;
4935 for (
int i = 0; i < num_acct; ++i)
4940 doorXRPLocking = result.
back();
4942 doorUSDLocking = result.
back();
4944 doorUSDIssuing = result.
back();
4948 for (
auto& acct : a)
4952 mcEnv.
fund(amt, acct);
4953 scEnv.
fund(amt, acct);
4955 Account USDLocking{
"USDLocking"};
4956 IOU usdLocking{USDLocking[
"USD"]};
4957 IOU usdIssuing{doorUSDIssuing[
"USD"]};
4959 mcEnv.
fund(
XRP(100000), USDLocking);
4961 mcEnv.
tx(trust(doorUSDLocking, usdLocking(100000)));
4963 mcEnv.
tx(pay(USDLocking, doorUSDLocking, usdLocking(50000)));
4965 for (
int i = 0; i < a.size(); ++i)
4970 mcEnv.
tx(trust(acct, usdLocking(100000)));
4971 scEnv.
tx(trust(acct, usdIssuing(100000)));
4976 st->init(s.account);
4981 constexpr
size_t num_ua = 20;
4983 using namespace std::literals;
4986 for (
int i = 0; i < num_ua; ++i)
4994 auto initBridge = [&mcEnv, &scEnv, &st](
BridgeDef& bd) {
4995 bd.initBridge(mcEnv, scEnv);
4996 st->a_.spendFee(bd.doorA, 2);
4997 st->b_.spendFee(bd.doorB, 2);
5035 ac(0, st, xrp_b, {a[0], ua[0],
XRP(777), xrp_b.reward,
true});
5036 xfer(8, st, xrp_b, {a[0], ua[0], a[2],
XRP(3),
true});
5041 ac(0, st, xrp_b, {a[0], ua[0],
XRP(777), xrp_b.reward,
false});
5042 xfer(8, st, xrp_b, {a[0], ua[0], a[2],
XRP(3),
false});
5047 xfer(0, st, xrp_b, {a[0], a[0], a[1],
XRP(6),
true, WithClaim::no});
5048 xfer(1, st, xrp_b, {a[0], a[0], a[1],
XRP(8),
false, WithClaim::no});
5049 xfer(1, st, xrp_b, {a[1], a[1], a[1],
XRP(1),
true});
5050 xfer(2, st, xrp_b, {a[0], a[0], a[1],
XRP(3),
false});
5051 xfer(2, st, xrp_b, {a[1], a[1], a[1],
XRP(5),
false});
5052 xfer(2, st, xrp_b, {a[0], a[0], a[1],
XRP(7),
false, WithClaim::no});
5053 xfer(2, st, xrp_b, {a[1], a[1], a[1],
XRP(9),
true});
5058 xfer(0, st, usd_b, {a[0], a[1], a[2], usdLocking(3),
true});
5063 xfer(0, st, usd_b, {a[0], a[0], a[1], usdLocking(6),
true});
5064 xfer(1, st, usd_b, {a[0], a[0], a[1], usdIssuing(8),
false});
5065 xfer(1, st, usd_b, {a[1], a[1], a[1], usdLocking(1),
true});
5066 xfer(2, st, usd_b, {a[0], a[0], a[1], usdIssuing(3),
false});
5067 xfer(2, st, usd_b, {a[1], a[1], a[1], usdIssuing(5),
false});
5068 xfer(2, st, usd_b, {a[0], a[0], a[1], usdIssuing(7),
false});
5069 xfer(2, st, usd_b, {a[1], a[1], a[1], usdLocking(9),
true});
5074 xfer(0, st, xrp_b, {a[0], a[0], a[0],
XRP(1),
true});
5075 xfer(0, st, usd_b, {a[1], a[3], a[3], usdIssuing(3),
false});
5076 xfer(0, st, usd_b, {a[3], a[2], a[1], usdIssuing(5),
false});
5078 xfer(1, st, xrp_b, {a[0], a[0], a[0],
XRP(4),
false});
5079 xfer(1, st, xrp_b, {a[1], a[1], a[0],
XRP(8),
true});
5080 xfer(1, st, usd_b, {a[4], a[1], a[1], usdLocking(7),
true});
5082 xfer(3, st, xrp_b, {a[1], a[1], a[0],
XRP(7),
true});
5083 xfer(3, st, xrp_b, {a[0], a[4], a[3],
XRP(2),
false});
5084 xfer(3, st, xrp_b, {a[1], a[1], a[0],
XRP(9),
true});
5085 xfer(3, st, usd_b, {a[3], a[1], a[1], usdIssuing(11),
false});
5090 ac(0, st, xrp_b, {a[0], ua[1],
XRP(301), xrp_b.reward,
true});
5091 ac(0, st, xrp_b, {a[1], ua[2],
XRP(302), xrp_b.reward,
true});
5092 ac(1, st, xrp_b, {a[0], ua[3],
XRP(303), xrp_b.reward,
true});
5093 ac(2, st, xrp_b, {a[1], ua[4],
XRP(304), xrp_b.reward,
true});
5094 ac(3, st, xrp_b, {a[0], ua[5],
XRP(305), xrp_b.reward,
true});
5095 ac(4, st, xrp_b, {a[1], ua[6],
XRP(306), xrp_b.reward,
true});
5096 ac(6, st, xrp_b, {a[0], ua[7],
XRP(307), xrp_b.reward,
true});
5097 ac(7, st, xrp_b, {a[2], ua[8],
XRP(308), xrp_b.reward,
true});
5098 ac(9, st, xrp_b, {a[0], ua[9],
XRP(309), xrp_b.reward,
true});
5099 ac(9, st, xrp_b, {a[0], ua[9],
XRP(309), xrp_b.reward,
true});
5100 ac(10, st, xrp_b, {a[0], ua[10],
XRP(310), xrp_b.reward,
true});
5101 ac(12, st, xrp_b, {a[0], ua[11],
XRP(311), xrp_b.reward,
true});
5102 ac(12, st, xrp_b, {a[3], ua[12],
XRP(312), xrp_b.reward,
true});
5103 ac(12, st, xrp_b, {a[4], ua[13],
XRP(313), xrp_b.reward,
true});
5104 ac(12, st, xrp_b, {a[3], ua[14],
XRP(314), xrp_b.reward,
true});
5105 ac(12, st, xrp_b, {a[6], ua[15],
XRP(315), xrp_b.reward,
true});
5106 ac(13, st, xrp_b, {a[7], ua[16],
XRP(316), xrp_b.reward,
true});
5107 ac(15, st, xrp_b, {a[3], ua[17],
XRP(317), xrp_b.reward,
true});
5108 runSimulation(st,
true);
5114 testXChainSimulation();