add remit test

This commit is contained in:
Denis Angell
2023-12-05 11:31:59 +01:00
parent ff6293c955
commit a13e3425dc
5 changed files with 585 additions and 0 deletions

View File

@@ -741,6 +741,7 @@ if (tests)
src/test/app/RCLCensorshipDetector_test.cpp src/test/app/RCLCensorshipDetector_test.cpp
src/test/app/RCLValidations_test.cpp src/test/app/RCLValidations_test.cpp
src/test/app/Regression_test.cpp src/test/app/Regression_test.cpp
src/test/app/Remit_test.cpp
src/test/app/SHAMapStore_test.cpp src/test/app/SHAMapStore_test.cpp
src/test/app/SetAuth_test.cpp src/test/app/SetAuth_test.cpp
src/test/app/SetRegularKey_test.cpp src/test/app/SetRegularKey_test.cpp
@@ -890,6 +891,7 @@ if (tests)
src/test/jtx/impl/rate.cpp src/test/jtx/impl/rate.cpp
src/test/jtx/impl/regkey.cpp src/test/jtx/impl/regkey.cpp
src/test/jtx/impl/reward.cpp src/test/jtx/impl/reward.cpp
src/test/jtx/impl/remit.cpp
src/test/jtx/impl/sendmax.cpp src/test/jtx/impl/sendmax.cpp
src/test/jtx/impl/seq.cpp src/test/jtx/impl/seq.cpp
src/test/jtx/impl/sig.cpp src/test/jtx/impl/sig.cpp

380
src/test/app/Remit_test.cpp Normal file
View File

@@ -0,0 +1,380 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2023 XRPL-Labs
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <ripple/basics/chrono.h>
#include <ripple/core/ConfigSections.h>
#include <ripple/ledger/Directory.h>
#include <ripple/protocol/Feature.h>
#include <ripple/protocol/Indexes.h>
#include <ripple/protocol/TxFlags.h>
#include <ripple/protocol/jss.h>
#include <test/jtx.h>
#include <chrono>
// Destination Exists - Trust Line Exists
// otxn | dest | exists | native | token | tl exists | uris xfr | uri mint |
// A | B | Y | N | N | N | N | N |
// A | B | Y | Y | N | N | N | N |
// A | B | Y | N | Y | Y | N | N |
// A | B | Y | Y | Y | Y | N | N |
// A | B | Y | N | N | N | Y | N |
// A | B | Y | N | N | N | N | Y |
// A | B | Y | Y | N | N | Y | N |
// A | B | Y | Y | Y | Y | Y | N |
// A | B | Y | Y | N | N | Y | Y |
// A | B | Y | Y | Y | Y | Y | Y |
/*
// Destination Exists - Trust Line DNE
// otxn | dest | exists | native | token | tl exists | uris xfr | uri mint |
// A | B | Y | N | Y | N | N | N |
// A | B | Y | Y | Y | N | N | N |
// A | B | Y | Y | Y | N | Y | N |
// A | B | Y | Y | Y | N | Y | Y |
// Destination Does Not Exist - Trust Line Exists
// otxn | dest | exists | native | token | tl exists | uris xfr | uri mint |
// A | B | N | N | N | N | N | N |
// A | B | N | Y | N | N | N | N |
// A | B | N | N | Y | Y | N | N |
// A | B | N | Y | Y | Y | N | N |
// A | B | N | N | N | N | Y | N |
// A | B | N | N | N | N | N | Y |
// A | B | N | Y | N | N | Y | N |
// A | B | N | Y | Y | Y | Y | N |
// A | B | N | Y | N | N | Y | Y |
// A | B | N | Y | Y | Y | Y | Y |
// Destination Exists - Trust Line DNE
// otxn | dest | exists | native | token | tl exists | uris xfr | uri mint |
// A | B | N | N | Y | N | N | N |
// A | B | N | Y | Y | N | N | N |
// A | B | N | Y | Y | N | Y | N |
// A | B | N | Y | Y | N | Y | Y |
*/
namespace ripple {
namespace test {
struct Remit_test : public beast::unit_test::suite
{
void
testEnabled(FeatureBitset features)
{
// 0D8BF22FF7570D58598D1EF19EBB6E142AD46E59A223FD3816262FBB69345BEA
testcase("enabled");
using namespace jtx;
using namespace std::literals::chrono_literals;
// setup env
auto const alice = Account("alice");
auto const bob = Account("bob");
for (bool const withRemit : {true, false})
{
auto const amend =
withRemit ? features : features - featureRemit;
Env env{*this, amend};
env.fund(XRP(1000), alice, bob);
auto const txResult =
withRemit ? ter(tesSUCCESS) : ter(temDISABLED);
// REMIT
env(remit::remit(alice, bob), txResult);
env.close();
}
}
void
testDestExistsTLExists(FeatureBitset features)
{
testcase("dest exists and trustline exists");
using namespace jtx;
using namespace std::literals::chrono_literals;
// setup env
auto const alice = Account("alice");
auto const bob = Account("bob");
auto const gw = Account("gw");
auto const USD = gw["USD"];
Env env{*this, features};
// Env env{*this, envconfig(), amend, nullptr,
// // beast::severities::kWarning
// beast::severities::kTrace
// };
auto const feeDrops = env.current()->fees().base;
env.fund(XRP(1000), alice, bob, gw);
env.close();
env.trust(USD(100000), alice, bob);
env.close();
env(pay(gw, alice, USD(10000)));
env(pay(gw, bob, USD(10000)));
env.close();
// REMIT
{
env(remit::remit(alice, bob), ter(tesSUCCESS));
env.close();
// auto const preAlice = env.balance(alice, USD.issue());
}
// REMIT: XAH
{
auto const preAlice = env.balance(alice);
env(remit::remit(alice, bob),
remit::amts({XRP(1)}),
ter(tesSUCCESS));
env.close();
auto const postAlice = env.balance(alice);
BEAST_EXPECT(postAlice == preAlice + XRP(1) - feeDrops);
}
// REMIT: XAH + USD
{
env(remit::remit(alice, bob),
remit::amts({XRP(1), USD(1)}),
ter(tesSUCCESS));
env.close();
}
// REMIT: URITOKEN XFER
{
// mint uri token
std::string const uri(maxTokenURILength, 'A');
std::string const tid{strHex(uritoken::tokenid(alice, uri))};
env(uritoken::mint(alice, uri), ter(tesSUCCESS));
env.close();
// remit with uritoken id
env(remit::remit(alice, bob),
remit::token_ids({tid}),
ter(tesSUCCESS));
env.close();
}
// REMIT: URITOKEN MINT
{
std::string const uri(maxTokenURILength, 'B');
env(remit::remit(alice, bob), remit::uri(uri), ter(tesSUCCESS));
env.close();
}
// REMIT: XAH + URITOKEN XFER
{
// mint uri token
std::string const uri(maxTokenURILength, 'C');
std::string const tid{strHex(uritoken::tokenid(alice, uri))};
env(uritoken::mint(alice, uri), ter(tesSUCCESS));
env.close();
// remit xah + uritoken id
env(remit::remit(alice, bob),
remit::amts({XRP(1)}),
remit::token_ids({tid}),
ter(tesSUCCESS));
env.close();
}
// REMIT: XAH/USD + URITOKEN XFER
{
// mint uri token
std::string const uri(maxTokenURILength, 'D');
std::string const tid{strHex(uritoken::tokenid(alice, uri))};
env(uritoken::mint(alice, uri), ter(tesSUCCESS));
env.close();
// remit xah/usd + uritoken id
env(remit::remit(alice, bob),
remit::amts({XRP(1), USD(1)}),
remit::token_ids({tid}),
ter(tesSUCCESS));
env.close();
}
// REMIT: XAH + URITOKEN XFER + URITOKEN MINT
{
// mint uri token
std::string const uri1(maxTokenURILength, 'E');
std::string const tid{strHex(uritoken::tokenid(alice, uri1))};
env(uritoken::mint(alice, uri1), ter(tesSUCCESS));
env.close();
// remit xah/usd + uritoken id + uritoken mint
std::string const uri2(maxTokenURILength - 1, 'E');
env(remit::remit(alice, bob),
remit::amts({XRP(1)}),
remit::token_ids({tid}),
remit::uri(uri2),
ter(tesSUCCESS));
env.close();
}
// REMIT: XAH/USD + URITOKEN XFER + URITOKEN MINT
{
// mint uri token
std::string const uri1(maxTokenURILength, 'F');
std::string const tid{strHex(uritoken::tokenid(alice, uri1))};
env(uritoken::mint(alice, uri1), ter(tesSUCCESS));
env.close();
// remit xah/usd + uritoken id + uritoken mint
std::string const uri2(maxTokenURILength - 1, 'F');
env(remit::remit(alice, bob),
remit::amts({XRP(1), USD(1)}),
remit::token_ids({tid}),
remit::uri(uri2),
ter(tesSUCCESS));
env.close();
}
}
void
testDestDoesNotExists(FeatureBitset features)
{
testcase("dest does not exist");
using namespace jtx;
using namespace std::literals::chrono_literals;
// setup env
auto const alice = Account("alice");
auto const bob = Account("bob");
auto const gw = Account("gw");
auto const USD = gw["USD"];
Env env{*this, features};
// Env env{*this, envconfig(), amend, nullptr,
// // beast::severities::kWarning
// beast::severities::kTrace
// };
env.fund(XRP(1000), alice, bob, gw);
env.close();
env.trust(USD(100000), alice);
env.close();
env(pay(gw, alice, USD(10000)));
env.close();
// REMIT No Amounts No URI Tokens
env(remit::remit(alice, bob), ter(tesSUCCESS));
env.close();
// REMIT XAH
env(remit::remit(alice, bob), remit::amts({ XRP(1) }), ter(tesSUCCESS));
env.close();
// // REMIT XAH + USD
// env(remit::remit(alice, bob), remit::amts({ XRP(1), USD(1) }), txResult);
// env.close();
// // MINT
// std::string const uri(maxTokenURILength, '?');
// std::string const tid{strHex(uritoken::tokenid(alice, uri))};
// env(uritoken::mint(alice, uri), txResult);
// env.close();
// // REMIT URI XFER
// env(remit::remit(alice, bob), remit::token_ids({ tid }), txResult);
// env.close();
// // REMIT 2 amount XAH
// env(remit::remit(alice, bob), txResult);
// env.close();
}
void
testTLDoesNotExists(FeatureBitset features)
{
testcase("trust line does not exist");
using namespace jtx;
using namespace std::literals::chrono_literals;
// setup env
auto const alice = Account("alice");
auto const bob = Account("bob");
auto const gw = Account("gw");
auto const USD = gw["USD"];
Env env{*this, features};
// Env env{*this, envconfig(), amend, nullptr,
// // beast::severities::kWarning
// beast::severities::kTrace
// };
env.fund(XRP(1000), alice, bob, gw);
env.close();
env.trust(USD(100000), alice);
env.close();
env(pay(gw, alice, USD(10000)));
env.close();
// REMIT No Amounts No URI Tokens
env(remit::remit(alice, bob), ter(tesSUCCESS));
env.close();
// REMIT XAH
env(remit::remit(alice, bob), remit::amts({ XRP(1) }), ter(tesSUCCESS));
env.close();
// // REMIT XAH + USD
// env(remit::remit(alice, bob), remit::amts({ XRP(1), USD(1) }), txResult);
// env.close();
// // MINT
// std::string const uri(maxTokenURILength, '?');
// std::string const tid{strHex(uritoken::tokenid(alice, uri))};
// env(uritoken::mint(alice, uri), txResult);
// env.close();
// // REMIT URI XFER
// env(remit::remit(alice, bob), remit::token_ids({ tid }), txResult);
// env.close();
// // REMIT 2 amount XAH
// env(remit::remit(alice, bob), txResult);
// env.close();
}
void
testWithFeats(FeatureBitset features)
{
testEnabled(features);
testDestExistsTLExists(features);
}
public:
void
run() override
{
using namespace test::jtx;
auto const sa = supported_amendments();
testWithFeats(sa);
}
};
BEAST_DEFINE_TESTSUITE(Remit, app, ripple);
} // namespace test
} // namespace ripple

View File

@@ -60,6 +60,7 @@
#include <test/jtx/require.h> #include <test/jtx/require.h>
#include <test/jtx/requires.h> #include <test/jtx/requires.h>
#include <test/jtx/reward.h> #include <test/jtx/reward.h>
#include <test/jtx/remit.h>
#include <test/jtx/sendmax.h> #include <test/jtx/sendmax.h>
#include <test/jtx/seq.h> #include <test/jtx/seq.h>
#include <test/jtx/sig.h> #include <test/jtx/sig.h>

View File

@@ -0,0 +1,84 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2023 XRPL Labs
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <ripple/protocol/jss.h>
#include <test/jtx/remit.h>
namespace ripple {
namespace test {
namespace jtx {
namespace remit {
Json::Value
remit(jtx::Account const& account, jtx::Account const& dest)
{
using namespace jtx;
Json::Value jv;
jv[jss::TransactionType] = jss::Remit;
jv[jss::Account] = account.human();
jv[jss::Destination] = dest.human();
return jv;
}
void
amts::operator()(Env& env, JTx& jt) const
{
auto& ja = jt.jv[sfAmounts.getJsonName()];
for (std::size_t i = 0; i < amts_.size(); ++i)
{
ja[i][sfAmountEntry.jsonName] = Json::Value{};
ja[i][sfAmountEntry.jsonName][jss::Amount] =
amts_[i].getJson(JsonOptions::none);
}
jt.jv[sfAmounts.jsonName] = ja;
}
void
blob::operator()(Env& env, JTx& jt) const
{
jt.jv[sfBlob.jsonName] = blob_;
}
void
inform::operator()(Env& env, JTx& jt) const
{
jt.jv[sfInform.jsonName] = inform_.human();
}
void
token_ids::operator()(Env& env, JTx& jt) const
{
for (std::size_t i = 0; i < token_ids_.size(); ++i)
{
jt.jv[sfURITokenIDs.jsonName] = Json::arrayValue;
jt.jv[sfURITokenIDs.jsonName][i] = token_ids_[i];
}
}
void
uri::operator()(Env& env, JTx& jt) const
{
jt.jv[sfMintURIToken.jsonName] = Json::Value{};
jt.jv[sfMintURIToken.jsonName][sfURI.jsonName] = strHex(uri_);;
}
} // namespace remit
} // namespace jtx
} // namespace test
} // namespace ripple

118
src/test/jtx/remit.h Normal file
View File

@@ -0,0 +1,118 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2023 XRPL Labs
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_TEST_JTX_REMIT_H_INCLUDED
#define RIPPLE_TEST_JTX_REMIT_H_INCLUDED
#include <ripple/protocol/STAmount.h>
#include <test/jtx/Account.h>
#include <test/jtx/Env.h>
namespace ripple {
namespace test {
namespace jtx {
namespace remit {
Json::Value
remit(jtx::Account const& account, jtx::Account const& dest);
/** Sets the optional Amount on a JTx. */
class amts
{
private:
std::vector<STAmount> amts_;
public:
explicit amts(std::vector<STAmount> const& amts) : amts_(amts)
{
}
void
operator()(Env&, JTx& jtx) const;
};
/** Set the optional "Blob" on a JTx */
class blob
{
private:
std::string blob_;
public:
explicit blob(std::string const& blob) : blob_(blob)
{
}
void
operator()(Env&, JTx& jtx) const;
};
/** Sets the optional "Inform" on a JTx. */
class inform
{
private:
jtx::Account inform_;
public:
explicit inform(jtx::Account const& inform) : inform_(inform)
{
}
void
operator()(Env&, JTx& jtx) const;
};
/** Sets the optional "URITokenIDs" on a JTx. */
class token_ids
{
private:
std::vector<std::string> token_ids_;
public:
explicit token_ids(std::vector<std::string> const& token_ids) : token_ids_(token_ids)
{
}
void
operator()(Env&, JTx& jtx) const;
};
/** Set the optional "sfMintURIToken" on a JTx */
class uri
{
private:
std::string uri_;
public:
explicit uri(std::string const& uri) : uri_(uri)
{
}
void
operator()(Env&, JTx& jtx) const;
};
} // namespace remit
} // namespace jtx
} // namespace test
} // namespace ripple
#endif // RIPPLE_TEST_JTX_REMIT_H_INCLUDED