3#include <xrpl/protocol/Feature.h>
15 return env.
current()->fees().accountReserve(count);
61 IOU const USD = gw[
"USD"];
65 env.
fund(
XRP(10000), alice, bob, carol, gw);
67 env.
trust(USD(1000), alice, bob);
70 env(
pay(gw, alice, USD(150)));
71 env(
offer(carol, USD(100),
XRP(100)));
75 env(
pay(alice, bob, USD(50)));
83 auto failedIouPayments = [
this, &env, &alice, &bob, &USD]() {
100 BEAST_EXPECT(bobXrpBalance == env.
balance(bob,
XRP));
101 BEAST_EXPECT(bobUsdBalance == env.
balance(bob, USD));
109 env(
pay(bob, alice, USD(25)));
115 env(
pay(bob, alice, bobPaysXRP),
fee(bobPaysFee));
121 BEAST_EXPECT(env.
balance(bob, USD) == USD(25));
138 env(
pay(alice, bob, USD(50)));
157 auto const baseFee = env.
current()->fees().base;
159 env.
fund(
XRP(10000), alice, bob);
176 env(
pay(bob, alice, bobPaysXRP),
fee(bobPaysFee));
232 env(
pay(alice, bob,
drops(baseFee - 1)));
262 IOU const USD1(gw1[
"USD"]);
263 IOU const USD2(gw2[
"USD"]);
268 bool withDepositAuth) {
269 Env env(*
this, features);
271 env.
fund(
XRP(10000), gw1, alice, bob);
275 env.
trust(USD1(10), alice, bob);
277 env(
pay(gw1, alice, USD1(10)));
284 env(
pay(alice, bob, USD1(10)),
path(gw1),
ter(result));
290 bool withDepositAuth) {
291 Env env(*
this, features);
293 env.
fund(
XRP(10000), gw1, gw2, alice);
297 env(
pay(gw2, alice, USD2(10)));
304 env(
pay(gw1, gw2, USD2(10)),
311 for (
int i = 0; i < 8; ++i)
313 auto const noRipplePrev = i & 0x1;
314 auto const noRippleNext = i & 0x2;
315 auto const withDepositAuth = i & 0x4;
347 jvParams[jss::ledger_index] = jss::validated;
348 jvParams[jss::deposit_preauth][jss::owner] = acc.
human();
349 jvParams[jss::deposit_preauth][jss::authorized_credentials] =
351 auto& arr(jvParams[jss::deposit_preauth][jss::authorized_credentials]);
352 for (
auto const& o :
auth)
354 arr.append(o.toLEJson());
356 return env.
rpc(
"json",
"ledger_entry",
to_string(jvParams));
374 env.
fund(
XRP(10000), alice, becky);
393 env.
fund(
XRP(10000), alice, becky);
410 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
418 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
443 env.
fund(
XRP(10000), alice, becky);
464 tx[sfUnauthorize.jsonName] = becky.human();
550 IOU const USD(gw[
"USD"]);
556 Env env(*
this, features);
557 env.
fund(
XRP(5000), alice, becky, gw);
560 env.
trust(USD(1000), alice);
561 env.
trust(USD(1000), becky);
564 env(
pay(gw, alice, USD(500)));
581 env(
pay(becky, becky, USD(10)),
589 char const credType[] =
"abcde";
594 bool const supportsCredentials = features[featureCredentials];
611 ? jv[jss::result][jss::index].asString()
612 :
"48004829F915654A81B11C4AB8218D96FED67F209B58328A72314FB6"
615 env(
pay(gw, becky, USD(100)),
626 Env env(*
this, features);
627 env.
fund(
XRP(5000), alice, becky, carol, gw);
630 env.
trust(USD(1000), alice);
631 env.
trust(USD(1000), becky);
632 env.
trust(USD(1000), carol);
635 env(
pay(gw, alice, USD(1000)));
639 env(
pay(alice, becky,
XRP(100)));
640 env(
pay(alice, becky, USD(100)));
667 env(
pay(alice, becky,
XRP(100)));
668 env(
pay(alice, becky, USD(100)));
685 env(
pay(alice, becky,
XRP(100)));
686 env(
pay(alice, becky, USD(100)));
702 env(
pay(alice, becky,
XRP(100)));
703 env(
pay(alice, becky, USD(100)));
712 char const credType[] =
"abcde";
713 Account const issuer{
"issuer"};
720 testcase(
"Payment failure with disabled credentials rule.");
724 env.
fund(
XRP(5000), issuer, bob, alice);
743 "0E0B04ED60588A758B67E21FBBE95AC5A63598BA951761DC0EC9C08D7E"
745 env(
pay(alice, bob,
XRP(10)),
752 testcase(
"Payment with credentials.");
756 env.
fund(
XRP(5000), issuer, alice, bob, john);
766 std::string const credIdx = jv[jss::result][jss::index].asString();
780 jDP.isObject() && jDP.isMember(jss::result) &&
781 !jDP[jss::result].isMember(jss::error) &&
782 jDP[jss::result].isMember(jss::node) &&
783 jDP[jss::result][jss::node].isMember(
"LedgerEntryType") &&
784 jDP[jss::result][jss::node][
"LedgerEntryType"] ==
785 jss::DepositPreauth);
789 auto jv =
pay(alice, bob,
XRP(100));
796 env(
pay(alice, bob,
XRP(100)),
822 testcase(
"Payment failure with invalid credentials.");
826 env.
fund(
XRP(10000), issuer, alice, bob, maria);
838 std::string const credIdx = jv[jss::result][jss::index].asString();
852 env(
pay(alice, bob,
XRP(100)),
859 bob, {{issuer, credType}, {issuer, credType}}),
868 "0E0B04ED60588A758B67E21FBBE95AC5A63598BA951761DC0EC9C08D7E"
871 env(
pay(alice, bob,
XRP(100)),
878 env(
pay(maria, bob,
XRP(100)),
885 char const credType2[] =
"fghij";
893 jv[jss::result][jss::index].asString();
896 env(
pay(alice, bob,
XRP(100)),
902 env(
pay(alice, bob,
XRP(100)),
917 char const credType[] =
"abcde";
918 Account const issuer{
"issuer"};
924 testcase(
"Creating / deleting with credentials.");
928 env.
fund(
XRP(5000), issuer, alice, bob);
941 jv[sfUnauthorize.jsonName] = issuer.human();
948 jv[sfAuthorize.jsonName] = issuer.human();
955 jv[sfUnauthorize.jsonName] = issuer.human();
962 jv[sfAuthorize.jsonName] = issuer.human();
975 auto& arr(jv[sfAuthorizeCredentials.jsonName]);
978 cred[sfCredentialType.jsonName] =
981 credParent[jss::Credential] = cred;
982 arr.
append(std::move(credParent));
995 Account const a(
"a"), b(
"b"), c(
"c"), d(
"d"), e(
"e"), f(
"f"),
996 g(
"g"), h(
"h"), i(
"i");
997 auto const& z = credType;
1023 env.
fund(env.
current()->fees().accountReserve(0), john);
1043 jDP.isObject() && jDP.isMember(jss::result) &&
1044 !jDP[jss::result].isMember(jss::error) &&
1045 jDP[jss::result].isMember(jss::node) &&
1046 jDP[jss::result][jss::node].isMember(
"LedgerEntryType") &&
1047 jDP[jss::result][jss::node][
"LedgerEntryType"] ==
1048 jss::DepositPreauth);
1052 jDP[jss::result][jss::node][jss::Account] == bob.human());
1053 auto const& credentials(
1054 jDP[jss::result][jss::node][
"AuthorizeCredentials"]);
1055 BEAST_EXPECT(credentials.isArray() && credentials.size() == 1);
1056 for (
auto const& o : credentials)
1058 auto const& c(o[jss::Credential]);
1059 BEAST_EXPECT(c[jss::Issuer].asString() == issuer.human());
1061 c[
"CredentialType"].asString() ==
1077 jDP.isObject() && jDP.isMember(jss::result) &&
1078 jDP[jss::result].isMember(jss::error) &&
1079 jDP[jss::result][jss::error] ==
"entryNotFound");
1087 using namespace jtx;
1088 char const credType[] =
"abcde";
1089 char const credType2[] =
"fghijkl";
1090 Account const issuer{
"issuer"};
1094 IOU const USD = gw[
"USD"];
1098 testcase(
"Payment failure with expired credentials.");
1102 env.
fund(
XRP(10000), issuer, alice, bob, gw);
1109 uint32_t
const t = env.
current()
1111 .parentCloseTime.time_since_epoch()
1114 jv[sfExpiration.jsonName] = t;
1124 uint32_t
const t2 = env.
current()
1126 .parentCloseTime.time_since_epoch()
1129 jv[sfExpiration.jsonName] = t2;
1140 std::string const credIdx = jv[jss::result][jss::index].asString();
1142 std::string const credIdx2 = jv[jss::result][jss::index].asString();
1149 bob, {{issuer, credType}, {issuer, credType2}}));
1154 env(
pay(alice, bob,
XRP(100)),
1160 env(
pay(alice, bob,
XRP(100)),
1167 auto const jDelCred =
1170 jDelCred.isObject() && jDelCred.isMember(jss::result) &&
1171 jDelCred[jss::result].isMember(jss::error) &&
1172 jDelCred[jss::result][jss::error] ==
"entryNotFound");
1180 jle.isObject() && jle.isMember(jss::result) &&
1181 !jle[jss::result].isMember(jss::error) &&
1182 jle[jss::result].isMember(jss::node) &&
1183 jle[jss::result][jss::node].isMember(
1184 "LedgerEntryType") &&
1185 jle[jss::result][jss::node][
"LedgerEntryType"] ==
1187 jle[jss::result][jss::node][jss::Issuer] ==
1189 jle[jss::result][jss::node][jss::Subject] ==
1191 jle[jss::result][jss::node][
"CredentialType"] ==
1201 uint32_t
const t = env.
current()
1203 .parentCloseTime.time_since_epoch()
1206 jv[sfExpiration.jsonName] = t;
1214 jv[jss::result][jss::index].asString();
1224 env(
pay(gw, bob, USD(150)),
1230 auto const jDelCred =
1233 jDelCred.isObject() && jDelCred.isMember(jss::result) &&
1234 jDelCred[jss::result].isMember(jss::error) &&
1235 jDelCred[jss::result][jss::error] ==
"entryNotFound");
1245 testcase(
"Escrow failure with expired credentials.");
1249 env.
fund(
XRP(5000), issuer, alice, bob, zelda);
1256 .parentCloseTime.time_since_epoch()
1259 jv[sfExpiration.jsonName] = t;
1269 std::string const credIdx = jv[jss::result][jss::index].asString();
1278 auto const seq = env.
seq(alice);
1294 "0E0B04ED60588A758B67E21FBBE95AC5A63598BA951761DC0EC9C08D7E"
1312 auto const jDelCred =
1315 jDelCred.isObject() && jDelCred.isMember(jss::result) &&
1316 jDelCred[jss::result].isMember(jss::error) &&
1317 jDelCred[jss::result][jss::error] ==
"entryNotFound");
1324 using namespace jtx;
1334 env.
fund(
XRP(5000), stock, alice, bob);
1346 for (
auto const& c : credentials)
1347 env.
fund(
XRP(5000), c.issuer);
1355 for (
auto const& c : credentials)
1356 pubKey2Acc.
emplace(c.issuer.human(), c.issuer);
1359 for (
int i = 0; i < 10; ++i)
1367 auto const& authCred(
1368 dp[jss::result][jss::node][
"AuthorizeCredentials"]);
1370 authCred.isArray() &&
1371 authCred.size() == credentials.
size());
1373 for (
auto const& o : authCred)
1375 auto const& c(o[jss::Credential]);
1376 auto issuer = c[jss::Issuer].asString();
1378 if (BEAST_EXPECT(pubKey2Acc.
contains(issuer)))
1380 pubKey2Acc.
at(issuer),
1381 c[
"CredentialType"].asString());
1397 for (
int i = 0; i < 10; ++i)
1405 testcase(
"Check duplicate credentials.");
1409 credentials.
begin(), credentials.
end() - 1);
1412 for (
auto const& c : copyCredentials)
1414 auto credentials2 = copyCredentials;
1422 for (
auto const& c : credentials)
1433 c.credType)[jss::result][jss::index]
1438 for (
auto const& h : credentialIDs)
1440 auto credentialIDs2 = credentialIDs;
1443 env(
pay(alice, bob,
XRP(100)),
1465BEAST_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.
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.