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]() {
98 BEAST_EXPECT(bobXrpBalance == env.
balance(bob,
XRP));
99 BEAST_EXPECT(bobUsdBalance == env.
balance(bob, USD));
107 env(
pay(bob, alice, USD(25)));
113 env(
pay(bob, alice, bobPaysXRP),
fee(bobPaysFee));
119 BEAST_EXPECT(env.
balance(bob, USD) == USD(25));
136 env(
pay(alice, bob, USD(50)));
155 auto const baseFee = env.
current()->fees().base;
157 env.
fund(
XRP(10000), alice, bob);
174 env(
pay(bob, alice, bobPaysXRP),
fee(bobPaysFee));
228 env(
pay(alice, bob,
drops(baseFee - 1)));
258 IOU const USD1(gw1[
"USD"]);
259 IOU const USD2(gw2[
"USD"]);
262 [&](
FeatureBitset const& features,
bool noRipplePrev,
bool noRippleNext,
bool withDepositAuth) {
263 Env env(*
this, features);
265 env.
fund(
XRP(10000), gw1, alice, bob);
269 env.
trust(USD1(10), alice, bob);
271 env(
pay(gw1, alice, USD1(10)));
277 env(
pay(alice, bob, USD1(10)),
path(gw1),
ter(result));
281 [&](
FeatureBitset const& features,
bool noRipplePrev,
bool noRippleNext,
bool withDepositAuth) {
282 Env env(*
this, features);
284 env.
fund(
XRP(10000), gw1, gw2, alice);
288 env(
pay(gw2, alice, USD2(10)));
298 for (
int i = 0; i < 8; ++i)
300 auto const noRipplePrev = i & 0x1;
301 auto const noRippleNext = i & 0x2;
302 auto const withDepositAuth = i & 0x4;
326 jvParams[jss::ledger_index] = jss::validated;
327 jvParams[jss::deposit_preauth][jss::owner] = acc.
human();
328 jvParams[jss::deposit_preauth][jss::authorized_credentials] =
Json::arrayValue;
329 auto& arr(jvParams[jss::deposit_preauth][jss::authorized_credentials]);
330 for (
auto const& o :
auth)
332 arr.append(o.toLEJson());
334 return env.
rpc(
"json",
"ledger_entry",
to_string(jvParams));
352 env.
fund(
XRP(10000), alice, becky);
371 env.
fund(
XRP(10000), alice, becky);
388 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
396 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
421 env.
fund(
XRP(10000), alice, becky);
442 tx[sfUnauthorize.jsonName] = becky.human();
528 IOU const USD(gw[
"USD"]);
534 Env env(*
this, features);
535 env.
fund(
XRP(5000), alice, becky, gw);
538 env.
trust(USD(1000), alice);
539 env.
trust(USD(1000), becky);
542 env(
pay(gw, alice, USD(500)));
563 char const credType[] =
"abcde";
568 bool const supportsCredentials = features[featureCredentials];
583 ? jv[jss::result][jss::index].asString()
584 :
"48004829F915654A81B11C4AB8218D96FED67F209B58328A72314FB6"
596 Env env(*
this, features);
597 env.
fund(
XRP(5000), alice, becky, carol, gw);
600 env.
trust(USD(1000), alice);
601 env.
trust(USD(1000), becky);
602 env.
trust(USD(1000), carol);
605 env(
pay(gw, alice, USD(1000)));
609 env(
pay(alice, becky,
XRP(100)));
610 env(
pay(alice, becky, USD(100)));
637 env(
pay(alice, becky,
XRP(100)));
638 env(
pay(alice, becky, USD(100)));
655 env(
pay(alice, becky,
XRP(100)));
656 env(
pay(alice, becky, USD(100)));
672 env(
pay(alice, becky,
XRP(100)));
673 env(
pay(alice, becky, USD(100)));
682 char const credType[] =
"abcde";
683 Account const issuer{
"issuer"};
690 testcase(
"Payment failure with disabled credentials rule.");
694 env.
fund(
XRP(5000), issuer, bob, alice);
712 "0E0B04ED60588A758B67E21FBBE95AC5A63598BA951761DC0EC9C08D7E"
719 testcase(
"Payment with credentials.");
723 env.
fund(
XRP(5000), issuer, alice, bob, john);
732 std::string const credIdx = jv[jss::result][jss::index].asString();
745 jDP.isObject() && jDP.isMember(jss::result) && !jDP[jss::result].isMember(jss::error) &&
746 jDP[jss::result].isMember(jss::node) && jDP[jss::result][jss::node].isMember(
"LedgerEntryType") &&
747 jDP[jss::result][jss::node][
"LedgerEntryType"] == jss::DepositPreauth);
751 auto jv =
pay(alice, bob,
XRP(100));
782 testcase(
"Payment failure with invalid credentials.");
786 env.
fund(
XRP(10000), issuer, alice, bob, maria);
797 std::string const credIdx = jv[jss::result][jss::index].asString();
823 "0E0B04ED60588A758B67E21FBBE95AC5A63598BA951761DC0EC9C08D7E"
836 char const credType2[] =
"fghij";
842 std::string const credIdx2 = jv[jss::result][jss::index].asString();
862 char const credType[] =
"abcde";
863 Account const issuer{
"issuer"};
869 testcase(
"Creating / deleting with credentials.");
873 env.
fund(
XRP(5000), issuer, alice, bob);
886 jv[sfUnauthorize.jsonName] = issuer.human();
893 jv[sfAuthorize.jsonName] = issuer.human();
900 jv[sfUnauthorize.jsonName] = issuer.human();
907 jv[sfAuthorize.jsonName] = issuer.human();
920 auto& arr(jv[sfAuthorizeCredentials.jsonName]);
925 credParent[jss::Credential] = cred;
926 arr.
append(std::move(credParent));
939 Account const a(
"a"), b(
"b"), c(
"c"), d(
"d"), e(
"e"), f(
"f"), g(
"g"), h(
"h"), i(
"i");
940 auto const& z = credType;
942 bob, {{a, z}, {b, z}, {c, z}, {d, z}, {e, z}, {f, z}, {g, z}, {h, z}, {i, z}});
957 env.
fund(env.
current()->fees().accountReserve(0), john);
975 jDP.isObject() && jDP.isMember(jss::result) && !jDP[jss::result].isMember(jss::error) &&
976 jDP[jss::result].isMember(jss::node) && jDP[jss::result][jss::node].isMember(
"LedgerEntryType") &&
977 jDP[jss::result][jss::node][
"LedgerEntryType"] == jss::DepositPreauth);
980 BEAST_EXPECT(jDP[jss::result][jss::node][jss::Account] == bob.human());
981 auto const& credentials(jDP[jss::result][jss::node][
"AuthorizeCredentials"]);
982 BEAST_EXPECT(credentials.isArray() && credentials.size() == 1);
983 for (
auto const& o : credentials)
985 auto const& c(o[jss::Credential]);
986 BEAST_EXPECT(c[jss::Issuer].asString() == issuer.human());
1000 jDP.isObject() && jDP.isMember(jss::result) && jDP[jss::result].isMember(jss::error) &&
1001 jDP[jss::result][jss::error] ==
"entryNotFound");
1009 using namespace jtx;
1010 char const credType[] =
"abcde";
1011 char const credType2[] =
"fghijkl";
1012 Account const issuer{
"issuer"};
1016 IOU const USD = gw[
"USD"];
1020 testcase(
"Payment failure with expired credentials.");
1024 env.
fund(
XRP(10000), issuer, alice, bob, gw);
1031 uint32_t
const t = env.
current()->header().parentCloseTime.time_since_epoch().count() + 60;
1032 jv[sfExpiration.jsonName] = t;
1042 uint32_t
const t2 = env.
current()->header().parentCloseTime.time_since_epoch().count() + 1000;
1043 jv[sfExpiration.jsonName] = t2;
1054 std::string const credIdx = jv[jss::result][jss::index].asString();
1056 std::string const credIdx2 = jv[jss::result][jss::index].asString();
1079 jDelCred.isObject() && jDelCred.isMember(jss::result) &&
1080 jDelCred[jss::result].isMember(jss::error) &&
1081 jDelCred[jss::result][jss::error] ==
"entryNotFound");
1088 jle.isObject() && jle.isMember(jss::result) && !jle[jss::result].isMember(jss::error) &&
1089 jle[jss::result].isMember(jss::node) &&
1090 jle[jss::result][jss::node].isMember(
"LedgerEntryType") &&
1091 jle[jss::result][jss::node][
"LedgerEntryType"] == jss::Credential &&
1092 jle[jss::result][jss::node][jss::Issuer] == issuer.human() &&
1093 jle[jss::result][jss::node][jss::Subject] == alice.human() &&
1103 uint32_t
const t = env.
current()->header().parentCloseTime.time_since_epoch().count() + 40;
1104 jv[sfExpiration.jsonName] = t;
1111 std::string const credIdx = jv[jss::result][jss::index].asString();
1127 jDelCred.isObject() && jDelCred.isMember(jss::result) &&
1128 jDelCred[jss::result].isMember(jss::error) && jDelCred[jss::result][jss::error] ==
"entryNotFound");
1138 testcase(
"Escrow failure with expired credentials.");
1142 env.
fund(
XRP(5000), issuer, alice, bob, zelda);
1147 uint32_t const t = env.
current()->header().parentCloseTime.time_since_epoch().count() + 50;
1148 jv[sfExpiration.jsonName] = t;
1158 std::string const credIdx = jv[jss::result][jss::index].asString();
1167 auto const seq = env.
seq(alice);
1180 "0E0B04ED60588A758B67E21FBBE95AC5A63598BA951761DC0EC9C08D7E"
1195 jDelCred.isObject() && jDelCred.isMember(jss::result) && jDelCred[jss::result].isMember(jss::error) &&
1196 jDelCred[jss::result][jss::error] ==
"entryNotFound");
1203 using namespace jtx;
1213 env.
fund(
XRP(5000), stock, alice, bob);
1216 {
"a",
"a"}, {
"b",
"b"}, {
"c",
"c"}, {
"d",
"d"}, {
"e",
"e"}, {
"f",
"f"}, {
"g",
"g"}, {
"h",
"h"}};
1218 for (
auto const& c : credentials)
1219 env.
fund(
XRP(5000), c.issuer);
1227 for (
auto const& c : credentials)
1228 pubKey2Acc.
emplace(c.issuer.human(), c.issuer);
1231 for (
int i = 0; i < 10; ++i)
1238 auto const& authCred(dp[jss::result][jss::node][
"AuthorizeCredentials"]);
1239 BEAST_EXPECT(authCred.isArray() && authCred.size() == credentials.
size());
1241 for (
auto const& o : authCred)
1243 auto const& c(o[jss::Credential]);
1244 auto issuer = c[jss::Issuer].asString();
1246 if (BEAST_EXPECT(pubKey2Acc.
contains(issuer)))
1247 readCreds.
emplace_back(pubKey2Acc.
at(issuer), c[
"CredentialType"].asString());
1263 for (
int i = 0; i < 10; ++i)
1270 testcase(
"Check duplicate credentials.");
1276 for (
auto const& c : copyCredentials)
1278 auto credentials2 = copyCredentials;
1285 for (
auto const& c : credentials)
1297 for (
auto const& h : credentialIDs)
1299 auto credentialIDs2 = credentialIDs;
1322BEAST_DEFINE_TESTSUITE(DepositAuth, app,
xrpl);
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.
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
std::shared_ptr< SLE const > le(Account const &account) const
Return an account root.
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
PrettyAmount balance(Account const &account) const
Returns the XRP balance on an account.
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
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 memoize(Account const &account)
Associate AccountID with account.
void require(Args const &... args)
Check a set of requirements.
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
NetClock::time_point now()
Returns the current network time.
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 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 create(jtx::Account const &subject, jtx::Account const &issuer, std::string_view credType)
Json::Value authCredentials(jtx::Account const &account, std::vector< AuthorizeCredentials > const &auth)
Json::Value unauth(Account const &account, Account const &unauth)
Remove pre-authorization 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)
auto const finish_time
Set the "FinishAfter" time tag on a JTx.
Json::Value create(AccountID const &account, AccountID const &to, STAmount const &amount)
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.
Json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
std::uint32_t ownerCount(Env const &env, Account const &account)
XRP_t const XRP
Converts to XRP Issue or STAmount.
Json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
FeatureBitset testable_amendments()
owner_count< ltOFFER > offers
Match the number of offers in the account's owner directory.
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
owner_count< ltTICKET > tickets
Match the number of tickets on the account.
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
Json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
static bool hasDepositAuth(jtx::Env const &env, jtx::Account const &acct)
static XRPAmount reserve(jtx::Env &env, std::uint32_t count)
static Json::Value ledgerEntryDepositPreauth(jtx::Env &env, jtx::Account const &acc, std::vector< jtx::deposit::AuthorizeCredentials > const &auth)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
constexpr std::uint32_t tfSell
constexpr std::uint32_t tfPassive
std::string to_string(base_uint< Bits, Tag > const &a)
std::string strHex(FwdIt begin, FwdIt end)
constexpr std::uint32_t tfSetNoRipple
constexpr std::uint32_t asfDepositAuth
TERSubset< CanCvtToTER > TER
AccountID const & xrpAccount()
Compute AccountID from public key.
@ tecINSUFFICIENT_RESERVE
void run() override
Runs the suite.
void testCredentialsPayment()
void run() override
Runs the suite.
void testSortingCredentials()
void testCredentialsCreation()
void testPayment(FeatureBitset features)
Represents an XRP or IOU quantity This customizes the string conversion and supports XRP conversions ...
Set the sequence number on a JTx.