rippled
Loading...
Searching...
No Matches
Regression_test.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012, 2013 Ripple Labs Inc.
5 Permission to use, copy, modify, and/or distribute this software for any
6 purpose with or without fee is hereby granted, provided that the above
7 copyright notice and this permission notice appear in all copies.
8 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15*/
16//==============================================================================
17
18#include <test/jtx.h>
19#include <test/jtx/envconfig.h>
20#include <xrpld/app/tx/apply.h>
21#include <xrpl/basics/StringUtilities.h>
22#include <xrpl/json/json_reader.h>
23#include <xrpl/protocol/Feature.h>
24#include <xrpl/protocol/jss.h>
25
26namespace ripple {
27namespace test {
28
30{
31 // OfferCreate, then OfferCreate with cancel
32 void
34 {
35 using namespace jtx;
36 Env env(*this);
37 auto const gw = Account("gw");
38 auto const USD = gw["USD"];
39 env.fund(XRP(10000), "alice", gw);
40 env(offer("alice", USD(10), XRP(10)), require(owners("alice", 1)));
41 env(offer("alice", USD(20), XRP(10)),
42 json(R"raw(
43 { "OfferSequence" : 4 }
44 )raw"),
45 require(owners("alice", 1)));
46 }
47
48 void
50 {
51 testcase("Account balance < fee destroys correct amount of XRP");
52 using namespace jtx;
53 Env env(*this);
54 env.memoize("alice");
55
56 // The low balance scenario can not deterministically
57 // be reproduced against an open ledger. Make a local
58 // closed ledger and work with it directly.
59 auto closed = std::make_shared<Ledger>(
61 env.app().config(),
63 env.app().getNodeFamily());
64 auto expectedDrops = INITIAL_XRP;
65 BEAST_EXPECT(closed->info().drops == expectedDrops);
66
67 auto const aliceXRP = 400;
68 auto const aliceAmount = XRP(aliceXRP);
69
70 auto next = std::make_shared<Ledger>(
71 *closed, env.app().timeKeeper().closeTime());
72 {
73 // Fund alice
74 auto const jt = env.jt(pay(env.master, "alice", aliceAmount));
75 OpenView accum(&*next);
76
77 auto const result =
78 ripple::apply(env.app(), accum, *jt.stx, tapNONE, env.journal);
79 BEAST_EXPECT(result.first == tesSUCCESS);
80 BEAST_EXPECT(result.second);
81
82 accum.apply(*next);
83 }
84 expectedDrops -= next->fees().base;
85 BEAST_EXPECT(next->info().drops == expectedDrops);
86 {
87 auto const sle = next->read(keylet::account(Account("alice").id()));
88 BEAST_EXPECT(sle);
89 auto balance = sle->getFieldAmount(sfBalance);
90
91 BEAST_EXPECT(balance == aliceAmount);
92 }
93
94 {
95 // Specify the seq manually since the env's open ledger
96 // doesn't know about this account.
97 auto const jt = env.jt(noop("alice"), fee(expectedDrops), seq(2));
98
99 OpenView accum(&*next);
100
101 auto const result =
102 ripple::apply(env.app(), accum, *jt.stx, tapNONE, env.journal);
103 BEAST_EXPECT(result.first == tecINSUFF_FEE);
104 BEAST_EXPECT(result.second);
105
106 accum.apply(*next);
107 }
108 {
109 auto const sle = next->read(keylet::account(Account("alice").id()));
110 BEAST_EXPECT(sle);
111 auto balance = sle->getFieldAmount(sfBalance);
112
113 BEAST_EXPECT(balance == XRP(0));
114 }
115 expectedDrops -= aliceXRP * dropsPerXRP;
116 BEAST_EXPECT(next->info().drops == expectedDrops);
117 }
118
119 void
121 {
122 testcase("Signing with a secp256r1 key should fail gracefully");
123 using namespace jtx;
124 Env env(*this);
125
126 // Test case we'll use.
127 auto test256r1key = [&env](Account const& acct) {
128 auto const baseFee = env.current()->fees().base;
129 std::uint32_t const acctSeq = env.seq(acct);
130 Json::Value jsonNoop =
131 env.json(noop(acct), fee(baseFee), seq(acctSeq), sig(acct));
132 JTx jt = env.jt(jsonNoop);
133 jt.fill_sig = false;
134
135 // Random secp256r1 public key generated by
136 // https://kjur.github.io/jsrsasign/sample-ecdsa.html
137 std::string const secp256r1PubKey =
138 "045d02995ec24988d9a2ae06a3733aa35ba0741e87527"
139 "ed12909b60bd458052c944b24cbf5893c3e5be321774e"
140 "5082e11c034b765861d0effbde87423f8476bb2c";
141
142 // Set the key in the JSON.
143 jt.jv["SigningPubKey"] = secp256r1PubKey;
144
145 // Set the same key in the STTx.
146 auto secp256r1Sig = std::make_unique<STTx>(*(jt.stx));
147 auto pubKeyBlob = strUnHex(secp256r1PubKey);
148 assert(pubKeyBlob); // Hex for public key must be valid
149 secp256r1Sig->setFieldVL(sfSigningPubKey, *pubKeyBlob);
150 jt.stx.reset(secp256r1Sig.release());
151
152 env(jt,
153 rpc("invalidTransaction",
154 "fails local checks: Invalid signature."));
155 };
156
157 Account const alice{"alice", KeyType::secp256k1};
158 Account const becky{"becky", KeyType::ed25519};
159
160 env.fund(XRP(10000), alice, becky);
161
162 test256r1key(alice);
163 test256r1key(becky);
164 }
165
166 void
168 {
169 testcase("Autofilled fee should use the escalated fee");
170 using namespace jtx;
171 Env env(*this, envconfig([](std::unique_ptr<Config> cfg) {
172 cfg->section("transaction_queue")
173 .set("minimum_txn_in_ledger_standalone", "3");
174 return cfg;
175 }));
176 Env_ss envs(env);
177
178 auto const alice = Account("alice");
179 env.fund(XRP(100000), alice);
180
181 auto params = Json::Value(Json::objectValue);
182 // Max fee = 50k drops
183 params[jss::fee_mult_max] = 5000;
184 std::vector<int> const expectedFees({10, 10, 8889, 13889, 20000});
185
186 // We should be able to submit 5 transactions within
187 // our fee limit.
188 for (int i = 0; i < 5; ++i)
189 {
190 envs(noop(alice), fee(none), seq(none))(params);
191
192 auto tx = env.tx();
193 if (BEAST_EXPECT(tx))
194 {
195 BEAST_EXPECT(tx->getAccountID(sfAccount) == alice.id());
196 BEAST_EXPECT(tx->getTxnType() == ttACCOUNT_SET);
197 auto const fee = tx->getFieldAmount(sfFee);
198 BEAST_EXPECT(fee == drops(expectedFees[i]));
199 }
200 }
201 }
202
203 void
205 {
206 testcase("Fee escalation shouldn't allocate extreme memory");
207 using clock_type = std::chrono::steady_clock;
208 using namespace jtx;
209 using namespace std::chrono_literals;
210
211 Env env(*this, envconfig([](std::unique_ptr<Config> cfg) {
212 auto& s = cfg->section("transaction_queue");
213 s.set("minimum_txn_in_ledger_standalone", "4294967295");
214 s.set("minimum_txn_in_ledger", "4294967295");
215 s.set("target_txn_in_ledger", "4294967295");
216 s.set("normal_consensus_increase_percent", "4294967295");
217
218 return cfg;
219 }));
220
221 env(noop(env.master));
222 // This test will probably fail if any breakpoints are encountered,
223 // but should pass on even the slowest machines.
224 auto const start = clock_type::now();
225 env.close();
226 BEAST_EXPECT(clock_type::now() - start < 1s);
227 }
228
229 void
231 {
232 using namespace jtx;
233 using boost::asio::buffer;
234 testcase("jsonInvalid");
235
236 std::string const request =
237 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";
238
239 Json::Value jvRequest;
240 Json::Reader jrReader;
241
243 buffers.emplace_back(buffer(request, 1024));
244 buffers.emplace_back(
245 buffer(request.data() + 1024, request.length() - 1024));
246 BEAST_EXPECT(
247 jrReader.parse(jvRequest, buffers) && jvRequest.isObject());
248 }
249
250 void
251 run() override
252 {
253 testOffer1();
259 }
260};
261
262BEAST_DEFINE_TESTSUITE(Regression, app, ripple);
263
264} // namespace test
265} // namespace ripple
Unserialize a JSON document into a Value.
Definition: json_reader.h:37
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
Definition: json_reader.cpp:73
Represents a JSON value.
Definition: json_value.h:147
bool isObject() const
A testsuite class.
Definition: suite.h:53
testcase_t testcase
Memberspace for declaring test cases.
Definition: suite.h:153
virtual Config & config()=0
virtual TimeKeeper & timeKeeper()=0
virtual Family & getNodeFamily()=0
Writable ledger view that accumulates state and tx changes.
Definition: OpenView.h:56
void apply(TxsRawView &to) const
Apply changes.
Definition: OpenView.cpp:130
time_point closeTime() const
Returns the predicted close time, in network time.
Definition: TimeKeeper.h:76
Immutable cryptographic account descriptor.
Definition: Account.h:38
A transaction testing environment wrapper.
Definition: Env_ss.h:34
A transaction testing environment.
Definition: Env.h:117
Json::Value json(JsonValue &&jv, FN const &... fN)
Create JSON from parameters.
Definition: Env.h:502
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
Definition: Env.cpp:216
std::shared_ptr< STTx const > tx() const
Return the tx data for the last JTx.
Definition: Env.cpp:467
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition: Env.h:325
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition: Env.cpp:121
Account const & master
Definition: Env.h:121
JTx jt(JsonValue &&jv, FN const &... fN)
Create a JTx from parameters.
Definition: Env.h:476
Application & app()
Definition: Env.h:255
beast::Journal const journal
Definition: Env.h:158
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:237
void memoize(Account const &account)
Associate AccountID with account.
Definition: Env.cpp:156
A balance matches.
Definition: balance.h:39
Set the fee on a JTx.
Definition: fee.h:36
Inject raw JSON.
Definition: jtx_json.h:32
Match the number of items in the account's owner directory.
Definition: owners.h:70
Check a set of conditions.
Definition: require.h:64
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition: rpc.h:34
Set the regular signature on a JTx.
Definition: sig.h:35
T data(T... args)
T emplace_back(T... args)
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:43
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:160
static none_t const none
Definition: tags.h:34
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:29
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition: envconfig.h:54
Json::Value noop(Account const &account)
The null transaction.
Definition: noop.h:31
Json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
Definition: offer.cpp:28
XRP_t const XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:104
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
std::pair< TER, bool > apply(Application &app, OpenView &view, STTx const &tx, ApplyFlags flags, beast::Journal journal)
Apply a transaction to an OpenView.
Definition: apply.cpp:109
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,...
Definition: BasicConfig.h:313
constexpr XRPAmount INITIAL_XRP
Configure the native currency.
@ tecINSUFF_FEE
Definition: TER.h:289
@ tesSUCCESS
Definition: TER.h:242
create_genesis_t const create_genesis
Definition: Ledger.cpp:60
@ tapNONE
Definition: ApplyView.h:31
T length(T... args)
void run() override
Runs the suite.
Execution context for applying a JSON transaction.
Definition: JTx.h:44
std::shared_ptr< STTx const > stx
Definition: JTx.h:54
Json::Value jv
Definition: JTx.h:45
Set the sequence number on a JTx.
Definition: seq.h:34