rippled
Loading...
Searching...
No Matches
Regression_test.cpp
1#include <test/jtx.h>
2#include <test/jtx/check.h>
3#include <test/jtx/envconfig.h>
4
5#include <xrpld/app/ledger/LedgerMaster.h>
6#include <xrpld/app/tx/apply.h>
7
8#include <xrpl/basics/CountedObject.h>
9#include <xrpl/basics/StringUtilities.h>
10#include <xrpl/json/json_reader.h>
11#include <xrpl/protocol/Indexes.h>
12#include <xrpl/protocol/jss.h>
13
14namespace ripple {
15namespace test {
16
18{
19 // OfferCreate, then OfferCreate with cancel
20 void
22 {
23 using namespace jtx;
24 Env env(*this);
25 auto const gw = Account("gw");
26 auto const USD = gw["USD"];
27 env.fund(XRP(10000), "alice", gw);
28 env(offer("alice", USD(10), XRP(10)), require(owners("alice", 1)));
29 env(offer("alice", USD(20), XRP(10)),
30 json(R"raw(
31 { "OfferSequence" : 4 }
32 )raw"),
33 require(owners("alice", 1)));
34 }
35
36 void
38 {
39 testcase("Account balance < fee destroys correct amount of XRP");
40 using namespace jtx;
41 Env env(*this);
42 env.memoize("alice");
43
44 // The low balance scenario can not deterministically
45 // be reproduced against an open ledger. Make a local
46 // closed ledger and work with it directly.
47 auto closed = std::make_shared<Ledger>(
49 env.app().config(),
51 env.app().getNodeFamily());
52 auto expectedDrops = INITIAL_XRP;
53 BEAST_EXPECT(closed->info().drops == expectedDrops);
54
55 auto const aliceXRP = 400;
56 auto const aliceAmount = XRP(aliceXRP);
57
58 auto next = std::make_shared<Ledger>(
59 *closed, env.app().timeKeeper().closeTime());
60 {
61 // Fund alice
62 auto const jt = env.jt(pay(env.master, "alice", aliceAmount));
63 OpenView accum(&*next);
64
65 auto const result =
66 ripple::apply(env.app(), accum, *jt.stx, tapNONE, env.journal);
67 BEAST_EXPECT(result.ter == tesSUCCESS);
68 BEAST_EXPECT(result.applied);
69
70 accum.apply(*next);
71 }
72 expectedDrops -= next->fees().base;
73 BEAST_EXPECT(next->info().drops == expectedDrops);
74 {
75 auto const sle = next->read(keylet::account(Account("alice").id()));
76 BEAST_EXPECT(sle);
77 auto balance = sle->getFieldAmount(sfBalance);
78
79 BEAST_EXPECT(balance == aliceAmount);
80 }
81
82 {
83 // Specify the seq manually since the env's open ledger
84 // doesn't know about this account.
85 auto const jt = env.jt(noop("alice"), fee(expectedDrops), seq(2));
86
87 OpenView accum(&*next);
88
89 auto const result =
90 ripple::apply(env.app(), accum, *jt.stx, tapNONE, env.journal);
91 BEAST_EXPECT(result.ter == tecINSUFF_FEE);
92 BEAST_EXPECT(result.applied);
93
94 accum.apply(*next);
95 }
96 {
97 auto const sle = next->read(keylet::account(Account("alice").id()));
98 BEAST_EXPECT(sle);
99 auto balance = sle->getFieldAmount(sfBalance);
100
101 BEAST_EXPECT(balance == XRP(0));
102 }
103 expectedDrops -= aliceXRP * dropsPerXRP;
104 BEAST_EXPECT(next->info().drops == expectedDrops);
105 }
106
107 void
109 {
110 testcase("Signing with a secp256r1 key should fail gracefully");
111 using namespace jtx;
112 Env env(*this);
113
114 // Test case we'll use.
115 auto test256r1key = [&env](Account const& acct) {
116 auto const baseFee = env.current()->fees().base;
117 std::uint32_t const acctSeq = env.seq(acct);
118 Json::Value jsonNoop =
119 env.json(noop(acct), fee(baseFee), seq(acctSeq), sig(acct));
120 JTx jt = env.jt(jsonNoop);
121 jt.fill_sig = false;
122
123 // Random secp256r1 public key generated by
124 // https://kjur.github.io/jsrsasign/sample-ecdsa.html
125 std::string const secp256r1PubKey =
126 "045d02995ec24988d9a2ae06a3733aa35ba0741e87527"
127 "ed12909b60bd458052c944b24cbf5893c3e5be321774e"
128 "5082e11c034b765861d0effbde87423f8476bb2c";
129
130 // Set the key in the JSON.
131 jt.jv["SigningPubKey"] = secp256r1PubKey;
132
133 // Set the same key in the STTx.
134 auto secp256r1Sig = std::make_unique<STTx>(*(jt.stx));
135 auto pubKeyBlob = strUnHex(secp256r1PubKey);
136 assert(pubKeyBlob); // Hex for public key must be valid
137 secp256r1Sig->setFieldVL(sfSigningPubKey, *pubKeyBlob);
138 jt.stx.reset(secp256r1Sig.release());
139
140 env(jt,
141 rpc("invalidTransaction",
142 "fails local checks: Invalid signature."));
143 };
144
145 Account const alice{"alice", KeyType::secp256k1};
146 Account const becky{"becky", KeyType::ed25519};
147
148 env.fund(XRP(10000), alice, becky);
149
150 test256r1key(alice);
151 test256r1key(becky);
152 }
153
154 void
156 {
157 testcase("Autofilled fee should use the escalated fee");
158 using namespace jtx;
159 Env env(*this, envconfig([](std::unique_ptr<Config> cfg) {
160 cfg->section("transaction_queue")
161 .set("minimum_txn_in_ledger_standalone", "3");
162 cfg->FEES.reference_fee = 10;
163 return cfg;
164 }));
165 Env_ss envs(env);
166
167 auto const alice = Account("alice");
168 env.fund(XRP(100000), alice);
169
170 auto params = Json::Value(Json::objectValue);
171 // Max fee = 50k drops
172 params[jss::fee_mult_max] = 5000;
173 std::vector<int> const expectedFees({10, 10, 8889, 13889, 20000});
174
175 // We should be able to submit 5 transactions within
176 // our fee limit.
177 for (int i = 0; i < 5; ++i)
178 {
179 envs(noop(alice), fee(none), seq(none))(params);
180
181 auto tx = env.tx();
182 if (BEAST_EXPECT(tx))
183 {
184 BEAST_EXPECT(tx->getAccountID(sfAccount) == alice.id());
185 BEAST_EXPECT(tx->getTxnType() == ttACCOUNT_SET);
186 auto const fee = tx->getFieldAmount(sfFee);
187 BEAST_EXPECT(fee == drops(expectedFees[i]));
188 }
189 }
190 }
191
192 void
194 {
195 testcase("Fee escalation shouldn't allocate extreme memory");
196 using clock_type = std::chrono::steady_clock;
197 using namespace jtx;
198 using namespace std::chrono_literals;
199
200 Env env(*this, envconfig([](std::unique_ptr<Config> cfg) {
201 auto& s = cfg->section("transaction_queue");
202 s.set("minimum_txn_in_ledger_standalone", "4294967295");
203 s.set("minimum_txn_in_ledger", "4294967295");
204 s.set("target_txn_in_ledger", "4294967295");
205 s.set("normal_consensus_increase_percent", "4294967295");
206
207 return cfg;
208 }));
209
210 env(noop(env.master));
211 // This test will probably fail if any breakpoints are encountered,
212 // but should pass on even the slowest machines.
213 auto const start = clock_type::now();
214 env.close();
215 BEAST_EXPECT(clock_type::now() - start < 1s);
216 }
217
218 void
220 {
221 using namespace jtx;
222 using boost::asio::buffer;
223 testcase("jsonInvalid");
224
225 std::string const request =
226 R"json({"command":"path_find","id":19,"subcommand":"create","source_account":"rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh","destination_account":"rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh","destination_amount":"1000000","source_currencies":[{"currency":"0000000000000000000000000000000000000000"},{"currency":"0000000000000000000000005553440000000000"},{"currency":"0000000000000000000000004254430000000000"},{"issuer":"rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh","currency":"0000000000000000000000004254430000000000"},{"issuer":"rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh","currency":"0000000000000000000000004254430000000000"},{"issuer":"rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh","currency":"0000000000000000000000004555520000000000"},{"currency":"0000000000000000000000004554480000000000"},{"currency":"0000000000000000000000004A50590000000000"},{"issuer":"rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh","currency":"000000000000000000000000434E590000000000"},{"currency":"0000000000000000000000004742490000000000"},{"issuer":"rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh","currency":"0000000000000000000000004341440000000000"}]})json";
227
228 Json::Value jvRequest;
229 Json::Reader jrReader;
230
232 buffers.emplace_back(buffer(request, 1024));
233 buffers.emplace_back(
234 buffer(request.data() + 1024, request.length() - 1024));
235 BEAST_EXPECT(
236 jrReader.parse(jvRequest, buffers) && jvRequest.isObject());
237 }
238
239 void
241 {
242 testcase("Invalid Transaction Object ID Type");
243 // Crasher bug introduced in 2.0.1. Fixed in 2.3.0.
244
245 using namespace jtx;
246 Env env(*this);
247
248 Account alice("alice");
249 Account bob("bob");
250 env.fund(XRP(10'000), alice, bob);
251 env.close();
252
253 {
254 auto const alice_index = keylet::account(alice).key;
255 if (BEAST_EXPECT(alice_index.isNonZero()))
256 {
257 env(check::cash(
258 alice, alice_index, check::DeliverMin(XRP(100))),
260 }
261 }
262
263 {
264 auto const bob_index = keylet::account(bob).key;
265
266 auto const digest = [&]() -> std::optional<uint256> {
267 auto const& state =
268 env.app().getLedgerMaster().getClosedLedger()->stateMap();
270 if (!state.peekItem(bob_index, digest))
271 return std::nullopt;
272 return digest.as_uint256();
273 }();
274
275 auto const mapCounts = [&](CountedObjects::List const& list) {
277 for (auto const& e : list)
278 {
279 result[e.first] = e.second;
280 }
281
282 return result;
283 };
284
285 if (BEAST_EXPECT(bob_index.isNonZero()) &&
286 BEAST_EXPECT(digest.has_value()))
287 {
288 auto& cache = env.app().cachedSLEs();
289 cache.del(*digest, false);
290 auto const beforeCounts =
291 mapCounts(CountedObjects::getInstance().getCounts(0));
292
293 env(check::cash(alice, bob_index, check::DeliverMin(XRP(100))),
295
296 auto const afterCounts =
297 mapCounts(CountedObjects::getInstance().getCounts(0));
298
299 using namespace std::string_literals;
300 BEAST_EXPECT(
301 beforeCounts.at("CachedView::hit"s) ==
302 afterCounts.at("CachedView::hit"s));
303 BEAST_EXPECT(
304 beforeCounts.at("CachedView::hitExpired"s) + 1 ==
305 afterCounts.at("CachedView::hitExpired"s));
306 BEAST_EXPECT(
307 beforeCounts.at("CachedView::miss"s) ==
308 afterCounts.at("CachedView::miss"s));
309 }
310 }
311 }
312
313 void
324};
325
326BEAST_DEFINE_TESTSUITE(Regression, app, ripple);
327
328} // namespace test
329} // namespace ripple
Unserialize a JSON document into a Value.
Definition json_reader.h:20
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
Represents a JSON value.
Definition json_value.h:130
bool isObject() const
A testsuite class.
Definition suite.h:52
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:152
virtual CachedSLEs & cachedSLEs()=0
virtual Config & config()=0
virtual TimeKeeper & timeKeeper()=0
virtual Family & getNodeFamily()=0
virtual LedgerMaster & getLedgerMaster()=0
static CountedObjects & getInstance() noexcept
std::shared_ptr< Ledger const > getClosedLedger()
Writable ledger view that accumulates state and tx changes.
Definition OpenView.h:46
void apply(TxsRawView &to) const
Apply changes.
Definition OpenView.cpp:109
uint256 const & as_uint256() const
Definition SHAMapHash.h:25
bool del(key_type const &key, bool valid)
time_point closeTime() const
Returns the predicted close time, in network time.
Definition TimeKeeper.h:57
Immutable cryptographic account descriptor.
Definition Account.h:20
A transaction testing environment wrapper.
Definition Env_ss.h:15
A transaction testing environment.
Definition Env.h:102
Json::Value json(JsonValue &&jv, FN const &... fN)
Create JSON from parameters.
Definition Env.h:515
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
Definition Env.cpp:250
std::shared_ptr< STTx const > tx() const
Return the tx data for the last JTx.
Definition Env.cpp:507
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition Env.h:312
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition Env.cpp:103
Account const & master
Definition Env.h:106
JTx jt(JsonValue &&jv, FN const &... fN)
Create a JTx from parameters.
Definition Env.h:489
Application & app()
Definition Env.h:242
beast::Journal const journal
Definition Env.h:143
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition Env.cpp:271
void memoize(Account const &account)
Associate AccountID with account.
Definition Env.cpp:138
A balance matches.
Definition balance.h:20
Set the fee on a JTx.
Definition fee.h:18
Inject raw JSON.
Definition jtx_json.h:14
Match the number of items in the account's owner directory.
Definition owners.h:54
Check a set of conditions.
Definition require.h:47
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition rpc.h:16
Set the regular signature on a JTx.
Definition sig.h:16
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition ter.h:16
T data(T... args)
T emplace_back(T... args)
T is_same_v
@ objectValue
object value (collection of name/value pairs).
Definition json_value.h:26
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:165
Json::Value cash(jtx::Account const &dest, uint256 const &checkId, STAmount const &amount)
Cash a check requiring that a specific amount be delivered.
Definition check.cpp:14
static none_t const none
Definition tags.h:15
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
constexpr XRPAmount dropsPerXRP
Json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
Definition pay.cpp:11
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition envconfig.h:35
Json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
Definition offer.cpp:10
XRP_t const XRP
Converts to XRP Issue or STAmount.
Definition amount.cpp:92
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
std::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
bool set(T &target, std::string const &name, Section const &section)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
constexpr XRPAmount INITIAL_XRP
Configure the native currency.
static Hasher::result_type digest(void const *data, std::size_t size) noexcept
Definition tokens.cpp:138
@ tecNO_ENTRY
Definition TER.h:288
@ tecINSUFF_FEE
Definition TER.h:284
@ tesSUCCESS
Definition TER.h:226
ApplyResult apply(Application &app, OpenView &view, STTx const &tx, ApplyFlags flags, beast::Journal journal)
Apply a transaction to an OpenView.
Definition apply.cpp:127
create_genesis_t const create_genesis
Definition Ledger.cpp:32
@ tapNONE
Definition ApplyView.h:12
T length(T... args)
uint256 key
Definition Keylet.h:21
void run() override
Runs the suite.
Execution context for applying a JSON transaction.
Definition JTx.h:26
std::shared_ptr< STTx const > stx
Definition JTx.h:37
Json::Value jv
Definition JTx.h:27
Type used to specify DeliverMin for cashing a check.
Definition check.h:21
Set the sequence number on a JTx.
Definition seq.h:15