3#include <xrpl/protocol/Feature.h>
15 return env.
current()->fees().accountReserve(count);
76 IOU const USD = gw[
"USD"];
80 env.
fund(
XRP(10000), alice, bob, carol, gw);
82 env.
trust(USD(1000), alice, bob);
85 env(
pay(gw, alice, USD(150)));
86 env(
offer(carol, USD(100),
XRP(100)));
90 env(
pay(alice, bob, USD(50)));
98 auto failedIouPayments = [
this, &env, &alice, &bob, &USD]() {
115 BEAST_EXPECT(bobXrpBalance == env.
balance(bob,
XRP));
116 BEAST_EXPECT(bobUsdBalance == env.
balance(bob, USD));
124 env(
pay(bob, alice, USD(25)));
130 env(
pay(bob, alice, bobPaysXRP),
fee(bobPaysFee));
136 BEAST_EXPECT(env.
balance(bob, USD) == USD(25));
153 env(
pay(alice, bob, USD(50)));
172 auto const baseFee = env.
current()->fees().base;
174 env.
fund(
XRP(10000), alice, bob);
191 env(
pay(bob, alice, bobPaysXRP),
fee(bobPaysFee));
247 env(
pay(alice, bob,
drops(baseFee - 1)));
277 IOU const USD1(gw1[
"USD"]);
278 IOU const USD2(gw2[
"USD"]);
283 bool withDepositAuth) {
284 assert(!withDepositAuth || features[featureDepositAuth]);
286 Env env(*
this, features);
288 env.
fund(
XRP(10000), gw1, alice, bob);
292 env.
trust(USD1(10), alice, bob);
294 env(
pay(gw1, alice, USD1(10)));
301 env(
pay(alice, bob, USD1(10)),
path(gw1),
ter(result));
307 bool withDepositAuth) {
308 assert(!withDepositAuth || features[featureDepositAuth]);
310 Env env(*
this, features);
312 env.
fund(
XRP(10000), gw1, gw2, alice);
316 env(
pay(gw2, alice, USD2(10)));
323 env(
pay(gw1, gw2, USD2(10)),
330 for (
int i = 0; i < 8; ++i)
332 auto const noRipplePrev = i & 0x1;
333 auto const noRippleNext = i & 0x2;
334 auto const withDepositAuth = i & 0x4;
341 if (!withDepositAuth)
354 if (!withDepositAuth)
380 jvParams[jss::ledger_index] = jss::validated;
381 jvParams[jss::deposit_preauth][jss::owner] = acc.
human();
382 jvParams[jss::deposit_preauth][jss::authorized_credentials] =
384 auto& arr(jvParams[jss::deposit_preauth][jss::authorized_credentials]);
385 for (
auto const& o :
auth)
387 arr.append(o.toLEJson());
389 return env.
rpc(
"json",
"ledger_entry",
to_string(jvParams));
405 env.
fund(
XRP(10000), alice, becky);
427 env.
fund(
XRP(10000), alice, becky);
446 env.
fund(
XRP(10000), alice, becky);
463 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
471 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
496 env.
fund(
XRP(10000), alice, becky);
517 tx[sfUnauthorize.jsonName] = becky.human();
603 IOU const USD(gw[
"USD"]);
605 bool const supportsPreauth = {features[featureDepositPreauth]};
611 Env env(*
this, features);
612 env.
fund(
XRP(5000), alice, becky, gw);
615 env.
trust(USD(1000), alice);
616 env.
trust(USD(1000), becky);
619 env(
pay(gw, alice, USD(500)));
640 env(
pay(becky, becky, USD(10)),
648 char const credType[] =
"abcde";
653 bool const supportsCredentials = features[featureCredentials];
655 TER const expectCredentials(
657 TER const expectPayment(
674 ter(expectCredentials));
677 ter(expectCredentials));
682 ? jv[jss::result][jss::index].asString()
683 :
"48004829F915654A81B11C4AB8218D96FED67F209B58328A72314FB6"
686 env(
pay(gw, becky, USD(100)),
695 if (!supportsPreauth)
697 auto const seq1 = env.
seq(alice);
717 Env env(*
this, features);
718 env.
fund(
XRP(5000), alice, becky, carol, gw);
721 env.
trust(USD(1000), alice);
722 env.
trust(USD(1000), becky);
723 env.
trust(USD(1000), carol);
726 env(
pay(gw, alice, USD(1000)));
730 env(
pay(alice, becky,
XRP(100)));
731 env(
pay(alice, becky, USD(100)));
758 env(
pay(alice, becky,
XRP(100)));
759 env(
pay(alice, becky, USD(100)));
776 env(
pay(alice, becky,
XRP(100)));
777 env(
pay(alice, becky, USD(100)));
793 env(
pay(alice, becky,
XRP(100)));
794 env(
pay(alice, becky, USD(100)));
804 char const credType[] =
"abcde";
805 Account const issuer{
"issuer"};
812 testcase(
"Payment failure with disabled credentials rule.");
816 env.
fund(
XRP(5000), issuer, bob, alice);
835 "0E0B04ED60588A758B67E21FBBE95AC5A63598BA951761DC0EC9C08D7E"
837 env(
pay(alice, bob,
XRP(10)),
844 testcase(
"Payment with credentials.");
848 env.
fund(
XRP(5000), issuer, alice, bob, john);
858 std::string const credIdx = jv[jss::result][jss::index].asString();
872 jDP.isObject() && jDP.isMember(jss::result) &&
873 !jDP[jss::result].isMember(jss::error) &&
874 jDP[jss::result].isMember(jss::node) &&
875 jDP[jss::result][jss::node].isMember(
"LedgerEntryType") &&
876 jDP[jss::result][jss::node][
"LedgerEntryType"] ==
877 jss::DepositPreauth);
881 auto jv =
pay(alice, bob,
XRP(100));
888 env(
pay(alice, bob,
XRP(100)),
914 testcase(
"Payment failure with invalid credentials.");
918 env.
fund(
XRP(10000), issuer, alice, bob, maria);
930 std::string const credIdx = jv[jss::result][jss::index].asString();
944 env(
pay(alice, bob,
XRP(100)),
951 bob, {{issuer, credType}, {issuer, credType}}),
960 "0E0B04ED60588A758B67E21FBBE95AC5A63598BA951761DC0EC9C08D7E"
963 env(
pay(alice, bob,
XRP(100)),
970 env(
pay(maria, bob,
XRP(100)),
977 char const credType2[] =
"fghij";
985 jv[jss::result][jss::index].asString();
988 env(
pay(alice, bob,
XRP(100)),
994 env(
pay(alice, bob,
XRP(100)),
1007 using namespace jtx;
1009 char const credType[] =
"abcde";
1010 Account const issuer{
"issuer"};
1016 testcase(
"Creating / deleting with credentials.");
1020 env.
fund(
XRP(5000), issuer, alice, bob);
1033 jv[sfUnauthorize.jsonName] = issuer.human();
1040 jv[sfAuthorize.jsonName] = issuer.human();
1047 jv[sfUnauthorize.jsonName] = issuer.human();
1054 jv[sfAuthorize.jsonName] = issuer.human();
1067 auto& arr(jv[sfAuthorizeCredentials.jsonName]);
1070 cred[sfCredentialType.jsonName] =
1073 credParent[jss::Credential] = cred;
1074 arr.
append(std::move(credParent));
1087 Account const a(
"a"), b(
"b"), c(
"c"), d(
"d"), e(
"e"), f(
"f"),
1088 g(
"g"), h(
"h"), i(
"i");
1089 auto const& z = credType;
1115 env.
fund(env.
current()->fees().accountReserve(0), john);
1135 jDP.isObject() && jDP.isMember(jss::result) &&
1136 !jDP[jss::result].isMember(jss::error) &&
1137 jDP[jss::result].isMember(jss::node) &&
1138 jDP[jss::result][jss::node].isMember(
"LedgerEntryType") &&
1139 jDP[jss::result][jss::node][
"LedgerEntryType"] ==
1140 jss::DepositPreauth);
1144 jDP[jss::result][jss::node][jss::Account] == bob.human());
1145 auto const& credentials(
1146 jDP[jss::result][jss::node][
"AuthorizeCredentials"]);
1147 BEAST_EXPECT(credentials.isArray() && credentials.size() == 1);
1148 for (
auto const& o : credentials)
1150 auto const& c(o[jss::Credential]);
1151 BEAST_EXPECT(c[jss::Issuer].asString() == issuer.human());
1153 c[
"CredentialType"].asString() ==
1169 jDP.isObject() && jDP.isMember(jss::result) &&
1170 jDP[jss::result].isMember(jss::error) &&
1171 jDP[jss::result][jss::error] ==
"entryNotFound");
1179 using namespace jtx;
1180 char const credType[] =
"abcde";
1181 char const credType2[] =
"fghijkl";
1182 Account const issuer{
"issuer"};
1186 IOU const USD = gw[
"USD"];
1190 testcase(
"Payment failure with expired credentials.");
1194 env.
fund(
XRP(10000), issuer, alice, bob, gw);
1203 .parentCloseTime.time_since_epoch()
1206 jv[sfExpiration.jsonName] = t;
1218 .parentCloseTime.time_since_epoch()
1221 jv[sfExpiration.jsonName] = t2;
1232 std::string const credIdx = jv[jss::result][jss::index].asString();
1234 std::string const credIdx2 = jv[jss::result][jss::index].asString();
1241 bob, {{issuer, credType}, {issuer, credType2}}));
1246 env(
pay(alice, bob,
XRP(100)),
1252 env(
pay(alice, bob,
XRP(100)),
1259 auto const jDelCred =
1262 jDelCred.isObject() && jDelCred.isMember(jss::result) &&
1263 jDelCred[jss::result].isMember(jss::error) &&
1264 jDelCred[jss::result][jss::error] ==
"entryNotFound");
1272 jle.isObject() && jle.isMember(jss::result) &&
1273 !jle[jss::result].isMember(jss::error) &&
1274 jle[jss::result].isMember(jss::node) &&
1275 jle[jss::result][jss::node].isMember(
1276 "LedgerEntryType") &&
1277 jle[jss::result][jss::node][
"LedgerEntryType"] ==
1279 jle[jss::result][jss::node][jss::Issuer] ==
1281 jle[jss::result][jss::node][jss::Subject] ==
1283 jle[jss::result][jss::node][
"CredentialType"] ==
1295 .parentCloseTime.time_since_epoch()
1298 jv[sfExpiration.jsonName] = t;
1306 jv[jss::result][jss::index].asString();
1316 env(
pay(gw, bob, USD(150)),
1322 auto const jDelCred =
1325 jDelCred.isObject() && jDelCred.isMember(jss::result) &&
1326 jDelCred[jss::result].isMember(jss::error) &&
1327 jDelCred[jss::result][jss::error] ==
"entryNotFound");
1337 testcase(
"Escrow failure with expired credentials.");
1341 env.
fund(
XRP(5000), issuer, alice, bob, zelda);
1348 .parentCloseTime.time_since_epoch()
1351 jv[sfExpiration.jsonName] = t;
1361 std::string const credIdx = jv[jss::result][jss::index].asString();
1370 auto const seq = env.
seq(alice);
1386 "0E0B04ED60588A758B67E21FBBE95AC5A63598BA951761DC0EC9C08D7E"
1404 auto const jDelCred =
1407 jDelCred.isObject() && jDelCred.isMember(jss::result) &&
1408 jDelCred[jss::result].isMember(jss::error) &&
1409 jDelCred[jss::result][jss::error] ==
"entryNotFound");
1416 using namespace jtx;
1426 env.
fund(
XRP(5000), stock, alice, bob);
1438 for (
auto const& c : credentials)
1439 env.
fund(
XRP(5000), c.issuer);
1447 for (
auto const& c : credentials)
1448 pubKey2Acc.
emplace(c.issuer.human(), c.issuer);
1451 for (
int i = 0; i < 10; ++i)
1459 auto const& authCred(
1460 dp[jss::result][jss::node][
"AuthorizeCredentials"]);
1462 authCred.isArray() &&
1463 authCred.size() == credentials.
size());
1465 for (
auto const& o : authCred)
1467 auto const& c(o[jss::Credential]);
1468 auto issuer = c[jss::Issuer].asString();
1470 if (BEAST_EXPECT(pubKey2Acc.
contains(issuer)))
1472 pubKey2Acc.
at(issuer),
1473 c[
"CredentialType"].asString());
1489 for (
int i = 0; i < 10; ++i)
1497 testcase(
"Check duplicate credentials.");
1501 credentials.
begin(), credentials.
end() - 1);
1504 for (
auto const& c : copyCredentials)
1506 auto credentials2 = copyCredentials;
1514 for (
auto const& c : credentials)
1525 c.credType)[jss::result][jss::index]
1530 for (
auto const& h : credentialIDs)
1532 auto credentialIDs2 = credentialIDs;
1535 env(
pay(alice, bob,
XRP(100)),
1548 testPayment(supported - featureDepositPreauth - featureCredentials);
1559BEAST_DEFINE_TESTSUITE(DepositAuth, app,
ripple);
Value & append(Value const &value)
Append value to array at the end.
Value removeMember(char const *key)
Remove and return the named member.
std::string asString() const
Returns the unquoted string value.
testcase_t testcase
Memberspace for declaring test cases.
bool expect(Condition const &shouldBeTrue)
Evaluate a test condition.
Immutable cryptographic account descriptor.
std::string const & human() const
Returns the human readable public key.
A transaction testing environment.
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
void require(Args const &... args)
Check a set of requirements.
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
NetClock::time_point now()
Returns the current network time.
Json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
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< SLE const > le(Account const &account) const
Return an account root.
Converts to IOU Issue or STAmount.
Match clear account flags.
Match the number of items in the account's owner directory.
Check a set of conditions.
Sets the SendMax on a JTx.
Set the expected result code for a JTx The test will fail if the code doesn't match.
Set a ticket sequence on a JTx.
T emplace_back(T... args)
@ arrayValue
array value (ordered list)
@ objectValue
object value (collection of name/value pairs).
Json::Value create(jtx::Account const &subject, jtx::Account const &issuer, std::string_view credType)
Json::Value accept(jtx::Account const &subject, jtx::Account const &issuer, std::string_view credType)
Json::Value ledgerEntry(jtx::Env &env, jtx::Account const &subject, jtx::Account const &issuer, std::string_view credType)
Json::Value unauth(Account const &account, Account const &unauth)
Remove preauthorization for deposit.
Json::Value auth(Account const &account, Account const &auth)
Preauthorize for deposit.
Json::Value unauthCredentials(jtx::Account const &account, std::vector< AuthorizeCredentials > const &auth)
Json::Value authCredentials(jtx::Account const &account, std::vector< AuthorizeCredentials > const &auth)
Json::Value create(AccountID const &account, AccountID const &to, STAmount const &amount)
auto const finish_time
Set the "FinishAfter" time tag on a JTx.
Json::Value finish(AccountID const &account, AccountID const &from, std::uint32_t seq)
Json::Value create(Account const &account, std::uint32_t count)
Create one of more tickets.
std::uint32_t ownerCount(Env const &env, Account const &account)
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
owner_count< ltOFFER > offers
Match the number of offers in the account's owner directory.
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
Json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
Json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
FeatureBitset testable_amendments()
Json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
owner_count< ltTICKET > tickets
Match the number of tickets on the account.
XRP_t const XRP
Converts to XRP Issue or STAmount.
static Json::Value ledgerEntryDepositPreauth(jtx::Env &env, jtx::Account const &acc, std::vector< jtx::deposit::AuthorizeCredentials > const &auth)
static bool hasDepositAuth(jtx::Env const &env, jtx::Account const &acct)
static XRPAmount reserve(jtx::Env &env, std::uint32_t count)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
constexpr std::uint32_t asfDepositAuth
AccountID const & xrpAccount()
Compute AccountID from public key.
constexpr std::uint32_t tfPassive
std::string strHex(FwdIt begin, FwdIt end)
@ tecINSUFFICIENT_RESERVE
std::string to_string(base_uint< Bits, Tag > const &a)
constexpr std::uint32_t tfSell
TERSubset< CanCvtToTER > TER
constexpr std::uint32_t tfSetNoRipple
void run() override
Runs the suite.
void testCredentialsCreation()
void testPayment(FeatureBitset features)
void run() override
Runs the suite.
void testSortingCredentials()
void testCredentialsPayment()
Represents an XRP or IOU quantity This customizes the string conversion and supports XRP conversions ...
Set the sequence number on a JTx.