19#include <test/jtx/delegate.h>
21#include <xrpl/protocol/Feature.h>
22#include <xrpl/protocol/Permissions.h>
31 testcase(
"test featurePermissionDelegation not enabled");
38 env.fund(
XRP(1000000), gw, alice, bob);
51 testcase(
"test valid request creating, updating, deleting permissions");
57 env.
fund(
XRP(100000), gw, alice);
65 BEAST_EXPECT(entry[jss::result][jss::error] ==
"entryNotFound");
78 auto comparePermissions =
84 !jle[jss::result].isMember(jss::error) &&
85 jle[jss::result].isMember(jss::node));
87 jle[jss::result][jss::node][
"LedgerEntryType"] ==
90 jle[jss::result][jss::node][jss::Account] ==
93 jle[jss::result][jss::node][sfAuthorize.jsonName] ==
96 auto const& jPermissions =
97 jle[jss::result][jss::node][sfPermissions.jsonName];
99 for (
auto const& permission : permissions)
102 jPermissions[i][sfPermission.jsonName]
103 [sfPermissionValue.jsonName] == permission);
114 "Payment",
"AMMCreate",
"AMMDeposit",
"AMMWithdraw"};
129 BEAST_EXPECT(jle[jss::result][jss::error] ==
"entryNotFound");
138 BEAST_EXPECT(response[jss::result][jss::error] ==
"entryNotFound");
144 testcase(
"test invalid DelegateSet");
151 env.
fund(
XRP(100000), gw, alice, bob);
182 jv[jss::TransactionType] = jss::DelegateSet;
183 jv[jss::Account] = gw.human();
184 jv[sfAuthorize.jsonName] = alice.human();
187 permissionValue[sfPermissionValue.jsonName] =
"Payment";
189 permissionObj[sfPermission.jsonName] = permissionValue;
190 permissionsJson.
append(permissionObj);
191 jv[sfPermissions.jsonName] = permissionsJson;
192 jv[sfFee.jsonName] = -1;
205 "TrustlineAuthorize",
207 "TrustlineAuthorize"}),
252 drops(env.
current()->fees().accountReserve(1)), bob, carol);
306 env.
fund(
XRP(10000), alice, carol);
314 auto aliceBalance = env.
balance(alice);
315 auto bobBalance = env.
balance(bob);
316 auto carolBalance = env.
balance(carol);
318 env(
pay(alice, carol,
XRP(100)),
323 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
324 BEAST_EXPECT(env.
balance(bob) == bobBalance);
325 BEAST_EXPECT(env.
balance(carol) == carolBalance);
333 auto aliceBalance = env.
balance(alice);
334 auto bobBalance = env.
balance(bob);
335 auto carolBalance = env.
balance(carol);
337 auto const sendAmt =
XRP(100);
338 auto const feeAmt =
XRP(10);
341 BEAST_EXPECT(env.
balance(alice) == aliceBalance - sendAmt);
342 BEAST_EXPECT(env.
balance(bob) == bobBalance - feeAmt);
343 BEAST_EXPECT(env.
balance(carol) == carolBalance + sendAmt);
348 auto aliceBalance = env.
balance(alice);
349 auto bobBalance = env.
balance(bob);
350 auto carolBalance = env.
balance(carol);
352 env(
pay(alice, carol,
XRP(100)),
357 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
358 BEAST_EXPECT(env.
balance(bob) == bobBalance);
359 BEAST_EXPECT(env.
balance(carol) == carolBalance);
365 auto aliceBalance = env.
balance(alice);
366 auto bobBalance = env.
balance(bob);
367 auto carolBalance = env.
balance(carol);
368 auto const feeAmt =
XRP(10);
370 env(
pay(alice, carol,
XRP(20000)),
375 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
376 BEAST_EXPECT(env.
balance(bob) == bobBalance - feeAmt);
377 BEAST_EXPECT(env.
balance(carol) == carolBalance);
391 env.
fund(
XRP(10000), alice, bob, carol);
394 auto aliceSeq = env.
seq(alice);
395 auto bobSeq = env.
seq(bob);
399 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
400 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
401 aliceSeq = env.
seq(alice);
402 bobSeq = env.
seq(bob);
404 for (
auto i = 0; i < 20; ++i)
409 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
410 BEAST_EXPECT(env.
seq(bob) == bobSeq);
411 aliceSeq = env.
seq(alice);
415 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
416 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
417 bobSeq = env.
seq(bob);
422 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
423 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
424 bobSeq = env.
seq(bob);
428 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
429 BEAST_EXPECT(env.
seq(bob) == bobSeq);
430 aliceSeq = env.
seq(alice);
443 env.
fund(
XRP(100000), alice, bob);
454 auto const aliceBalance = env.
balance(alice);
455 auto const bobBalance = env.
balance(bob);
458 auto const deleteFee =
drops(env.
current()->fees().increment);
464 BEAST_EXPECT(env.
balance(bob) == bobBalance + aliceBalance - deleteFee);
473 testcase(
"test delegate transaction");
549 auto const USD = gw[
"USD"];
550 auto const EUR = gw2[
"EUR"];
555 env.
trust(USD(200), alice);
556 env.
trust(EUR(400), gw);
566 env(
pay(gw, alice, USD(50)),
579 env(
pay(gw, alice, USD(50)),
596 env(
pay(gw, alice,
XRP(50)),
610 BEAST_EXPECT(env.
balance(bob, USD) == USD(0));
620 BEAST_EXPECT(env.
balance(bob, USD) == USD(0));
638 env(
pay(gw2, gw, EUR(200)));
662 auto const USD = gw[
"USD"];
667 env.
trust(USD(200), alice);
684 env(
pay(gw, alice, USD(50)),
705 BEAST_EXPECT(env.
balance(bob, USD) == USD(0));
712 testcase(
"test TrustSet granular permissions");
721 env.
fund(
XRP(10000), gw, alice, bob);
729 env(
trust(alice, gw[
"USD"](50)),
735 env(
trust(alice, gw[
"USD"](50)));
783 gw, bob, {
"TrustlineAuthorize",
"TrustlineFreeze"}));
788 gw, bob, {
"TrustlineAuthorize",
"TrustlineUnfreeze"}));
801 env(
trust(alice, gw[
"USD"](100)),
804 env(
trust(gw, alice[
"USD"](100)),
809 auto tx =
trust(alice, gw[
"USD"](50));
810 tx[
"QualityIn"] =
"1000";
812 auto tx2 =
trust(alice, gw[
"USD"](50));
813 tx2[
"QualityOut"] =
"1000";
815 auto tx3 =
trust(gw, alice[
"USD"](50));
816 tx3[
"QualityIn"] =
"1000";
818 auto tx4 =
trust(gw, alice[
"USD"](50));
819 tx4[
"QualityOut"] =
"1000";
825 auto tx5 =
trust(gw, alice[
"USD"](50));
826 tx5[
"QualityOut"] =
"1000";
828 auto tx6 =
trust(alice, gw[
"USD"](50));
829 tx6[
"QualityOut"] =
"1000";
842 env.
fund(
XRP(10000), gw, alice, bob);
847 env(
trust(alice, gw[
"USD"](50)),
851 alice, bob, {
"TrustlineUnfreeze",
"NFTokenCreateOffer"}));
854 env(
trust(alice, gw[
"USD"](50)),
862 {
"TrustlineUnfreeze",
863 "NFTokenCreateOffer",
865 "AccountTransferRateSet"}));
873 {
"TrustlineUnfreeze",
874 "NFTokenCreateOffer",
876 "AccountTransferRateSet"}));
900 testcase(
"test AccountSet granular permissions");
908 auto const alice =
Account{
"alice"};
909 auto const bob =
Account{
"bob"};
910 env.
fund(
XRP(10000), alice, bob);
921 auto jt =
noop(alice);
922 jt[sfDomain.fieldName] =
strHex(domain);
923 jt[sfDelegate.fieldName] = bob.human();
929 alice, bob, {
"TrustlineUnfreeze",
"AccountEmailHashSet"}));
939 BEAST_EXPECT((*env.
le(alice))[sfDomain] ==
makeSlice(domain));
942 jt[sfDomain.fieldName] =
"";
944 BEAST_EXPECT(!env.
le(alice)->isFieldPresent(sfDomain));
948 std::string const failDomain =
"fail_domain_update";
950 jt[sfDomain.fieldName] =
strHex(failDomain);
957 jt[sfDomain.fieldName] =
strHex(domain);
958 std::string const mh(
"5F31A79367DC3137FADA860C05742EE6");
959 jt[sfEmailHash.fieldName] = mh;
964 alice, bob, {
"AccountDomainSet",
"AccountEmailHashSet"}));
967 BEAST_EXPECT(
to_string((*env.
le(alice))[sfEmailHash]) == mh);
968 BEAST_EXPECT((*env.
le(alice))[sfDomain] ==
makeSlice(domain));
972 jt[sfMessageKey.fieldName] =
strHex(rkp.first.slice());
980 "AccountEmailHashSet",
981 "AccountMessageKeySet"}));
987 strHex((*env.
le(alice))[sfMessageKey]) ==
988 strHex(rkp.first.slice()));
989 jt[sfMessageKey.fieldName] =
"";
991 BEAST_EXPECT(!env.
le(alice)->isFieldPresent(sfMessageKey));
1000 {
"AccountDomainSet",
1001 "AccountEmailHashSet",
1002 "AccountMessageKeySet",
1003 "AccountTransferRateSet"}));
1005 auto jtRate =
rate(alice, 2.0);
1006 jtRate[sfDelegate.fieldName] = bob.human();
1009 BEAST_EXPECT((*env.
le(alice))[sfTransferRate] == 2000000000);
1012 jt[sfTickSize.fieldName] = 8;
1019 {
"AccountDomainSet",
1020 "AccountEmailHashSet",
1021 "AccountMessageKeySet",
1022 "AccountTransferRateSet",
1023 "AccountTickSizeSet"}));
1026 BEAST_EXPECT((*env.
le(alice))[sfTickSize] == 8);
1047 jt[sfTickSize.fieldName] = 7;
1053 {
"AccountDomainSet",
1054 "AccountEmailHashSet",
1055 "AccountMessageKeySet"}));
1060 "9633EC8AF54F16B5286DB1D7B519EF49EEFC050C0C8AC4384F1D88ACD1BFDF"
1062 auto jt2 =
noop(alice);
1063 jt2[sfDomain.fieldName] =
strHex(domain);
1064 jt2[sfDelegate.fieldName] = bob.human();
1065 jt2[sfWalletLocator.fieldName] = locator;
1073 auto const alice =
Account{
"alice"};
1074 auto const bob =
Account{
"bob"};
1075 env.
fund(
XRP(10000), alice, bob);
1080 env(
fset(alice, flag),
1084 env(
fset(alice, flag));
1101 {
"AccountDomainSet",
1102 "AccountEmailHashSet",
1103 "AccountMessageKeySet"}));
1122 BEAST_EXPECT(env.
le(alice)->isFieldPresent(sfAccountTxnID));
1129 jt[sfDelegate.fieldName] = bob.human();
1130 jt[sfNFTokenMinter.fieldName] = bob.human();
1137 {
"AccountDomainSet",
1138 "AccountEmailHashSet",
1139 "AccountMessageKeySet"}));
1158 env(
regkey(bob, bobKey));
1170 testcase(
"test MPTokenIssuanceSet granular");
1171 using namespace jtx;
1178 env.
fund(
XRP(100000), alice, bob);
1205 mpt.set({.account = alice, .flags =
tfMPTLock, .delegate = bob});
1214 alice, bob, {
"MPTokenIssuanceLock",
"MPTokenIssuanceUnlock"}));
1216 mpt.set({.account = alice, .flags =
tfMPTUnlock, .delegate = bob});
1217 mpt.set({.account = alice, .flags =
tfMPTLock, .delegate = bob});
1226 env.
fund(
XRP(100000), alice, bob);
1237 mpt.set({.account = alice, .flags =
tfMPTLock, .delegate = bob});
1250 {
"NFTokenMint",
"MPTokenIssuanceLock",
"NFTokenBurn"}));
1264 "MPTokenIssuanceLock",
1266 "MPTokenIssuanceSet"}));
1267 mpt.set({.account = alice, .flags =
tfMPTUnlock, .delegate = bob});
1269 mpt.set({.account = alice, .flags =
tfMPTLock});
1270 mpt.set({.account = alice, .flags =
tfMPTUnlock, .delegate = bob});
1271 mpt.set({.account = alice, .flags =
tfMPTLock, .delegate = bob});
1279 using namespace jtx;
1285 env.
fund(
XRP(100000), alice, bob, carol);
1291 auto aliceBalance = env.
balance(alice);
1292 auto bobBalance = env.
balance(bob);
1293 auto carolBalance = env.
balance(carol);
1295 env(
pay(alice, carol,
XRP(100)),
1300 BEAST_EXPECT(env.
balance(alice) == aliceBalance -
XRP(100));
1301 BEAST_EXPECT(env.
balance(bob) == bobBalance -
XRP(10));
1302 BEAST_EXPECT(env.
balance(carol) == carolBalance +
XRP(100));
1308 testcase(
"test single sign with bad secret");
1309 using namespace jtx;
1315 env.
fund(
XRP(100000), alice, bob, carol);
1321 auto aliceBalance = env.
balance(alice);
1322 auto bobBalance = env.
balance(bob);
1323 auto carolBalance = env.
balance(carol);
1325 env(
pay(alice, carol,
XRP(100)),
1331 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
1332 BEAST_EXPECT(env.
balance(bob) == bobBalance);
1333 BEAST_EXPECT(env.
balance(carol) == carolBalance);
1340 using namespace jtx;
1348 env.
fund(
XRP(100000), alice, bob, carol, daria, edward);
1351 env(
signers(bob, 2, {{daria, 1}, {edward, 1}}));
1357 auto aliceBalance = env.
balance(alice);
1358 auto bobBalance = env.
balance(bob);
1359 auto carolBalance = env.
balance(carol);
1360 auto dariaBalance = env.
balance(daria);
1361 auto edwardBalance = env.
balance(edward);
1363 env(
pay(alice, carol,
XRP(100)),
1366 msig(daria, edward));
1368 BEAST_EXPECT(env.
balance(alice) == aliceBalance -
XRP(100));
1369 BEAST_EXPECT(env.
balance(bob) == bobBalance -
XRP(10));
1370 BEAST_EXPECT(env.
balance(carol) == carolBalance +
XRP(100));
1371 BEAST_EXPECT(env.
balance(daria) == dariaBalance);
1372 BEAST_EXPECT(env.
balance(edward) == edwardBalance);
1378 testcase(
"test multi sign which does not meet quorum");
1379 using namespace jtx;
1388 env.
fund(
XRP(100000), alice, bob, carol, daria, edward, fred);
1391 env(
signers(bob, 3, {{daria, 1}, {edward, 1}, {fred, 1}}));
1397 auto aliceBalance = env.
balance(alice);
1398 auto bobBalance = env.
balance(bob);
1399 auto carolBalance = env.
balance(carol);
1400 auto dariaBalance = env.
balance(daria);
1401 auto edwardBalance = env.
balance(edward);
1403 env(
pay(alice, carol,
XRP(100)),
1406 msig(daria, edward),
1409 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
1410 BEAST_EXPECT(env.
balance(bob) == bobBalance);
1411 BEAST_EXPECT(env.
balance(carol) == carolBalance);
1412 BEAST_EXPECT(env.
balance(daria) == dariaBalance);
1413 BEAST_EXPECT(env.
balance(edward) == edwardBalance);
1437BEAST_DEFINE_TESTSUITE(Delegate, app,
ripple);
Value & append(Value const &value)
Append value to array at the end.
testcase_t testcase
Memberspace for declaring test cases.
void testFeatureDisabled()
void testTrustSetGranular()
void run() override
Runs the suite.
void testMPTokenIssuanceSetGranular()
void testInvalidRequest()
void testPaymentGranular()
void testSingleSignBadSecret()
void testDelegateTransaction()
void testMultiSignQuorumNotMet()
void testAccountSetGranular()
Immutable cryptographic account descriptor.
A transaction testing environment.
std::shared_ptr< ReadView const > closed()
Returns the last closed ledger.
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.
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
PrettyAmount balance(Account const &account) const
Returns the XRP balance on an account.
std::shared_ptr< SLE const > le(Account const &account) const
Return an account root.
Sets the optional URI on a DIDSet.
Set a multisignature on a JTx.
Set the regular signature on a JTx.
Set the expected result code for a JTx The test will fail if the code doesn't match.
@ arrayValue
array value (ordered list)
Keylet delegate(AccountID const &account, AccountID const &authorizedAccount) noexcept
A keylet for Delegate object.
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Json::Value create(A const &account, A const &dest, STAmount const &sendMax)
Create a check.
Json::Value entry(jtx::Env &env, jtx::Account const &account, jtx::Account const &authorize)
Json::Value set(jtx::Account const &account, jtx::Account const &authorize, std::vector< std::string > const &permissions)
Json::Value set(jtx::Account const &account)
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
Json::Value regkey(Account const &account, disabled_t)
Disable the regular key.
Json::Value signers(Account const &account, std::uint32_t quorum, std::vector< signer > const &v)
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.
Json::Value rate(Account const &account, double multiplier)
Set a transfer rate.
Json::Value acctdelete(Account const &account, Account const &dest)
Delete account.
XRP_t const XRP
Converts to XRP Issue or STAmount.
FeatureBitset supported_amendments()
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
constexpr std::uint32_t asfGlobalFreeze
constexpr std::uint32_t asfDepositAuth
constexpr std::uint32_t asfDisallowIncomingNFTokenOffer
constexpr std::uint32_t tfSetDeepFreeze
constexpr std::uint32_t asfRequireDest
constexpr std::uint32_t const tfMPTUnlock
constexpr std::uint32_t asfAuthorizedNFTokenMinter
constexpr std::uint32_t asfNoFreeze
constexpr std::uint32_t asfDisableMaster
constexpr std::uint32_t asfDisallowIncomingTrustline
constexpr std::uint32_t tfClearNoRipple
std::string strHex(FwdIt begin, FwdIt end)
constexpr std::uint32_t tfSetfAuth
constexpr std::uint32_t asfAccountTxnID
constexpr std::uint32_t asfDefaultRipple
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
constexpr std::uint32_t asfDisallowIncomingCheck
constexpr std::uint32_t tfClearFreeze
constexpr std::uint32_t tfRequireAuth
@ tecINSUFFICIENT_RESERVE
constexpr std::uint32_t const tfMPTLock
constexpr std::uint32_t tfClearDeepFreeze
std::string to_string(base_uint< Bits, Tag > const &a)
constexpr std::uint32_t asfDisallowIncomingPayChan
std::pair< PublicKey, SecretKey > randomKeyPair(KeyType type)
Create a key pair using secure random numbers.
constexpr std::uint32_t tfFullyCanonicalSig
Transaction flags.
constexpr std::uint32_t asfAllowTrustLineClawback
constexpr std::uint32_t asfRequireAuth
constexpr std::uint32_t tfSetFreeze
constexpr std::uint32_t tfSetNoRipple
constexpr std::uint32_t const tfMPTCanLock
constexpr std::uint32_t asfDisallowXRP