rippled
BookOffers.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012-2014 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/app/main/Application.h>
21 #include <ripple/app/misc/NetworkOPs.h>
22 #include <ripple/basics/Log.h>
23 #include <ripple/ledger/ReadView.h>
24 #include <ripple/net/RPCErr.h>
25 #include <ripple/protocol/ErrorCodes.h>
26 #include <ripple/protocol/jss.h>
27 #include <ripple/protocol/UintTypes.h>
28 #include <ripple/resource/Fees.h>
29 #include <ripple/rpc/Context.h>
30 #include <ripple/rpc/impl/RPCHelpers.h>
31 
32 namespace ripple {
33 
35 {
36  // VFALCO TODO Here is a terrible place for this kind of business
37  // logic. It needs to be moved elsewhere and documented,
38  // and encapsulated into a function.
39  if (context.app.getJobQueue ().getJobCountGE (jtCLIENT) > 200)
40  return rpcError (rpcTOO_BUSY);
41 
43  auto jvResult = RPC::lookupLedger (lpLedger, context);
44 
45  if (!lpLedger)
46  return jvResult;
47 
48  if (!context.params.isMember (jss::taker_pays))
49  return RPC::missing_field_error (jss::taker_pays);
50 
51  if (!context.params.isMember (jss::taker_gets))
52  return RPC::missing_field_error (jss::taker_gets);
53 
54  Json::Value const& taker_pays = context.params[jss::taker_pays];
55  Json::Value const& taker_gets = context.params[jss::taker_gets];
56 
57  if (!taker_pays.isObjectOrNull ())
58  return RPC::object_field_error (jss::taker_pays);
59 
60  if (!taker_gets.isObjectOrNull ())
61  return RPC::object_field_error (jss::taker_gets);
62 
63  if (!taker_pays.isMember (jss::currency))
64  return RPC::missing_field_error ("taker_pays.currency");
65 
66  if (! taker_pays [jss::currency].isString ())
67  return RPC::expected_field_error ("taker_pays.currency", "string");
68 
69  if (! taker_gets.isMember (jss::currency))
70  return RPC::missing_field_error ("taker_gets.currency");
71 
72  if (! taker_gets [jss::currency].isString ())
73  return RPC::expected_field_error ("taker_gets.currency", "string");
74 
75  Currency pay_currency;
76 
77  if (!to_currency (pay_currency, taker_pays [jss::currency].asString ()))
78  {
79  JLOG (context.j.info()) << "Bad taker_pays currency.";
81  "Invalid field 'taker_pays.currency', bad currency.");
82  }
83 
84  Currency get_currency;
85 
86  if (!to_currency (get_currency, taker_gets [jss::currency].asString ()))
87  {
88  JLOG (context.j.info()) << "Bad taker_gets currency.";
90  "Invalid field 'taker_gets.currency', bad currency.");
91  }
92 
93  AccountID pay_issuer;
94 
95  if (taker_pays.isMember (jss::issuer))
96  {
97  if (! taker_pays [jss::issuer].isString())
98  return RPC::expected_field_error ("taker_pays.issuer", "string");
99 
100  if (!to_issuer(
101  pay_issuer, taker_pays [jss::issuer].asString ()))
103  "Invalid field 'taker_pays.issuer', bad issuer.");
104 
105  if (pay_issuer == noAccount ())
107  "Invalid field 'taker_pays.issuer', bad issuer account one.");
108  }
109  else
110  {
111  pay_issuer = xrpAccount ();
112  }
113 
114  if (isXRP (pay_currency) && ! isXRP (pay_issuer))
115  return RPC::make_error (
116  rpcSRC_ISR_MALFORMED, "Unneeded field 'taker_pays.issuer' for "
117  "XRP currency specification.");
118 
119  if (!isXRP (pay_currency) && isXRP (pay_issuer))
121  "Invalid field 'taker_pays.issuer', expected non-XRP issuer.");
122 
123  AccountID get_issuer;
124 
125  if (taker_gets.isMember (jss::issuer))
126  {
127  if (! taker_gets [jss::issuer].isString())
128  return RPC::expected_field_error ("taker_gets.issuer", "string");
129 
130  if (! to_issuer (
131  get_issuer, taker_gets [jss::issuer].asString ()))
133  "Invalid field 'taker_gets.issuer', bad issuer.");
134 
135  if (get_issuer == noAccount ())
137  "Invalid field 'taker_gets.issuer', bad issuer account one.");
138  }
139  else
140  {
141  get_issuer = xrpAccount ();
142  }
143 
144 
145  if (isXRP (get_currency) && ! isXRP (get_issuer))
147  "Unneeded field 'taker_gets.issuer' for "
148  "XRP currency specification.");
149 
150  if (!isXRP (get_currency) && isXRP (get_issuer))
152  "Invalid field 'taker_gets.issuer', expected non-XRP issuer.");
153 
154  boost::optional<AccountID> takerID;
155  if (context.params.isMember (jss::taker))
156  {
157  if (! context.params [jss::taker].isString ())
158  return RPC::expected_field_error (jss::taker, "string");
159 
160  takerID = parseBase58<AccountID>(
161  context.params [jss::taker].asString());
162  if (! takerID)
163  return RPC::invalid_field_error (jss::taker);
164  }
165 
166  if (pay_currency == get_currency && pay_issuer == get_issuer)
167  {
168  JLOG (context.j.info()) << "taker_gets same as taker_pays.";
170  }
171 
172  unsigned int limit;
173  if (auto err = readLimitField(limit, RPC::Tuning::bookOffers, context))
174  return *err;
175 
176  bool const bProof (context.params.isMember (jss::proof));
177 
178  Json::Value const jvMarker (context.params.isMember (jss::marker)
179  ? context.params[jss::marker]
181 
182  context.netOps.getBookPage (
183  lpLedger,
184  {{pay_currency, pay_issuer}, {get_currency, get_issuer}},
185  takerID ? *takerID : beast::zero, bProof, limit, jvMarker, jvResult);
186 
188 
189  return jvResult;
190 }
191 
192 } // ripple
ripple::to_currency
bool to_currency(Currency &currency, std::string const &code)
Tries to convert a string to a Currency, returns true on success.
Definition: UintTypes.cpp:67
ripple::RPC::JsonContext
Definition: Context.h:52
ripple::rpcDST_AMT_MALFORMED
@ rpcDST_AMT_MALFORMED
Definition: ErrorCodes.h:107
std::shared_ptr
STL class.
Json::Value::isString
bool isString() const
Definition: json_value.cpp:1049
ripple::jtCLIENT
@ jtCLIENT
Definition: Job.h:49
ripple::Resource::feeMediumBurdenRPC
const Charge feeMediumBurdenRPC
ripple::RPC::Context::loadType
Resource::Charge & loadType
Definition: Context.h:43
ripple::rpcTOO_BUSY
@ rpcTOO_BUSY
Definition: ErrorCodes.h:57
ripple::RPC::Tuning::bookOffers
static constexpr LimitRange bookOffers
Limits for the book_offers command.
Definition: rpc/impl/Tuning.h:48
ripple::RPC::lookupLedger
Status lookupLedger(std::shared_ptr< ReadView const > &ledger, JsonContext &context, Json::Value &result)
Look up a ledger from a request and fill a Json::Result with the data representing a ledger.
Definition: RPCHelpers.cpp:484
ripple::RPC::object_field_error
Json::Value object_field_error(std::string const &name)
Definition: ErrorCodes.h:244
ripple::RPC::expected_field_error
Json::Value expected_field_error(std::string const &name, std::string const &type)
Definition: ErrorCodes.h:286
ripple::RPC::missing_field_error
Json::Value missing_field_error(std::string const &name)
Definition: ErrorCodes.h:229
ripple::RPC::Context::j
const beast::Journal j
Definition: Context.h:41
ripple::base_uint< 160, detail::CurrencyTag >
ripple::NetworkOPs::getBookPage
virtual void getBookPage(std::shared_ptr< ReadView const > &lpLedger, Book const &book, AccountID const &uTakerID, bool const bProof, unsigned int iLimit, Json::Value const &jvMarker, Json::Value &jvResult)=0
ripple::Application::getJobQueue
virtual JobQueue & getJobQueue()=0
ripple::rpcSRC_ISR_MALFORMED
@ rpcSRC_ISR_MALFORMED
Definition: ErrorCodes.h:126
ripple::xrpAccount
AccountID const & xrpAccount()
Compute AccountID from public key.
Definition: AccountID.cpp:149
ripple::RPC::Context::app
Application & app
Definition: Context.h:42
beast::Journal::info
Stream info() const
Definition: Journal.h:297
ripple::isXRP
bool isXRP(AccountID const &c)
Definition: AccountID.h:121
Json::Value::isMember
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:961
ripple::rpcDST_ISR_MALFORMED
@ rpcDST_ISR_MALFORMED
Definition: ErrorCodes.h:109
ripple::doBookOffers
Json::Value doBookOffers(RPC::JsonContext &context)
Definition: BookOffers.cpp:34
ripple::rpcError
Json::Value rpcError(int iError, Json::Value jvResult)
Definition: RPCErr.cpp:28
ripple::RPC::Context::netOps
NetworkOPs & netOps
Definition: Context.h:44
ripple::JobQueue::getJobCountGE
int getJobCountGE(JobType t) const
All waiting jobs at or greater than this priority.
Definition: JobQueue.cpp:141
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
Json::nullValue
@ nullValue
'null' value
Definition: json_value.h:38
ripple::rpcBAD_MARKET
@ rpcBAD_MARKET
Definition: ErrorCodes.h:98
ripple::rpcSRC_CUR_MALFORMED
@ rpcSRC_CUR_MALFORMED
Definition: ErrorCodes.h:125
ripple::RPC::JsonContext::params
Json::Value params
Definition: Context.h:63
ripple::RPC::invalid_field_error
Json::Value invalid_field_error(std::string const &name)
Definition: ErrorCodes.h:264
Json::Value::isObjectOrNull
bool isObjectOrNull() const
Definition: json_value.cpp:1075
ripple::noAccount
AccountID const & noAccount()
A placeholder for empty accounts.
Definition: AccountID.cpp:156
ripple::RPC::make_error
Json::Value make_error(error_code_i code)
Returns a new json object that reflects the error code.
Definition: ErrorCodes.cpp:182
Json::Value
Represents a JSON value.
Definition: json_value.h:141
ripple::to_issuer
bool to_issuer(AccountID &, std::string const &)
Convert hex or base58 string to AccountID.
Definition: AccountID.cpp:163
Json::Value::asString
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:482