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"}),
253 drops(env.
current()->fees().accountReserve(1)), bob, carol);
307 env.
fund(
XRP(10000), alice, carol);
315 auto aliceBalance = env.
balance(alice);
316 auto bobBalance = env.
balance(bob);
317 auto carolBalance = env.
balance(carol);
319 env(
pay(alice, carol,
XRP(100)),
324 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
325 BEAST_EXPECT(env.
balance(bob) == bobBalance);
326 BEAST_EXPECT(env.
balance(carol) == carolBalance);
334 auto aliceBalance = env.
balance(alice);
335 auto bobBalance = env.
balance(bob);
336 auto carolBalance = env.
balance(carol);
338 auto const sendAmt =
XRP(100);
339 auto const feeAmt =
XRP(10);
342 BEAST_EXPECT(env.
balance(alice) == aliceBalance - sendAmt);
343 BEAST_EXPECT(env.
balance(bob) == bobBalance - feeAmt);
344 BEAST_EXPECT(env.
balance(carol) == carolBalance + sendAmt);
349 auto aliceBalance = env.
balance(alice);
350 auto bobBalance = env.
balance(bob);
351 auto carolBalance = env.
balance(carol);
353 env(
pay(alice, carol,
XRP(100)),
358 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
359 BEAST_EXPECT(env.
balance(bob) == bobBalance);
360 BEAST_EXPECT(env.
balance(carol) == carolBalance);
366 auto aliceBalance = env.
balance(alice);
367 auto bobBalance = env.
balance(bob);
368 auto carolBalance = env.
balance(carol);
369 auto const feeAmt =
XRP(10);
371 env(
pay(alice, carol,
XRP(20000)),
376 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
377 BEAST_EXPECT(env.
balance(bob) == bobBalance - feeAmt);
378 BEAST_EXPECT(env.
balance(carol) == carolBalance);
392 env.
fund(
XRP(10000), alice, bob, carol);
395 auto aliceSeq = env.
seq(alice);
396 auto bobSeq = env.
seq(bob);
400 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
401 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
402 aliceSeq = env.
seq(alice);
403 bobSeq = env.
seq(bob);
405 for (
auto i = 0; i < 20; ++i)
410 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
411 BEAST_EXPECT(env.
seq(bob) == bobSeq);
412 aliceSeq = env.
seq(alice);
416 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
417 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
418 bobSeq = env.
seq(bob);
423 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
424 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
425 bobSeq = env.
seq(bob);
429 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
430 BEAST_EXPECT(env.
seq(bob) == bobSeq);
431 aliceSeq = env.
seq(alice);
444 env.
fund(
XRP(100000), alice, bob);
455 auto const aliceBalance = env.
balance(alice);
456 auto const bobBalance = env.
balance(bob);
459 auto const deleteFee =
drops(env.
current()->fees().increment);
465 BEAST_EXPECT(env.
balance(bob) == bobBalance + aliceBalance - deleteFee);
474 testcase(
"test delegate transaction");
550 auto const USD = gw[
"USD"];
551 auto const EUR = gw2[
"EUR"];
556 env.
trust(USD(200), alice);
557 env.
trust(EUR(400), gw);
567 env(
pay(gw, alice, USD(50)),
580 env(
pay(gw, alice, USD(50)),
597 env(
pay(gw, alice,
XRP(50)),
611 BEAST_EXPECT(env.
balance(bob, USD) == USD(0));
621 BEAST_EXPECT(env.
balance(bob, USD) == USD(0));
639 env(
pay(gw2, gw, EUR(200)));
663 auto const USD = gw[
"USD"];
668 env.
trust(USD(200), alice);
685 env(
pay(gw, alice, USD(50)),
706 BEAST_EXPECT(env.
balance(bob, USD) == USD(0));
713 testcase(
"test TrustSet granular permissions");
722 env.
fund(
XRP(10000), gw, alice, bob);
730 env(
trust(alice, gw[
"USD"](50)),
736 env(
trust(alice, gw[
"USD"](50)));
784 gw, bob, {
"TrustlineAuthorize",
"TrustlineFreeze"}));
789 gw, bob, {
"TrustlineAuthorize",
"TrustlineUnfreeze"}));
802 env(
trust(alice, gw[
"USD"](100)),
805 env(
trust(gw, alice[
"USD"](100)),
810 auto tx =
trust(alice, gw[
"USD"](50));
811 tx[
"QualityIn"] =
"1000";
813 auto tx2 =
trust(alice, gw[
"USD"](50));
814 tx2[
"QualityOut"] =
"1000";
816 auto tx3 =
trust(gw, alice[
"USD"](50));
817 tx3[
"QualityIn"] =
"1000";
819 auto tx4 =
trust(gw, alice[
"USD"](50));
820 tx4[
"QualityOut"] =
"1000";
826 auto tx5 =
trust(gw, alice[
"USD"](50));
827 tx5[
"QualityOut"] =
"1000";
829 auto tx6 =
trust(alice, gw[
"USD"](50));
830 tx6[
"QualityOut"] =
"1000";
843 env.
fund(
XRP(10000), gw, alice, bob);
848 env(
trust(alice, gw[
"USD"](50)),
852 alice, bob, {
"TrustlineUnfreeze",
"NFTokenCreateOffer"}));
855 env(
trust(alice, gw[
"USD"](50)),
863 {
"TrustlineUnfreeze",
864 "NFTokenCreateOffer",
866 "AccountTransferRateSet"}));
874 {
"TrustlineUnfreeze",
875 "NFTokenCreateOffer",
877 "AccountTransferRateSet"}));
901 testcase(
"test AccountSet granular permissions");
909 auto const alice =
Account{
"alice"};
910 auto const bob =
Account{
"bob"};
911 env.
fund(
XRP(10000), alice, bob);
922 auto jt =
noop(alice);
923 jt[sfDomain.fieldName] =
strHex(domain);
924 jt[sfDelegate.fieldName] = bob.human();
930 alice, bob, {
"TrustlineUnfreeze",
"AccountEmailHashSet"}));
940 BEAST_EXPECT((*env.
le(alice))[sfDomain] ==
makeSlice(domain));
943 jt[sfDomain.fieldName] =
"";
945 BEAST_EXPECT(!env.
le(alice)->isFieldPresent(sfDomain));
949 std::string const failDomain =
"fail_domain_update";
951 jt[sfDomain.fieldName] =
strHex(failDomain);
958 jt[sfDomain.fieldName] =
strHex(domain);
959 std::string const mh(
"5F31A79367DC3137FADA860C05742EE6");
960 jt[sfEmailHash.fieldName] = mh;
965 alice, bob, {
"AccountDomainSet",
"AccountEmailHashSet"}));
968 BEAST_EXPECT(
to_string((*env.
le(alice))[sfEmailHash]) == mh);
969 BEAST_EXPECT((*env.
le(alice))[sfDomain] ==
makeSlice(domain));
973 jt[sfMessageKey.fieldName] =
strHex(rkp.first.slice());
981 "AccountEmailHashSet",
982 "AccountMessageKeySet"}));
988 strHex((*env.
le(alice))[sfMessageKey]) ==
989 strHex(rkp.first.slice()));
990 jt[sfMessageKey.fieldName] =
"";
992 BEAST_EXPECT(!env.
le(alice)->isFieldPresent(sfMessageKey));
1001 {
"AccountDomainSet",
1002 "AccountEmailHashSet",
1003 "AccountMessageKeySet",
1004 "AccountTransferRateSet"}));
1006 auto jtRate =
rate(alice, 2.0);
1007 jtRate[sfDelegate.fieldName] = bob.human();
1010 BEAST_EXPECT((*env.
le(alice))[sfTransferRate] == 2000000000);
1013 jt[sfTickSize.fieldName] = 8;
1020 {
"AccountDomainSet",
1021 "AccountEmailHashSet",
1022 "AccountMessageKeySet",
1023 "AccountTransferRateSet",
1024 "AccountTickSizeSet"}));
1027 BEAST_EXPECT((*env.
le(alice))[sfTickSize] == 8);
1048 jt[sfTickSize.fieldName] = 7;
1054 {
"AccountDomainSet",
1055 "AccountEmailHashSet",
1056 "AccountMessageKeySet"}));
1061 "9633EC8AF54F16B5286DB1D7B519EF49EEFC050C0C8AC4384F1D88ACD1BFDF"
1063 auto jt2 =
noop(alice);
1064 jt2[sfDomain.fieldName] =
strHex(domain);
1065 jt2[sfDelegate.fieldName] = bob.human();
1066 jt2[sfWalletLocator.fieldName] = locator;
1074 auto const alice =
Account{
"alice"};
1075 auto const bob =
Account{
"bob"};
1076 env.
fund(
XRP(10000), alice, bob);
1081 env(
fset(alice, flag),
1085 env(
fset(alice, flag));
1102 {
"AccountDomainSet",
1103 "AccountEmailHashSet",
1104 "AccountMessageKeySet"}));
1123 BEAST_EXPECT(env.
le(alice)->isFieldPresent(sfAccountTxnID));
1130 jt[sfDelegate.fieldName] = bob.human();
1131 jt[sfNFTokenMinter.fieldName] = bob.human();
1138 {
"AccountDomainSet",
1139 "AccountEmailHashSet",
1140 "AccountMessageKeySet"}));
1159 env(
regkey(bob, bobKey));
1171 testcase(
"test MPTokenIssuanceSet granular");
1172 using namespace jtx;
1179 env.
fund(
XRP(100000), alice, bob);
1206 mpt.set({.account = alice, .flags =
tfMPTLock, .delegate = bob});
1215 alice, bob, {
"MPTokenIssuanceLock",
"MPTokenIssuanceUnlock"}));
1217 mpt.set({.account = alice, .flags =
tfMPTUnlock, .delegate = bob});
1218 mpt.set({.account = alice, .flags =
tfMPTLock, .delegate = bob});
1227 env.
fund(
XRP(100000), alice, bob);
1238 mpt.set({.account = alice, .flags =
tfMPTLock, .delegate = bob});
1251 {
"NFTokenMint",
"MPTokenIssuanceLock",
"NFTokenBurn"}));
1265 "MPTokenIssuanceLock",
1267 "MPTokenIssuanceSet"}));
1268 mpt.set({.account = alice, .flags =
tfMPTUnlock, .delegate = bob});
1270 mpt.set({.account = alice, .flags =
tfMPTLock});
1271 mpt.set({.account = alice, .flags =
tfMPTUnlock, .delegate = bob});
1272 mpt.set({.account = alice, .flags =
tfMPTLock, .delegate = bob});
1280 using namespace jtx;
1286 env.
fund(
XRP(100000), alice, bob, carol);
1292 auto aliceBalance = env.
balance(alice);
1293 auto bobBalance = env.
balance(bob);
1294 auto carolBalance = env.
balance(carol);
1296 env(
pay(alice, carol,
XRP(100)),
1301 BEAST_EXPECT(env.
balance(alice) == aliceBalance -
XRP(100));
1302 BEAST_EXPECT(env.
balance(bob) == bobBalance -
XRP(10));
1303 BEAST_EXPECT(env.
balance(carol) == carolBalance +
XRP(100));
1309 testcase(
"test single sign with bad secret");
1310 using namespace jtx;
1316 env.
fund(
XRP(100000), alice, bob, carol);
1322 auto aliceBalance = env.
balance(alice);
1323 auto bobBalance = env.
balance(bob);
1324 auto carolBalance = env.
balance(carol);
1326 env(
pay(alice, carol,
XRP(100)),
1332 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
1333 BEAST_EXPECT(env.
balance(bob) == bobBalance);
1334 BEAST_EXPECT(env.
balance(carol) == carolBalance);
1341 using namespace jtx;
1349 env.
fund(
XRP(100000), alice, bob, carol, daria, edward);
1352 env(
signers(bob, 2, {{daria, 1}, {edward, 1}}));
1358 auto aliceBalance = env.
balance(alice);
1359 auto bobBalance = env.
balance(bob);
1360 auto carolBalance = env.
balance(carol);
1361 auto dariaBalance = env.
balance(daria);
1362 auto edwardBalance = env.
balance(edward);
1364 env(
pay(alice, carol,
XRP(100)),
1367 msig(daria, edward));
1369 BEAST_EXPECT(env.
balance(alice) == aliceBalance -
XRP(100));
1370 BEAST_EXPECT(env.
balance(bob) == bobBalance -
XRP(10));
1371 BEAST_EXPECT(env.
balance(carol) == carolBalance +
XRP(100));
1372 BEAST_EXPECT(env.
balance(daria) == dariaBalance);
1373 BEAST_EXPECT(env.
balance(edward) == edwardBalance);
1379 testcase(
"test multi sign which does not meet quorum");
1380 using namespace jtx;
1389 env.
fund(
XRP(100000), alice, bob, carol, daria, edward, fred);
1392 env(
signers(bob, 3, {{daria, 1}, {edward, 1}, {fred, 1}}));
1398 auto aliceBalance = env.
balance(alice);
1399 auto bobBalance = env.
balance(bob);
1400 auto carolBalance = env.
balance(carol);
1401 auto dariaBalance = env.
balance(daria);
1402 auto edwardBalance = env.
balance(edward);
1404 env(
pay(alice, carol,
XRP(100)),
1407 msig(daria, edward),
1410 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
1411 BEAST_EXPECT(env.
balance(bob) == bobBalance);
1412 BEAST_EXPECT(env.
balance(carol) == carolBalance);
1413 BEAST_EXPECT(env.
balance(daria) == dariaBalance);
1414 BEAST_EXPECT(env.
balance(edward) == edwardBalance);
1438BEAST_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