featureDisallowIncoming: Opt-out of incoming Checks, PayChans, NFTokenOffers and Trustlines (#4336)

featureDisallowIncoming is a new amendment that would allow users to opt-out of incoming Checks, Payment Channels, NFTokenOffers, and trust lines. This commit includes tests.

Adds four new AccountSet Flags:
1. asfDisallowIncomingNFTOffer
2. asfDisallowIncomingCheck
3. asfDisallowIncomingPayChan
4. asfDisallowIncomingTrustline
This commit is contained in:
RichardAH
2022-12-20 02:35:35 +01:00
committed by Richard Holland
parent 167a7b3a5b
commit 3284ab1804
14 changed files with 642 additions and 99 deletions

View File

@@ -32,6 +32,8 @@ namespace ripple {
namespace test {
struct PayChan_test : public beast::unit_test::suite
{
FeatureBitset const disallowIncoming{featureDisallowIncoming};
static uint256
channel(
jtx::Account const& account,
@@ -175,12 +177,12 @@ struct PayChan_test : public beast::unit_test::suite
}
void
testSimple()
testSimple(FeatureBitset features)
{
testcase("simple");
using namespace jtx;
using namespace std::literals::chrono_literals;
Env env(*this);
Env env{*this, features};
auto const alice = Account("alice");
auto const bob = Account("bob");
auto USDA = alice["USD"];
@@ -350,7 +352,91 @@ struct PayChan_test : public beast::unit_test::suite
}
void
testCancelAfter()
testDisallowIncoming(FeatureBitset features)
{
testcase("Disallow Incoming Flag");
using namespace jtx;
// test flag doesn't set unless amendment enabled
{
Env env{*this, features - disallowIncoming};
Account const alice{"alice"};
env.fund(XRP(10000), alice);
env(fset(alice, asfDisallowIncomingPayChan));
env.close();
auto const sle = env.le(alice);
uint32_t flags = sle->getFlags();
BEAST_EXPECT(!(flags & lsfDisallowIncomingPayChan));
}
using namespace std::literals::chrono_literals;
Env env{*this, features | disallowIncoming};
auto const alice = Account("alice");
auto const bob = Account("bob");
auto const cho = Account("cho");
env.fund(XRP(10000), alice, bob, cho);
auto const pk = alice.pk();
auto const settleDelay = 100s;
// set flag on bob only
env(fset(bob, asfDisallowIncomingPayChan));
env.close();
// channel creation from alice to bob is disallowed
{
auto const chan = channel(alice, bob, env.seq(alice));
env(create(alice, bob, XRP(1000), settleDelay, pk),
ter(tecNO_PERMISSION));
BEAST_EXPECT(!channelExists(*env.current(), chan));
}
// set flag on alice also
env(fset(alice, asfDisallowIncomingPayChan));
env.close();
// channel creation from bob to alice is now disallowed
{
auto const chan = channel(bob, alice, env.seq(bob));
env(create(bob, alice, XRP(1000), settleDelay, pk),
ter(tecNO_PERMISSION));
BEAST_EXPECT(!channelExists(*env.current(), chan));
}
// remove flag from bob
env(fclear(bob, asfDisallowIncomingPayChan));
env.close();
// now the channel between alice and bob can exist
{
auto const chan = channel(alice, bob, env.seq(alice));
env(create(alice, bob, XRP(1000), settleDelay, pk),
ter(tesSUCCESS));
BEAST_EXPECT(channelExists(*env.current(), chan));
}
// a channel from cho to alice isn't allowed
{
auto const chan = channel(cho, alice, env.seq(cho));
env(create(cho, alice, XRP(1000), settleDelay, pk),
ter(tecNO_PERMISSION));
BEAST_EXPECT(!channelExists(*env.current(), chan));
}
// remove flag from alice
env(fclear(alice, asfDisallowIncomingPayChan));
env.close();
// now a channel from cho to alice is allowed
{
auto const chan = channel(cho, alice, env.seq(cho));
env(create(cho, alice, XRP(1000), settleDelay, pk),
ter(tesSUCCESS));
BEAST_EXPECT(channelExists(*env.current(), chan));
}
}
void
testCancelAfter(FeatureBitset features)
{
testcase("cancel after");
using namespace jtx;
@@ -360,7 +446,7 @@ struct PayChan_test : public beast::unit_test::suite
auto const carol = Account("carol");
{
// If dst claims after cancel after, channel closes
Env env(*this);
Env env{*this, features};
env.fund(XRP(10000), alice, bob);
auto const pk = alice.pk();
auto const settleDelay = 100s;
@@ -392,7 +478,7 @@ struct PayChan_test : public beast::unit_test::suite
}
{
// Third party can close after cancel after
Env env(*this);
Env env{*this, features};
env.fund(XRP(10000), alice, bob, carol);
auto const pk = alice.pk();
auto const settleDelay = 100s;
@@ -415,12 +501,12 @@ struct PayChan_test : public beast::unit_test::suite
}
void
testExpiration()
testExpiration(FeatureBitset features)
{
testcase("expiration");
using namespace jtx;
using namespace std::literals::chrono_literals;
Env env(*this);
Env env{*this, features};
auto const alice = Account("alice");
auto const bob = Account("bob");
auto const carol = Account("carol");
@@ -481,12 +567,12 @@ struct PayChan_test : public beast::unit_test::suite
}
void
testSettleDelay()
testSettleDelay(FeatureBitset features)
{
testcase("settle delay");
using namespace jtx;
using namespace std::literals::chrono_literals;
Env env(*this);
Env env{*this, features};
auto const alice = Account("alice");
auto const bob = Account("bob");
env.fund(XRP(10000), alice, bob);
@@ -541,12 +627,12 @@ struct PayChan_test : public beast::unit_test::suite
}
void
testCloseDry()
testCloseDry(FeatureBitset features)
{
testcase("close dry");
using namespace jtx;
using namespace std::literals::chrono_literals;
Env env(*this);
Env env{*this, features};
auto const alice = Account("alice");
auto const bob = Account("bob");
env.fund(XRP(10000), alice, bob);
@@ -575,13 +661,13 @@ struct PayChan_test : public beast::unit_test::suite
}
void
testDefaultAmount()
testDefaultAmount(FeatureBitset features)
{
// auth amount defaults to balance if not present
testcase("default amount");
using namespace jtx;
using namespace std::literals::chrono_literals;
Env env(*this);
Env env{*this, features};
auto const alice = Account("alice");
auto const bob = Account("bob");
env.fund(XRP(10000), alice, bob);
@@ -630,7 +716,7 @@ struct PayChan_test : public beast::unit_test::suite
}
void
testDisallowXRP()
testDisallowXRP(FeatureBitset features)
{
// auth amount defaults to balance if not present
testcase("Disallow XRP");
@@ -641,7 +727,7 @@ struct PayChan_test : public beast::unit_test::suite
auto const bob = Account("bob");
{
// Create a channel where dst disallows XRP
Env env(*this, supported_amendments() - featureDepositAuth);
Env env(*this, features - featureDepositAuth);
env.fund(XRP(10000), alice, bob);
env(fset(bob, asfDisallowXRP));
auto const chan = channel(alice, bob, env.seq(alice));
@@ -652,7 +738,7 @@ struct PayChan_test : public beast::unit_test::suite
{
// Create a channel where dst disallows XRP. Ignore that flag,
// since it's just advisory.
Env env(*this);
Env env{*this, features};
env.fund(XRP(10000), alice, bob);
env(fset(bob, asfDisallowXRP));
auto const chan = channel(alice, bob, env.seq(alice));
@@ -663,7 +749,7 @@ struct PayChan_test : public beast::unit_test::suite
{
// Claim to a channel where dst disallows XRP
// (channel is created before disallow xrp is set)
Env env(*this, supported_amendments() - featureDepositAuth);
Env env(*this, features - featureDepositAuth);
env.fund(XRP(10000), alice, bob);
auto const chan = channel(alice, bob, env.seq(alice));
env(create(alice, bob, XRP(1000), 3600s, alice.pk()));
@@ -677,7 +763,7 @@ struct PayChan_test : public beast::unit_test::suite
// Claim to a channel where dst disallows XRP (channel is
// created before disallow xrp is set). Ignore that flag
// since it is just advisory.
Env env(*this);
Env env{*this, features};
env.fund(XRP(10000), alice, bob);
auto const chan = channel(alice, bob, env.seq(alice));
env(create(alice, bob, XRP(1000), 3600s, alice.pk()));
@@ -690,14 +776,14 @@ struct PayChan_test : public beast::unit_test::suite
}
void
testDstTag()
testDstTag(FeatureBitset features)
{
// auth amount defaults to balance if not present
testcase("Dst Tag");
using namespace jtx;
using namespace std::literals::chrono_literals;
// Create a channel where dst disallows XRP
Env env(*this);
Env env{*this, features};
auto const alice = Account("alice");
auto const bob = Account("bob");
env.fund(XRP(10000), alice, bob);
@@ -720,7 +806,7 @@ struct PayChan_test : public beast::unit_test::suite
}
void
testDepositAuth()
testDepositAuth(FeatureBitset features)
{
testcase("Deposit Authorization");
using namespace jtx;
@@ -731,7 +817,7 @@ struct PayChan_test : public beast::unit_test::suite
auto const carol = Account("carol");
auto USDA = alice["USD"];
{
Env env(*this);
Env env{*this, features};
env.fund(XRP(10000), alice, bob, carol);
env(fset(bob, asfDepositAuth));
@@ -844,13 +930,13 @@ struct PayChan_test : public beast::unit_test::suite
}
void
testMultiple()
testMultiple(FeatureBitset features)
{
// auth amount defaults to balance if not present
testcase("Multiple channels to the same account");
using namespace jtx;
using namespace std::literals::chrono_literals;
Env env(*this);
Env env{*this, features};
auto const alice = Account("alice");
auto const bob = Account("bob");
env.fund(XRP(10000), alice, bob);
@@ -867,13 +953,13 @@ struct PayChan_test : public beast::unit_test::suite
}
void
testAccountChannelsRPC()
testAccountChannelsRPC(FeatureBitset features)
{
testcase("AccountChannels RPC");
using namespace jtx;
using namespace std::literals::chrono_literals;
Env env(*this);
Env env{*this, features};
auto const alice = Account("alice");
auto const bob = Account("bob");
auto const charlie = Account("charlie", KeyType::ed25519);
@@ -922,7 +1008,7 @@ struct PayChan_test : public beast::unit_test::suite
}
void
testAccountChannelsRPCMarkers()
testAccountChannelsRPCMarkers(FeatureBitset features)
{
testcase("Account channels RPC markers");
@@ -941,7 +1027,7 @@ struct PayChan_test : public beast::unit_test::suite
return r;
}();
Env env(*this);
Env env{*this, features};
env.fund(XRP(10000), alice);
for (auto const& a : bobs)
{
@@ -1038,7 +1124,7 @@ struct PayChan_test : public beast::unit_test::suite
}
void
testAccountChannelsRPCSenderOnly()
testAccountChannelsRPCSenderOnly(FeatureBitset features)
{
// Check that the account_channels command only returns channels owned
// by the account
@@ -1049,7 +1135,7 @@ struct PayChan_test : public beast::unit_test::suite
auto const alice = Account("alice");
auto const bob = Account("bob");
Env env(*this);
Env env{*this, features};
env.fund(XRP(10000), alice, bob);
// Create a channel from alice to bob and from bob to alice
@@ -1075,12 +1161,12 @@ struct PayChan_test : public beast::unit_test::suite
}
void
testAuthVerifyRPC()
testAuthVerifyRPC(FeatureBitset features)
{
testcase("PayChan Auth/Verify RPC");
using namespace jtx;
using namespace std::literals::chrono_literals;
Env env(*this);
Env env{*this, features};
auto const alice = Account("alice");
auto const bob = Account("bob");
auto const charlie = Account("charlie", KeyType::ed25519);
@@ -1415,12 +1501,12 @@ struct PayChan_test : public beast::unit_test::suite
}
void
testOptionalFields()
testOptionalFields(FeatureBitset features)
{
testcase("Optional Fields");
using namespace jtx;
using namespace std::literals::chrono_literals;
Env env(*this);
Env env{*this, features};
auto const alice = Account("alice");
auto const bob = Account("bob");
auto const carol = Account("carol");
@@ -1466,12 +1552,12 @@ struct PayChan_test : public beast::unit_test::suite
}
void
testMalformedPK()
testMalformedPK(FeatureBitset features)
{
testcase("malformed pk");
using namespace jtx;
using namespace std::literals::chrono_literals;
Env env(*this);
Env env{*this, features};
auto const alice = Account("alice");
auto const bob = Account("bob");
auto USDA = alice["USD"];
@@ -1536,7 +1622,7 @@ struct PayChan_test : public beast::unit_test::suite
}
void
testMetaAndOwnership()
testMetaAndOwnership(FeatureBitset features)
{
testcase("Metadata & Ownership");
@@ -1565,8 +1651,7 @@ struct PayChan_test : public beast::unit_test::suite
{
// Test without adding the paychan to the recipient's owner
// directory
Env env(
*this, supported_amendments() - fixPayChanRecipientOwnerDir);
Env env(*this, features - fixPayChanRecipientOwnerDir);
env.fund(XRP(10000), alice, bob);
env(create(alice, bob, XRP(1000), settleDelay, pk));
env.close();
@@ -1587,7 +1672,7 @@ struct PayChan_test : public beast::unit_test::suite
{
// Test with adding the paychan to the recipient's owner directory
Env env(*this);
Env env{*this, features};
env.fund(XRP(10000), alice, bob);
env(create(alice, bob, XRP(1000), settleDelay, pk));
env.close();
@@ -1609,8 +1694,7 @@ struct PayChan_test : public beast::unit_test::suite
{
// Test removing paychans created before adding to the recipient's
// owner directory
Env env(
*this, supported_amendments() - fixPayChanRecipientOwnerDir);
Env env(*this, features - fixPayChanRecipientOwnerDir);
env.fund(XRP(10000), alice, bob);
// create the channel before the amendment activates
env(create(alice, bob, XRP(1000), settleDelay, pk));
@@ -1644,7 +1728,7 @@ struct PayChan_test : public beast::unit_test::suite
}
void
testAccountDelete()
testAccountDelete(FeatureBitset features)
{
testcase("Account Delete");
using namespace test::jtx;
@@ -1678,8 +1762,8 @@ struct PayChan_test : public beast::unit_test::suite
for (bool const withOwnerDirFix : {false, true})
{
auto const amd = withOwnerDirFix
? supported_amendments()
: supported_amendments() - fixPayChanRecipientOwnerDir;
? features
: features - fixPayChanRecipientOwnerDir;
Env env{*this, amd};
env.fund(XRP(10000), alice, bob, carol);
env.close();
@@ -1771,8 +1855,7 @@ struct PayChan_test : public beast::unit_test::suite
{
// test resurrected account
Env env{
*this, supported_amendments() - fixPayChanRecipientOwnerDir};
Env env{*this, features - fixPayChanRecipientOwnerDir};
env.fund(XRP(10000), alice, bob, carol);
env.close();
auto const feeDrops = env.current()->fees().base;
@@ -1878,12 +1961,12 @@ struct PayChan_test : public beast::unit_test::suite
}
void
testUsingTickets()
testUsingTickets(FeatureBitset features)
{
testcase("using tickets");
using namespace jtx;
using namespace std::literals::chrono_literals;
Env env(*this);
Env env{*this, features};
auto const alice = Account("alice");
auto const bob = Account("bob");
auto USDA = alice["USD"];
@@ -2039,28 +2122,39 @@ struct PayChan_test : public beast::unit_test::suite
BEAST_EXPECT(env.seq(bob) == bobSeq);
}
void
testWithFeats(FeatureBitset features)
{
testSimple(features);
testDisallowIncoming(features);
testCancelAfter(features);
testSettleDelay(features);
testExpiration(features);
testCloseDry(features);
testDefaultAmount(features);
testDisallowXRP(features);
testDstTag(features);
testDepositAuth(features);
testMultiple(features);
testAccountChannelsRPC(features);
testAccountChannelsRPCMarkers(features);
testAccountChannelsRPCSenderOnly(features);
testAuthVerifyRPC(features);
testOptionalFields(features);
testMalformedPK(features);
testMetaAndOwnership(features);
testAccountDelete(features);
testUsingTickets(features);
}
public:
void
run() override
{
testSimple();
testCancelAfter();
testSettleDelay();
testExpiration();
testCloseDry();
testDefaultAmount();
testDisallowXRP();
testDstTag();
testDepositAuth();
testMultiple();
testAccountChannelsRPC();
testAccountChannelsRPCMarkers();
testAccountChannelsRPCSenderOnly();
testAuthVerifyRPC();
testOptionalFields();
testMalformedPK();
testMetaAndOwnership();
testAccountDelete();
testUsingTickets();
using namespace test::jtx;
FeatureBitset const all{supported_amendments()};
testWithFeats(all - disallowIncoming);
testWithFeats(all);
}
};