rippled
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 <ripple/app/tx/apply.h>
21 #include <ripple/basics/StringUtilities.h>
22 #include <ripple/json/json_reader.h>
23 #include <ripple/protocol/Feature.h>
24 #include <ripple/protocol/jss.h>
25 
26 namespace ripple {
27 namespace test {
28 
29 struct Regression_test : public beast::unit_test::suite
30 {
31  // OfferCreate, then OfferCreate with cancel
32  void testOffer1()
33  {
34  using namespace jtx;
35  Env env(*this);
36  auto const gw = Account("gw");
37  auto const USD = gw["USD"];
38  env.fund(XRP(10000), "alice", gw);
39  env(offer("alice", USD(10), XRP(10)), require(owners("alice", 1)));
40  env(offer("alice", USD(20), XRP(10)), json(R"raw(
41  { "OfferSequence" : 4 }
42  )raw"), require(owners("alice", 1)));
43  }
44 
46  {
47  testcase("Account balance < fee destroys correct amount of XRP");
48  using namespace jtx;
49  Env env(*this);
50  env.memoize("alice");
51 
52  // The low balance scenario can not deterministically
53  // be reproduced against an open ledger. Make a local
54  // closed ledger and work with it directly.
55  auto closed = std::make_shared<Ledger>(
56  create_genesis, env.app().config(),
57  std::vector<uint256>{}, env.app().family());
58  auto expectedDrops = INITIAL_XRP;
59  BEAST_EXPECT(closed->info().drops == expectedDrops);
60 
61  auto const aliceXRP = 400;
62  auto const aliceAmount = XRP(aliceXRP);
63 
64  auto next = std::make_shared<Ledger>(
65  *closed,
66  env.app().timeKeeper().closeTime());
67  {
68  // Fund alice
69  auto const jt = env.jt(pay(env.master, "alice", aliceAmount));
70  OpenView accum(&*next);
71 
72  auto const result = ripple::apply(env.app(),
73  accum, *jt.stx, tapNONE, env.journal);
74  BEAST_EXPECT(result.first == tesSUCCESS);
75  BEAST_EXPECT(result.second);
76 
77  accum.apply(*next);
78  }
79  expectedDrops -= next->fees().base;
80  BEAST_EXPECT(next->info().drops == expectedDrops);
81  {
82  auto const sle = next->read(
83  keylet::account(Account("alice").id()));
84  BEAST_EXPECT(sle);
85  auto balance = sle->getFieldAmount(sfBalance);
86 
87  BEAST_EXPECT(balance == aliceAmount );
88  }
89 
90  {
91  // Specify the seq manually since the env's open ledger
92  // doesn't know about this account.
93  auto const jt = env.jt(noop("alice"), fee(expectedDrops),
94  seq(2));
95 
96  OpenView accum(&*next);
97 
98  auto const result = ripple::apply(env.app(),
99  accum, *jt.stx, tapNONE, env.journal);
100  BEAST_EXPECT(result.first == tecINSUFF_FEE);
101  BEAST_EXPECT(result.second);
102 
103  accum.apply(*next);
104  }
105  {
106  auto const sle = next->read(
107  keylet::account(Account("alice").id()));
108  BEAST_EXPECT(sle);
109  auto balance = sle->getFieldAmount(sfBalance);
110 
111  BEAST_EXPECT(balance == XRP(0));
112  }
113  expectedDrops -= aliceXRP * dropsPerXRP;
114  BEAST_EXPECT(next->info().drops == expectedDrops);
115  }
116 
118  {
119  testcase("Signing with a secp256r1 key should fail gracefully");
120  using namespace jtx;
121  Env env(*this);
122 
123  // Test case we'll use.
124  auto test256r1key = [&env] (Account const& acct)
125  {
126  auto const baseFee = env.current()->fees().base;
127  std::uint32_t const acctSeq = env.seq (acct);
128  Json::Value jsonNoop = env.json (
129  noop (acct), fee(baseFee), seq(acctSeq), sig(acct));
130  JTx jt = env.jt (jsonNoop);
131  jt.fill_sig = false;
132 
133  // Random secp256r1 public key generated by
134  // https://kjur.github.io/jsrsasign/sample-ecdsa.html
135  std::string const secp256r1PubKey =
136  "045d02995ec24988d9a2ae06a3733aa35ba0741e87527"
137  "ed12909b60bd458052c944b24cbf5893c3e5be321774e"
138  "5082e11c034b765861d0effbde87423f8476bb2c";
139 
140  // Set the key in the JSON.
141  jt.jv["SigningPubKey"] = secp256r1PubKey;
142 
143  // Set the same key in the STTx.
144  auto secp256r1Sig = std::make_unique<STTx>(*(jt.stx));
145  auto pubKeyBlob = strUnHex (secp256r1PubKey);
146  assert (pubKeyBlob); // Hex for public key must be valid
147  secp256r1Sig->setFieldVL
148  (sfSigningPubKey, std::move(*pubKeyBlob));
149  jt.stx.reset (secp256r1Sig.release());
150 
151  env (jt, ter (temINVALID));
152  };
153 
154  Account const alice {"alice", KeyType::secp256k1};
155  Account const becky {"becky", KeyType::ed25519};
156 
157  env.fund(XRP(10000), alice, becky);
158 
159  test256r1key (alice);
160  test256r1key (becky);
161  }
162 
164  {
165  testcase("Autofilled fee should use the escalated fee");
166  using namespace jtx;
167  Env env(*this, envconfig([](std::unique_ptr<Config> cfg)
168  {
169  cfg->section("transaction_queue")
170  .set("minimum_txn_in_ledger_standalone", "3");
171  return cfg;
172  }));
173  Env_ss envs(env);
174 
175  auto const alice = Account("alice");
176  env.fund(XRP(100000), alice);
177 
178  auto params = Json::Value(Json::objectValue);
179  // Max fee = 50k drops
180  params[jss::fee_mult_max] = 5000;
181  std::vector<int> const
182  expectedFees({ 10, 10, 8889, 13889, 20000 });
183 
184  // We should be able to submit 5 transactions within
185  // our fee limit.
186  for (int i = 0; i < 5; ++i)
187  {
188  envs(noop(alice), fee(none), seq(none))(params);
189 
190  auto tx = env.tx();
191  if (BEAST_EXPECT(tx))
192  {
193  BEAST_EXPECT(tx->getAccountID(sfAccount) == alice.id());
194  BEAST_EXPECT(tx->getTxnType() == ttACCOUNT_SET);
195  auto const fee = tx->getFieldAmount(sfFee);
196  BEAST_EXPECT(fee == drops(expectedFees[i]));
197  }
198  }
199  }
200 
202  {
203  testcase("Fee escalation shouldn't allocate extreme memory");
204  using clock_type = std::chrono::steady_clock;
205  using namespace jtx;
206  using namespace std::chrono_literals;
207 
208  Env env(*this, envconfig([](std::unique_ptr<Config> cfg)
209  {
210  auto& s = cfg->section("transaction_queue");
211  s.set("minimum_txn_in_ledger_standalone", "4294967295");
212  s.set("minimum_txn_in_ledger", "4294967295");
213  s.set("target_txn_in_ledger", "4294967295");
214  s.set("normal_consensus_increase_percent", "4294967295");
215 
216  return cfg;
217  }));
218 
219  env(noop(env.master));
220  // This test will probably fail if any breakpoints are encountered,
221  // but should pass on even the slowest machines.
222  auto const start = clock_type::now();
223  env.close();
224  BEAST_EXPECT(clock_type::now() - start < 1s);
225  }
226 
228  {
229  using namespace jtx;
230  using boost::asio::buffer;
231  testcase("jsonInvalid");
232 
233  std::string const request = 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";
234 
235  Json::Value jvRequest;
236  Json::Reader jrReader;
237 
239  buffers.emplace_back(buffer(request, 1024));
240  buffers.emplace_back(buffer(request.data() + 1024, request.length() - 1024));
241  BEAST_EXPECT(jrReader.parse(jvRequest, buffers) && jvRequest.isObject());
242  }
243 
244  void run() override
245  {
246  testOffer1();
251  testJsonInvalid();
252  }
253 };
254 
255 BEAST_DEFINE_TESTSUITE(Regression,app,ripple);
256 
257 } // test
258 } // ripple
ripple::test::jtx::json
Inject raw JSON.
Definition: jtx_json.h:31
ripple::test::jtx::noop
Json::Value noop(Account const &account)
The null transaction.
Definition: noop.h:32
std::chrono::steady_clock
ripple::test::jtx::XRP
const XRP_t XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:109
ripple::test::jtx::dropsPerXRP
constexpr XRPAmount dropsPerXRP
Definition: amount.h:67
Json::Value::isObject
bool isObject() const
Definition: json_value.cpp:1069
ripple::test::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountDelete, app, ripple)
std::string
STL class.
ripple::test::jtx::drops
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
Definition: amount.h:261
ripple::test::jtx::Env::tx
std::shared_ptr< STTx const > tx() const
Return the tx data for the last JTx.
Definition: Env.cpp:370
ripple::apply
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:108
ripple::test::jtx::ter
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition: ter.h:33
ripple::OpenView::apply
void apply(TxsRawView &to) const
Apply changes.
Definition: OpenView.cpp:120
ripple::test::jtx::owners
Match the number of items in the account's owner directory.
Definition: owners.h:73
ripple::test::jtx::balance
A balance matches.
Definition: balance.h:38
ripple::sfSigningPubKey
const SF_Blob sfSigningPubKey(access, STI_VL, 3, "SigningPubKey")
Definition: SField.h:442
ripple::OpenView
Writable ledger view that accumulates state and tx changes.
Definition: OpenView.h:52
std::vector
STL class.
std::string::length
T length(T... args)
ripple::CashFilter::none
@ none
ripple::test::jtx::JTx::stx
std::shared_ptr< STTx const > stx
Definition: JTx.h:49
ripple::test::jtx::Env::jt
JTx jt(JsonValue &&jv, FN const &... fN)
Create a JTx from parameters.
Definition: Env.h:431
ripple::sfAccount
const SF_Account sfAccount(access, STI_ACCOUNT, 1, "Account")
Definition: SField.h:460
ripple::test::jtx::require
Check a set of conditions.
Definition: require.h:66
ripple::test::jtx::Env::journal
const beast::Journal journal
Definition: Env.h:143
ripple::strUnHex
boost::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
Definition: StringUtilities.h:69
ripple::test::jtx::Env::app
Application & app()
Definition: Env.h:237
ripple::Application::timeKeeper
virtual TimeKeeper & timeKeeper()=0
Json::Reader
Unserialize a JSON document into a Value.
Definition: json_reader.h:36
ripple::test::jtx::envconfig
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition: envconfig.h:52
ripple::test::jtx::offer
Json::Value offer(Account const &account, STAmount const &in, STAmount const &out, std::uint32_t flags)
Create an offer.
Definition: offer.cpp:28
ripple::tapNONE
@ tapNONE
Definition: ApplyView.h:33
ripple::INITIAL_XRP
constexpr XRPAmount INITIAL_XRP
Configure the native currency.
Definition: SystemParameters.h:45
ripple::test::Regression_test::testFeeEscalationExtremeConfig
void testFeeEscalationExtremeConfig()
Definition: Regression_test.cpp:201
ripple::KeyType::ed25519
@ ed25519
ripple::test::Regression_test::run
void run() override
Definition: Regression_test.cpp:244
ripple::test::Regression_test::testOffer1
void testOffer1()
Definition: Regression_test.cpp:32
ripple::Application::family
virtual Family & family()=0
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:45
ripple::keylet::account
static const account_t account
Definition: Indexes.h:116
ripple::Application::config
virtual Config & config()=0
ripple::test::jtx::JTx
Execution context for applying a JSON transaction.
Definition: JTx.h:41
ripple::test::jtx::JTx::jv
Json::Value jv
Definition: JTx.h:43
ripple::set
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:271
ripple::TimeKeeper::closeTime
virtual time_point closeTime() const =0
Returns the close time, in network time.
ripple::tecINSUFF_FEE
@ tecINSUFF_FEE
Definition: TER.h:267
std::uint32_t
ripple::test::jtx::sig
Set the regular signature on a JTx.
Definition: sig.h:33
ripple::test::jtx::Env::seq
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
Definition: Env.cpp:192
ripple::test::jtx::Env_ss
A transaction testing environment wrapper.
Definition: Env_ss.h:33
ripple::sfFee
const SF_Amount sfFee(access, STI_AMOUNT, 8, "Fee")
Definition: SField.h:430
ripple::test::jtx::fee
Set the fee on a JTx.
Definition: fee.h:34
ripple::KeyType::secp256k1
@ secp256k1
ripple::test::jtx::seq
Set the sequence number on a JTx.
Definition: seq.h:32
ripple::test::Regression_test::testFeeEscalationAutofill
void testFeeEscalationAutofill()
Definition: Regression_test.cpp:163
ripple::test::Regression_test::testSecp256r1key
void testSecp256r1key()
Definition: Regression_test.cpp:117
std::vector::emplace_back
T emplace_back(T... args)
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::sfBalance
const SF_Amount sfBalance(access, STI_AMOUNT, 2, "Balance")
Definition: SField.h:424
ripple::test::jtx::pay
Json::Value pay(Account const &account, Account const &to, AnyAmount amount)
Create a payment.
Definition: pay.cpp:29
ripple::test::jtx::JTx::fill_sig
bool fill_sig
Definition: JTx.h:48
ripple::ttACCOUNT_SET
@ ttACCOUNT_SET
Definition: TxFormats.h:40
ripple::test::jtx::Env::close
void close(NetClock::time_point closeTime, boost::optional< std::chrono::milliseconds > consensusDelay=boost::none)
Close and advance the ledger.
Definition: Env.cpp:114
ripple::test::jtx::Env::fund
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:214
ripple::create_genesis
const create_genesis_t create_genesis
Definition: Ledger.cpp:56
ripple::test::jtx::Env::master
Account const & master
Definition: Env.h:122
Json::Reader::parse
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
Definition: json_reader.cpp:76
ripple::test::Regression_test::testLowBalanceDestroy
void testLowBalanceDestroy()
Definition: Regression_test.cpp:45
ripple::test::jtx::Account
Immutable cryptographic account descriptor.
Definition: Account.h:37
ripple::test::jtx::Env::memoize
void memoize(Account const &account)
Associate AccountID with account.
Definition: Env.cpp:135
std::unique_ptr
STL class.
ripple::test::Regression_test
Definition: Regression_test.cpp:29
ripple::tesSUCCESS
@ tesSUCCESS
Definition: TER.h:219
std::string::data
T data(T... args)
ripple::test::Regression_test::testJsonInvalid
void testJsonInvalid()
Definition: Regression_test.cpp:227
ripple::test::jtx::Env::current
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition: Env.h:296
ripple::test::jtx::Env::json
Json::Value json(JsonValue &&jv, FN const &... fN)
Create JSON from parameters.
Definition: Env.h:446
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:117
ripple::temINVALID
@ temINVALID
Definition: TER.h:108
Json::Value
Represents a JSON value.
Definition: json_value.h:141