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"}),
250 drops(env.
current()->fees().accountReserve(1)), bob, carol);
304 env.
fund(
XRP(10000), alice, carol);
312 auto aliceBalance = env.
balance(alice);
313 auto bobBalance = env.
balance(bob);
314 auto carolBalance = env.
balance(carol);
316 env(
pay(alice, carol,
XRP(100)),
321 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
322 BEAST_EXPECT(env.
balance(bob) == bobBalance);
323 BEAST_EXPECT(env.
balance(carol) == carolBalance);
331 auto aliceBalance = env.
balance(alice);
332 auto bobBalance = env.
balance(bob);
333 auto carolBalance = env.
balance(carol);
335 auto const sendAmt =
XRP(100);
336 auto const feeAmt =
XRP(10);
339 BEAST_EXPECT(env.
balance(alice) == aliceBalance - sendAmt);
340 BEAST_EXPECT(env.
balance(bob) == bobBalance - feeAmt);
341 BEAST_EXPECT(env.
balance(carol) == carolBalance + sendAmt);
346 auto aliceBalance = env.
balance(alice);
347 auto bobBalance = env.
balance(bob);
348 auto carolBalance = env.
balance(carol);
350 env(
pay(alice, carol,
XRP(100)),
355 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
356 BEAST_EXPECT(env.
balance(bob) == bobBalance);
357 BEAST_EXPECT(env.
balance(carol) == carolBalance);
363 auto aliceBalance = env.
balance(alice);
364 auto bobBalance = env.
balance(bob);
365 auto carolBalance = env.
balance(carol);
366 auto const feeAmt =
XRP(10);
368 env(
pay(alice, carol,
XRP(20000)),
373 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
374 BEAST_EXPECT(env.
balance(bob) == bobBalance - feeAmt);
375 BEAST_EXPECT(env.
balance(carol) == carolBalance);
389 env.
fund(
XRP(10000), alice, bob, carol);
392 auto aliceSeq = env.
seq(alice);
393 auto bobSeq = env.
seq(bob);
397 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
398 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
399 aliceSeq = env.
seq(alice);
400 bobSeq = env.
seq(bob);
402 for (
auto i = 0; i < 20; ++i)
407 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
408 BEAST_EXPECT(env.
seq(bob) == bobSeq);
409 aliceSeq = env.
seq(alice);
413 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
414 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
415 bobSeq = env.
seq(bob);
420 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
421 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
422 bobSeq = env.
seq(bob);
426 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
427 BEAST_EXPECT(env.
seq(bob) == bobSeq);
428 aliceSeq = env.
seq(alice);
441 env.
fund(
XRP(100000), alice, bob);
452 auto const aliceBalance = env.
balance(alice);
453 auto const bobBalance = env.
balance(bob);
456 auto const deleteFee =
drops(env.
current()->fees().increment);
462 BEAST_EXPECT(env.
balance(bob) == bobBalance + aliceBalance - deleteFee);
471 testcase(
"test delegate transaction");
547 auto const USD = gw[
"USD"];
548 auto const EUR = gw2[
"EUR"];
553 env.
trust(USD(200), alice);
554 env.
trust(EUR(400), gw);
564 env(
pay(gw, alice, USD(50)),
577 env(
pay(gw, alice, USD(50)),
594 env(
pay(gw, alice,
XRP(50)),
608 BEAST_EXPECT(env.
balance(bob, USD) == USD(0));
618 BEAST_EXPECT(env.
balance(bob, USD) == USD(0));
636 env(
pay(gw2, gw, EUR(200)));
660 auto const USD = gw[
"USD"];
665 env.
trust(USD(200), alice);
682 env(
pay(gw, alice, USD(50)),
703 BEAST_EXPECT(env.
balance(bob, USD) == USD(0));
710 testcase(
"test TrustSet granular permissions");
719 env.
fund(
XRP(10000), gw, alice, bob);
727 env(
trust(alice, gw[
"USD"](50)),
733 env(
trust(alice, gw[
"USD"](50)));
781 gw, bob, {
"TrustlineAuthorize",
"TrustlineFreeze"}));
786 gw, bob, {
"TrustlineAuthorize",
"TrustlineUnfreeze"}));
799 env(
trust(alice, gw[
"USD"](100)),
802 env(
trust(gw, alice[
"USD"](100)),
807 auto tx =
trust(alice, gw[
"USD"](50));
808 tx[
"QualityIn"] =
"1000";
810 auto tx2 =
trust(alice, gw[
"USD"](50));
811 tx2[
"QualityOut"] =
"1000";
813 auto tx3 =
trust(gw, alice[
"USD"](50));
814 tx3[
"QualityIn"] =
"1000";
816 auto tx4 =
trust(gw, alice[
"USD"](50));
817 tx4[
"QualityOut"] =
"1000";
823 auto tx5 =
trust(gw, alice[
"USD"](50));
824 tx5[
"QualityOut"] =
"1000";
826 auto tx6 =
trust(alice, gw[
"USD"](50));
827 tx6[
"QualityOut"] =
"1000";
840 env.
fund(
XRP(10000), gw, alice, bob);
845 env(
trust(alice, gw[
"USD"](50)),
849 alice, bob, {
"TrustlineUnfreeze",
"NFTokenCreateOffer"}));
852 env(
trust(alice, gw[
"USD"](50)),
860 {
"TrustlineUnfreeze",
861 "NFTokenCreateOffer",
863 "AccountTransferRateSet"}));
871 {
"TrustlineUnfreeze",
872 "NFTokenCreateOffer",
874 "AccountTransferRateSet"}));
898 testcase(
"test AccountSet granular permissions");
906 auto const alice =
Account{
"alice"};
907 auto const bob =
Account{
"bob"};
908 env.
fund(
XRP(10000), alice, bob);
919 auto jt =
noop(alice);
920 jt[sfDomain.fieldName] =
strHex(domain);
921 jt[sfDelegate.fieldName] = bob.human();
927 alice, bob, {
"TrustlineUnfreeze",
"AccountEmailHashSet"}));
937 BEAST_EXPECT((*env.
le(alice))[sfDomain] ==
makeSlice(domain));
940 jt[sfDomain.fieldName] =
"";
942 BEAST_EXPECT(!env.
le(alice)->isFieldPresent(sfDomain));
946 std::string const failDomain =
"fail_domain_update";
948 jt[sfDomain.fieldName] =
strHex(failDomain);
955 jt[sfDomain.fieldName] =
strHex(domain);
956 std::string const mh(
"5F31A79367DC3137FADA860C05742EE6");
957 jt[sfEmailHash.fieldName] = mh;
962 alice, bob, {
"AccountDomainSet",
"AccountEmailHashSet"}));
965 BEAST_EXPECT(
to_string((*env.
le(alice))[sfEmailHash]) == mh);
966 BEAST_EXPECT((*env.
le(alice))[sfDomain] ==
makeSlice(domain));
970 jt[sfMessageKey.fieldName] =
strHex(rkp.first.slice());
978 "AccountEmailHashSet",
979 "AccountMessageKeySet"}));
985 strHex((*env.
le(alice))[sfMessageKey]) ==
986 strHex(rkp.first.slice()));
987 jt[sfMessageKey.fieldName] =
"";
989 BEAST_EXPECT(!env.
le(alice)->isFieldPresent(sfMessageKey));
999 "AccountEmailHashSet",
1000 "AccountMessageKeySet",
1001 "AccountTransferRateSet"}));
1003 auto jtRate =
rate(alice, 2.0);
1004 jtRate[sfDelegate.fieldName] = bob.human();
1007 BEAST_EXPECT((*env.
le(alice))[sfTransferRate] == 2000000000);
1010 jt[sfTickSize.fieldName] = 8;
1017 {
"AccountDomainSet",
1018 "AccountEmailHashSet",
1019 "AccountMessageKeySet",
1020 "AccountTransferRateSet",
1021 "AccountTickSizeSet"}));
1024 BEAST_EXPECT((*env.
le(alice))[sfTickSize] == 8);
1045 jt[sfTickSize.fieldName] = 7;
1051 {
"AccountDomainSet",
1052 "AccountEmailHashSet",
1053 "AccountMessageKeySet"}));
1058 "9633EC8AF54F16B5286DB1D7B519EF49EEFC050C0C8AC4384F1D88ACD1BFDF"
1060 auto jt2 =
noop(alice);
1061 jt2[sfDomain.fieldName] =
strHex(domain);
1062 jt2[sfDelegate.fieldName] = bob.human();
1063 jt2[sfWalletLocator.fieldName] = locator;
1071 auto const alice =
Account{
"alice"};
1072 auto const bob =
Account{
"bob"};
1073 env.
fund(
XRP(10000), alice, bob);
1078 env(
fset(alice, flag),
1082 env(
fset(alice, flag));
1099 {
"AccountDomainSet",
1100 "AccountEmailHashSet",
1101 "AccountMessageKeySet"}));
1120 BEAST_EXPECT(env.
le(alice)->isFieldPresent(sfAccountTxnID));
1127 jt[sfDelegate.fieldName] = bob.human();
1128 jt[sfNFTokenMinter.fieldName] = bob.human();
1135 {
"AccountDomainSet",
1136 "AccountEmailHashSet",
1137 "AccountMessageKeySet"}));
1156 env(
regkey(bob, bobKey));
1168 testcase(
"test MPTokenIssuanceSet granular");
1169 using namespace jtx;
1176 env.
fund(
XRP(100000), alice, bob);
1203 mpt.set({.account = alice, .flags =
tfMPTLock, .delegate = bob});
1212 alice, bob, {
"MPTokenIssuanceLock",
"MPTokenIssuanceUnlock"}));
1214 mpt.set({.account = alice, .flags =
tfMPTUnlock, .delegate = bob});
1215 mpt.set({.account = alice, .flags =
tfMPTLock, .delegate = bob});
1224 env.
fund(
XRP(100000), alice, bob);
1235 mpt.set({.account = alice, .flags =
tfMPTLock, .delegate = bob});
1248 {
"NFTokenMint",
"MPTokenIssuanceLock",
"NFTokenBurn"}));
1262 "MPTokenIssuanceLock",
1264 "MPTokenIssuanceSet"}));
1265 mpt.set({.account = alice, .flags =
tfMPTUnlock, .delegate = bob});
1267 mpt.set({.account = alice, .flags =
tfMPTLock});
1268 mpt.set({.account = alice, .flags =
tfMPTUnlock, .delegate = bob});
1269 mpt.set({.account = alice, .flags =
tfMPTLock, .delegate = bob});
1277 using namespace jtx;
1283 env.
fund(
XRP(100000), alice, bob, carol);
1289 auto aliceBalance = env.
balance(alice);
1290 auto bobBalance = env.
balance(bob);
1291 auto carolBalance = env.
balance(carol);
1293 env(
pay(alice, carol,
XRP(100)),
1298 BEAST_EXPECT(env.
balance(alice) == aliceBalance -
XRP(100));
1299 BEAST_EXPECT(env.
balance(bob) == bobBalance -
XRP(10));
1300 BEAST_EXPECT(env.
balance(carol) == carolBalance +
XRP(100));
1306 testcase(
"test single sign with bad secret");
1307 using namespace jtx;
1313 env.
fund(
XRP(100000), alice, bob, carol);
1319 auto aliceBalance = env.
balance(alice);
1320 auto bobBalance = env.
balance(bob);
1321 auto carolBalance = env.
balance(carol);
1323 env(
pay(alice, carol,
XRP(100)),
1329 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
1330 BEAST_EXPECT(env.
balance(bob) == bobBalance);
1331 BEAST_EXPECT(env.
balance(carol) == carolBalance);
1338 using namespace jtx;
1346 env.
fund(
XRP(100000), alice, bob, carol, daria, edward);
1349 env(
signers(bob, 2, {{daria, 1}, {edward, 1}}));
1355 auto aliceBalance = env.
balance(alice);
1356 auto bobBalance = env.
balance(bob);
1357 auto carolBalance = env.
balance(carol);
1358 auto dariaBalance = env.
balance(daria);
1359 auto edwardBalance = env.
balance(edward);
1361 env(
pay(alice, carol,
XRP(100)),
1364 msig(daria, edward));
1366 BEAST_EXPECT(env.
balance(alice) == aliceBalance -
XRP(100));
1367 BEAST_EXPECT(env.
balance(bob) == bobBalance -
XRP(10));
1368 BEAST_EXPECT(env.
balance(carol) == carolBalance +
XRP(100));
1369 BEAST_EXPECT(env.
balance(daria) == dariaBalance);
1370 BEAST_EXPECT(env.
balance(edward) == edwardBalance);
1376 testcase(
"test multi sign which does not meet quorum");
1377 using namespace jtx;
1386 env.
fund(
XRP(100000), alice, bob, carol, daria, edward, fred);
1389 env(
signers(bob, 3, {{daria, 1}, {edward, 1}, {fred, 1}}));
1395 auto aliceBalance = env.
balance(alice);
1396 auto bobBalance = env.
balance(bob);
1397 auto carolBalance = env.
balance(carol);
1398 auto dariaBalance = env.
balance(daria);
1399 auto edwardBalance = env.
balance(edward);
1401 env(
pay(alice, carol,
XRP(100)),
1404 msig(daria, edward),
1407 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
1408 BEAST_EXPECT(env.
balance(bob) == bobBalance);
1409 BEAST_EXPECT(env.
balance(carol) == carolBalance);
1410 BEAST_EXPECT(env.
balance(daria) == dariaBalance);
1411 BEAST_EXPECT(env.
balance(edward) == edwardBalance);
1435BEAST_DEFINE_TESTSUITE(Delegate, app,
ripple);
Value & append(const Value &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