rippled
TransactionSign.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/rpc/impl/TransactionSign.h>
21 #include <ripple/app/ledger/LedgerMaster.h>
22 #include <ripple/app/ledger/OpenLedger.h>
23 #include <ripple/app/main/Application.h>
24 #include <ripple/app/misc/LoadFeeTrack.h>
25 #include <ripple/app/misc/Transaction.h>
26 #include <ripple/app/misc/TxQ.h>
27 #include <ripple/app/paths/Pathfinder.h>
28 #include <ripple/app/tx/apply.h> // Validity::Valid
29 #include <ripple/basics/Log.h>
30 #include <ripple/basics/mulDiv.h>
31 #include <ripple/json/json_writer.h>
32 #include <ripple/net/RPCErr.h>
33 #include <ripple/protocol/Sign.h>
34 #include <ripple/protocol/ErrorCodes.h>
35 #include <ripple/protocol/Feature.h>
36 #include <ripple/protocol/STAccount.h>
37 #include <ripple/protocol/STParsedJSON.h>
38 #include <ripple/protocol/TxFlags.h>
39 #include <ripple/rpc/impl/LegacyPathFind.h>
40 #include <ripple/rpc/impl/RPCHelpers.h>
41 #include <ripple/rpc/impl/Tuning.h>
42 #include <algorithm>
43 #include <iterator>
44 
45 namespace ripple {
46 namespace RPC {
47 namespace detail {
48 
49 // Used to pass extra parameters used when returning a
50 // a SigningFor object.
52 {
53 private:
57 
58 public:
59  explicit SigningForParams ()
60  : multiSigningAcctID_ (nullptr)
61  , multiSignPublicKey_ (nullptr)
62  , multiSignature_ (nullptr)
63  { }
64 
65  SigningForParams (SigningForParams const& rhs) = delete;
66 
68  AccountID const& multiSigningAcctID,
69  PublicKey& multiSignPublicKey,
70  Buffer& multiSignature)
71  : multiSigningAcctID_ (&multiSigningAcctID)
72  , multiSignPublicKey_ (&multiSignPublicKey)
73  , multiSignature_ (&multiSignature)
74  { }
75 
76  bool isMultiSigning () const
77  {
78  return ((multiSigningAcctID_ != nullptr) &&
79  (multiSignPublicKey_ != nullptr) &&
80  (multiSignature_ != nullptr));
81  }
82 
83  bool isSingleSigning () const
84  {
85  return !isMultiSigning();
86  }
87 
88  // When multi-signing we should not edit the tx_json fields.
89  bool editFields () const
90  {
91  return !isMultiSigning();
92  }
93 
94  // Don't call this method unless isMultiSigning() returns true.
95  AccountID const& getSigner ()
96  {
97  return *multiSigningAcctID_;
98  }
99 
100  void setPublicKey (PublicKey const& multiSignPublicKey)
101  {
102  *multiSignPublicKey_ = multiSignPublicKey;
103  }
104 
105  void moveMultiSignature (Buffer&& multiSignature)
106  {
107  *multiSignature_ = std::move (multiSignature);
108  }
109 };
110 
111 //------------------------------------------------------------------------------
112 
114  std::shared_ptr<SLE const> accountState,
115  AccountID const& accountID,
116  PublicKey const& publicKey)
117 {
118  auto const publicKeyAcctID = calcAccountID(publicKey);
119  bool const isMasterKey = publicKeyAcctID == accountID;
120 
121  // If we can't get the accountRoot, but the accountIDs match, that's
122  // good enough.
123  if (!accountState)
124  {
125  if (isMasterKey)
126  return rpcSUCCESS;
127  return rpcBAD_SECRET;
128  }
129 
130  // If we *can* get to the accountRoot, check for MASTER_DISABLED.
131  auto const& sle = *accountState;
132  if (isMasterKey)
133  {
134  if (sle.isFlag(lsfDisableMaster))
135  return rpcMASTER_DISABLED;
136  return rpcSUCCESS;
137  }
138 
139  // The last gasp is that we have public Regular key.
140  if ((sle.isFieldPresent (sfRegularKey)) &&
141  (publicKeyAcctID == sle.getAccountID (sfRegularKey)))
142  {
143  return rpcSUCCESS;
144  }
145  return rpcBAD_SECRET;
146 }
147 
149  Json::Value const& params,
150  Json::Value& tx_json,
151  AccountID const& srcAddressID,
152  Role const role,
153  Application& app,
154  std::shared_ptr<ReadView const> const& ledger,
155  bool doPath)
156 {
157  // Only path find for Payments.
158  if (tx_json[jss::TransactionType].asString () != jss::Payment)
159  return Json::Value();
160 
161  if (!tx_json.isMember (jss::Amount))
162  return RPC::missing_field_error ("tx_json.Amount");
163 
164  STAmount amount;
165 
166  if (! amountFromJsonNoThrow (amount, tx_json [jss::Amount]))
167  return RPC::invalid_field_error ("tx_json.Amount");
168 
169  if (!tx_json.isMember (jss::Destination))
170  return RPC::missing_field_error ("tx_json.Destination");
171 
172  auto const dstAccountID = parseBase58<AccountID>(
173  tx_json[jss::Destination].asString());
174  if (! dstAccountID)
175  return RPC::invalid_field_error ("tx_json.Destination");
176 
177  if ((doPath == false) && params.isMember (jss::build_path))
179  "Field 'build_path' not allowed in this context.");
180 
181  if (tx_json.isMember (jss::Paths) && params.isMember (jss::build_path))
183  "Cannot specify both 'tx_json.Paths' and 'build_path'");
184 
185  if (!tx_json.isMember (jss::Paths) && params.isMember (jss::build_path))
186  {
187  STAmount sendMax;
188 
189  if (tx_json.isMember (jss::SendMax))
190  {
191  if (! amountFromJsonNoThrow (sendMax, tx_json [jss::SendMax]))
192  return RPC::invalid_field_error ("tx_json.SendMax");
193  }
194  else
195  {
196  // If no SendMax, default to Amount with sender as issuer.
197  sendMax = amount;
198  sendMax.setIssuer (srcAddressID);
199  }
200 
201  if (sendMax.native () && amount.native ())
203  "Cannot build XRP to XRP paths.");
204 
205  {
206  LegacyPathFind lpf (isUnlimited (role), app);
207  if (!lpf.isOk ())
208  return rpcError (rpcTOO_BUSY);
209 
210  STPathSet result;
211  if (ledger)
212  {
213  Pathfinder pf(std::make_shared<RippleLineCache>(ledger),
214  srcAddressID, *dstAccountID, sendMax.issue().currency,
215  sendMax.issue().account, amount, boost::none, app);
216  if (pf.findPaths(app.config().PATH_SEARCH_OLD))
217  {
218  // 4 is the maxium paths
219  pf.computePathRanks(4);
220  STPath fullLiquidityPath;
221  STPathSet paths;
222  result = pf.getBestPaths(4, fullLiquidityPath, paths,
223  sendMax.issue().account);
224  }
225  }
226 
227  auto j = app.journal ("RPCHandler");
228  JLOG (j.debug())
229  << "transactionSign: build_path: "
230  << result.getJson (JsonOptions::none);
231 
232  if (! result.empty ())
233  tx_json[jss::Paths] = result.getJson (JsonOptions::none);
234  }
235  }
236  return Json::Value();
237 }
238 
239 //------------------------------------------------------------------------------
240 
241 // Validate (but don't modify) the contents of the tx_json.
242 //
243 // Returns a pair<Json::Value, AccountID>. The Json::Value will contain error
244 // information if there was an error. On success, the account ID is returned
245 // and the Json::Value will be empty.
246 //
247 // This code does not check the "Sequence" field, since the expectations
248 // for that field are particularly context sensitive.
251  Json::Value const& tx_json,
252  Role const role,
253  bool const verify,
254  std::chrono::seconds validatedLedgerAge,
255  Config const& config,
256  LoadFeeTrack const& feeTrack)
257 {
259 
260  if (!tx_json.isObject())
261  {
262  ret.first = RPC::object_field_error (jss::tx_json);
263  return ret;
264  }
265 
266  if (! tx_json.isMember (jss::TransactionType))
267  {
268  ret.first = RPC::missing_field_error ("tx_json.TransactionType");
269  return ret;
270  }
271 
272  if (! tx_json.isMember (jss::Account))
273  {
275  RPC::missing_field_message ("tx_json.Account"));
276  return ret;
277  }
278 
279  auto const srcAddressID = parseBase58<AccountID>(
280  tx_json[jss::Account].asString());
281 
282  if (! srcAddressID)
283  {
285  RPC::invalid_field_message ("tx_json.Account"));
286  return ret;
287  }
288 
289  // Check for current ledger.
290  if (verify && !config.standalone() &&
291  (validatedLedgerAge > Tuning::maxValidatedLedgerAge))
292  {
293  ret.first = rpcError (rpcNO_CURRENT);
294  return ret;
295  }
296 
297  // Check for load.
298  if (feeTrack.isLoadedCluster() && !isUnlimited (role))
299  {
300  ret.first = rpcError (rpcTOO_BUSY);
301  return ret;
302  }
303 
304  // It's all good. Return the AccountID.
305  ret.second = *srcAddressID;
306  return ret;
307 }
308 
309 //------------------------------------------------------------------------------
310 
311 // A move-only struct that makes it easy to return either a Json::Value or a
312 // std::shared_ptr<STTx const> from transactionPreProcessImpl ().
314 {
317 
318  transactionPreProcessResult () = delete;
321  : first (std::move (rhs.first)) // VS2013 won't default this.
322  , second (std::move (rhs.second))
323  { }
324 
325  transactionPreProcessResult& operator=
326  (transactionPreProcessResult const&) = delete;
327  transactionPreProcessResult& operator=
328  (transactionPreProcessResult&&) = delete;
329 
331  : first (std::move (json))
332  , second ()
333  { }
334 
336  : first ()
337  , second (std::move (st))
338  { }
339 };
340 
341 static
342 transactionPreProcessResult
344  Json::Value& params,
345  Role role,
346  SigningForParams& signingArgs,
347  std::chrono::seconds validatedLedgerAge,
348  Application& app,
349  std::shared_ptr<OpenView const> const& ledger)
350 {
351  auto j = app.journal ("RPCHandler");
352 
353  Json::Value jvResult;
354  auto const [pk, sk] = keypairForSignature (params, jvResult);
355  if (contains_error (jvResult))
356  return jvResult;
357 
358  bool const verify = !(params.isMember (jss::offline)
359  && params[jss::offline].asBool());
360 
361  if (! params.isMember (jss::tx_json))
362  return RPC::missing_field_error (jss::tx_json);
363 
364  Json::Value& tx_json (params [jss::tx_json]);
365 
366  // Check tx_json fields, but don't add any.
367  auto [txJsonResult, srcAddressID] = checkTxJsonFields (
368  tx_json, role, verify, validatedLedgerAge,
369  app.config(), app.getFeeTrack());
370 
371  if (RPC::contains_error (txJsonResult))
372  return std::move (txJsonResult);
373 
374  // This test covers the case where we're offline so the sequence number
375  // cannot be determined locally. If we're offline then the caller must
376  // provide the sequence number.
377  if (!verify && !tx_json.isMember (jss::Sequence))
378  return RPC::missing_field_error ("tx_json.Sequence");
379 
380  std::shared_ptr<SLE const> sle = ledger->read(
381  keylet::account(srcAddressID));
382 
383  if (verify && !sle)
384  {
385  // If not offline and did not find account, error.
386  JLOG (j.debug())
387  << "transactionSign: Failed to find source account "
388  << "in current ledger: "
389  << toBase58(srcAddressID);
390 
392  }
393 
394  {
395  Json::Value err = checkFee (
396  params,
397  role,
398  verify && signingArgs.editFields(),
399  app.config(),
400  app.getFeeTrack(),
401  app.getTxQ(),
402  ledger);
403 
404  if (RPC::contains_error (err))
405  return err;
406 
407  err = checkPayment (
408  params,
409  tx_json,
410  srcAddressID,
411  role,
412  app,
413  ledger,
414  verify && signingArgs.editFields());
415 
416  if (RPC::contains_error(err))
417  return err;
418  }
419 
420  if (signingArgs.editFields())
421  {
422  if (!tx_json.isMember (jss::Sequence))
423  {
424  if (! sle)
425  {
426  JLOG (j.debug())
427  << "transactionSign: Failed to find source account "
428  << "in current ledger: "
429  << toBase58(srcAddressID);
430 
432  }
433 
434  auto seq = (*sle)[sfSequence];
435  auto const queued = app.getTxQ().getAccountTxs(srcAddressID,
436  *ledger);
437  // If the account has any txs in the TxQ, skip those sequence
438  // numbers (accounting for possible gaps).
439  for(auto const& tx : queued)
440  {
441  if (tx.first == seq)
442  ++seq;
443  else if (tx.first > seq)
444  break;
445  }
446  tx_json[jss::Sequence] = seq;
447  }
448 
449  if (!tx_json.isMember (jss::Flags))
450  tx_json[jss::Flags] = tfFullyCanonicalSig;
451  }
452 
453  // If multisigning there should not be a single signature and vice versa.
454  if (signingArgs.isMultiSigning())
455  {
456  if (tx_json.isMember (sfTxnSignature.jsonName))
458 
459  // If multisigning then we need to return the public key.
460  signingArgs.setPublicKey (pk);
461  }
462  else if (signingArgs.isSingleSigning())
463  {
464  if (tx_json.isMember (sfSigners.jsonName))
465  return rpcError (rpcALREADY_MULTISIG);
466  }
467 
468  if (verify)
469  {
470  if (! sle)
471  // XXX Ignore transactions for accounts not created.
473 
474  JLOG (j.trace())
475  << "verify: " << toBase58(calcAccountID(pk))
476  << " : " << toBase58(srcAddressID);
477 
478  // Don't do this test if multisigning since the account and secret
479  // probably don't belong together in that case.
480  if (!signingArgs.isMultiSigning())
481  {
482  // Make sure the account and secret belong together.
483  auto const err = acctMatchesPubKey (
484  sle, srcAddressID, pk);
485 
486  if (err != rpcSUCCESS)
487  return rpcError (err);
488  }
489  }
490 
491  STParsedJSONObject parsed (std::string (jss::tx_json), tx_json);
492  if (parsed.object == boost::none)
493  {
494  Json::Value err;
495  err [jss::error] = parsed.error [jss::error];
496  err [jss::error_code] = parsed.error [jss::error_code];
497  err [jss::error_message] = parsed.error [jss::error_message];
498  return err;
499  }
500 
501  std::shared_ptr<STTx> stpTrans;
502  try
503  {
504  // If we're generating a multi-signature the SigningPubKey must be
505  // empty, otherwise it must be the master account's public key.
506  parsed.object->setFieldVL (sfSigningPubKey,
507  signingArgs.isMultiSigning()
508  ? Slice (nullptr, 0)
509  : pk.slice());
510 
511  stpTrans = std::make_shared<STTx> (
512  std::move (parsed.object.get()));
513  }
514  catch (STObject::FieldErr& err)
515  {
516  return RPC::make_error (rpcINVALID_PARAMS, err.what());
517  }
518  catch (std::exception&)
519  {
521  "Exception occurred constructing serialized transaction");
522  }
523 
524  std::string reason;
525  if (!passesLocalChecks (*stpTrans, reason))
526  return RPC::make_error (rpcINVALID_PARAMS, reason);
527 
528  // If multisign then return multiSignature, else set TxnSignature field.
529  if (signingArgs.isMultiSigning ())
530  {
531  Serializer s = buildMultiSigningData (*stpTrans,
532  signingArgs.getSigner ());
533 
534  auto multisig = ripple::sign (
535  pk,
536  sk,
537  s.slice());
538 
539  signingArgs.moveMultiSignature (std::move (multisig));
540  }
541  else if (signingArgs.isSingleSigning())
542  {
543  stpTrans->sign (pk, sk);
544  }
545 
546  return transactionPreProcessResult {std::move (stpTrans)};
547 }
548 
549 static
552  Rules const& rules, Application& app)
553 {
555 
556  // Turn the passed in STTx into a Transaction.
557  Transaction::pointer tpTrans;
558  {
559  std::string reason;
560  tpTrans = std::make_shared<Transaction>(
561  stpTrans, reason, app);
562  if (tpTrans->getStatus () != NEW)
563  {
565  "Unable to construct transaction: " + reason);
566  return ret;
567  }
568  }
569  try
570  {
571  // Make sure the Transaction we just built is legit by serializing it
572  // and then de-serializing it. If the result isn't equivalent
573  // to the initial transaction then there's something wrong with the
574  // passed-in STTx.
575  {
576  Serializer s;
577  tpTrans->getSTransaction ()->add (s);
578  Blob transBlob = s.getData ();
579  SerialIter sit {makeSlice(transBlob)};
580 
581  // Check the signature if that's called for.
582  auto sttxNew = std::make_shared<STTx const> (sit);
583  if (!app.checkSigs())
585  sttxNew->getTransactionID(), Validity::SigGoodOnly);
586  if (checkValidity(app.getHashRouter(),
587  *sttxNew, rules, app.config()).first != Validity::Valid)
588  {
590  "Invalid signature.");
591  return ret;
592  }
593 
594  std::string reason;
595  auto tpTransNew =
596  std::make_shared<Transaction> (sttxNew, reason, app);
597 
598  if (tpTransNew)
599  {
600  if (!tpTransNew->getSTransaction()->isEquivalent (
601  *tpTrans->getSTransaction()))
602  {
603  tpTransNew.reset ();
604  }
605  tpTrans = std::move (tpTransNew);
606  }
607  }
608  }
609  catch (std::exception&)
610  {
611  // Assume that any exceptions are related to transaction sterilization.
612  tpTrans.reset ();
613  }
614 
615  if (!tpTrans)
616  {
618  "Unable to sterilize transaction.");
619  return ret;
620  }
621  ret.second = std::move (tpTrans);
622  return ret;
623 }
624 
626 {
627  Json::Value jvResult;
628  try
629  {
630  jvResult[jss::tx_json] = tpTrans->getJson (JsonOptions::none);
631  jvResult[jss::tx_blob] = strHex (
632  tpTrans->getSTransaction ()->getSerializer ().peekData ());
633 
634  if (temUNCERTAIN != tpTrans->getResult ())
635  {
636  std::string sToken;
637  std::string sHuman;
638 
639  transResultInfo (tpTrans->getResult (), sToken, sHuman);
640 
641  jvResult[jss::engine_result] = sToken;
642  jvResult[jss::engine_result_code] = tpTrans->getResult ();
643  jvResult[jss::engine_result_message] = sHuman;
644  }
645  }
646  catch (std::exception&)
647  {
648  jvResult = RPC::make_error (rpcINTERNAL,
649  "Exception occurred during JSON handling.");
650  }
651  return jvResult;
652 }
653 
654 } // detail
655 
656 //------------------------------------------------------------------------------
657 
659  Json::Value& request,
660  Role const role,
661  bool doAutoFill,
662  Config const& config,
663  LoadFeeTrack const& feeTrack,
664  TxQ const& txQ,
665  std::shared_ptr<OpenView const> const& ledger)
666 {
667  Json::Value& tx (request[jss::tx_json]);
668  if (tx.isMember (jss::Fee))
669  return Json::Value();
670 
671  if (! doAutoFill)
672  return RPC::missing_field_error ("tx_json.Fee");
673 
676  if (request.isMember (jss::fee_mult_max))
677  {
678  if (request[jss::fee_mult_max].isInt())
679  {
680  mult = request[jss::fee_mult_max].asInt();
681  if (mult < 0)
683  RPC::expected_field_message(jss::fee_mult_max,
684  "a positive integer"));
685  }
686  else
687  {
689  RPC::expected_field_message (jss::fee_mult_max,
690  "a positive integer"));
691  }
692  }
693  if (request.isMember(jss::fee_div_max))
694  {
695  if (request[jss::fee_div_max].isInt())
696  {
697  div = request[jss::fee_div_max].asInt();
698  if (div <= 0)
700  RPC::expected_field_message(jss::fee_div_max,
701  "a positive integer"));
702  }
703  else
704  {
706  RPC::expected_field_message(jss::fee_div_max,
707  "a positive integer"));
708  }
709  }
710 
711  // Default fee in fee units.
712  FeeUnit32 const feeDefault = config.TRANSACTION_FEE_BASE;
713 
714  // Administrative and identified endpoints are exempt from local fees.
715  XRPAmount const loadFee =
716  scaleFeeLoad (feeDefault, feeTrack,
717  ledger->fees(), isUnlimited (role));
718  XRPAmount fee = loadFee;
719  {
720  auto const metrics = txQ.getMetrics(*ledger);
721  auto const baseFee = ledger->fees().base;
722  auto escalatedFee = toDrops(
723  metrics.openLedgerFeeLevel - FeeLevel64{ 1 }, baseFee).second +
724  1;
725  fee = std::max(fee, escalatedFee);
726  }
727 
728  auto const limit = [&]()
729  {
730  // Scale fee units to drops:
731  auto const drops = mulDiv (feeDefault,
732  ledger->fees().base, ledger->fees().units);
733  if (!drops.first)
734  Throw<std::overflow_error>("mulDiv");
735  auto const result = mulDiv (drops.second, mult, div);
736  if (!result.first)
737  Throw<std::overflow_error>("mulDiv");
738  return result.second;
739  }();
740 
741  if (fee > limit)
742  {
744  ss << "Fee of " << fee
745  << " exceeds the requested tx limit of " << limit;
746  return RPC::make_error (rpcHIGH_FEE, ss.str());
747  }
748 
749  tx [jss::Fee] = fee.jsonClipped();
750  return Json::Value();
751 }
752 
753 //------------------------------------------------------------------------------
754 
757  Json::Value jvRequest,
758  NetworkOPs::FailHard failType,
759  Role role,
760  std::chrono::seconds validatedLedgerAge,
761  Application& app)
762 {
763  using namespace detail;
764 
765  auto const& ledger = app.openLedger().current();
766  auto j = app.journal ("RPCHandler");
767  JLOG (j.debug()) << "transactionSign: " << jvRequest;
768 
769  // Add and amend fields based on the transaction type.
770  SigningForParams signForParams;
771  transactionPreProcessResult preprocResult = transactionPreProcessImpl (
772  jvRequest, role, signForParams,
773  validatedLedgerAge, app, ledger);
774 
775  if (!preprocResult.second)
776  return preprocResult.first;
777 
778  // Make sure the STTx makes a legitimate Transaction.
781  preprocResult.second, ledger->rules(), app);
782 
783  if (!txn.second)
784  return txn.first;
785 
786  return transactionFormatResultImpl (txn.second);
787 }
788 
791  Json::Value jvRequest,
792  NetworkOPs::FailHard failType,
793  Role role,
794  std::chrono::seconds validatedLedgerAge,
795  Application& app,
796  ProcessTransactionFn const& processTransaction)
797 {
798  using namespace detail;
799 
800  auto const& ledger = app.openLedger().current();
801  auto j = app.journal ("RPCHandler");
802  JLOG (j.debug()) << "transactionSubmit: " << jvRequest;
803 
804 
805  // Add and amend fields based on the transaction type.
806  SigningForParams signForParams;
807  transactionPreProcessResult preprocResult = transactionPreProcessImpl (
808  jvRequest, role, signForParams, validatedLedgerAge, app, ledger);
809 
810  if (!preprocResult.second)
811  return preprocResult.first;
812 
813  // Make sure the STTx makes a legitimate Transaction.
816  preprocResult.second, ledger->rules(), app);
817 
818  if (!txn.second)
819  return txn.first;
820 
821  // Finally, submit the transaction.
822  try
823  {
824  // FIXME: For performance, should use asynch interface
825  processTransaction (
826  txn.second, isUnlimited (role), true, failType);
827  }
828  catch (std::exception&)
829  {
831  "Exception occurred during transaction submission.");
832  }
833 
834  return transactionFormatResultImpl (txn.second);
835 }
836 
837 namespace detail
838 {
839 // There are a some field checks shared by transactionSignFor
840 // and transactionSubmitMultiSigned. Gather them together here.
842 {
843  if (! jvRequest.isMember (jss::tx_json))
844  return RPC::missing_field_error (jss::tx_json);
845 
846  Json::Value const& tx_json (jvRequest [jss::tx_json]);
847 
848  if (!tx_json.isObject())
849  return RPC::invalid_field_message (jss::tx_json);
850 
851  // There are a couple of additional fields we need to check before
852  // we serialize. If we serialize first then we generate less useful
853  //error messages.
854  if (!tx_json.isMember (jss::Sequence))
855  return RPC::missing_field_error ("tx_json.Sequence");
856 
857  if (!tx_json.isMember (sfSigningPubKey.getJsonName()))
858  return RPC::missing_field_error ("tx_json.SigningPubKey");
859 
860  if (!tx_json[sfSigningPubKey.getJsonName()].asString().empty())
862  "When multi-signing 'tx_json.SigningPubKey' must be empty.");
863 
864  return Json::Value ();
865 }
866 
867 // Sort and validate an stSigners array.
868 //
869 // Returns a null Json::Value if there are no errors.
871  STArray& signers, AccountID const& signingForID)
872 {
873  if (signers.empty ())
874  return RPC::make_param_error ("Signers array may not be empty.");
875 
876  // Signers must be sorted by Account.
877  std::sort (signers.begin(), signers.end(),
878  [](STObject const& a, STObject const& b)
879  {
880  return (a[sfAccount] < b[sfAccount]);
881  });
882 
883  // Signers may not contain any duplicates.
884  auto const dupIter = std::adjacent_find (
885  signers.begin(), signers.end(),
886  [] (STObject const& a, STObject const& b)
887  {
888  return (a[sfAccount] == b[sfAccount]);
889  });
890 
891  if (dupIter != signers.end())
892  {
893  std::ostringstream err;
894  err << "Duplicate Signers:Signer:Account entries ("
895  << toBase58((*dupIter)[sfAccount])
896  << ") are not allowed.";
897  return RPC::make_param_error(err.str ());
898  }
899 
900  // An account may not sign for itself.
901  if (signers.end() != std::find_if (signers.begin(), signers.end(),
902  [&signingForID](STObject const& elem)
903  {
904  return elem[sfAccount] == signingForID;
905  }))
906  {
907  std::ostringstream err;
908  err << "A Signer may not be the transaction's Account ("
909  << toBase58(signingForID) << ").";
910  return RPC::make_param_error(err.str ());
911  }
912  return {};
913 }
914 
915 } // detail
916 
919  Json::Value jvRequest,
920  NetworkOPs::FailHard failType,
921  Role role,
922  std::chrono::seconds validatedLedgerAge,
923  Application& app)
924 {
925  auto const& ledger = app.openLedger().current();
926  auto j = app.journal ("RPCHandler");
927  JLOG (j.debug()) << "transactionSignFor: " << jvRequest;
928 
929  // Verify presence of the signer's account field.
930  const char accountField[] = "account";
931 
932  if (! jvRequest.isMember (accountField))
933  return RPC::missing_field_error (accountField);
934 
935  // Turn the signer's account into an AccountID for multi-sign.
936  auto const signerAccountID = parseBase58<AccountID>(
937  jvRequest[accountField].asString());
938  if (! signerAccountID)
939  {
941  RPC::invalid_field_message (accountField));
942  }
943 
944  if (! jvRequest.isMember (jss::tx_json))
945  return RPC::missing_field_error (jss::tx_json);
946 
947  {
948  Json::Value& tx_json (jvRequest [jss::tx_json]);
949 
950  if (!tx_json.isObject())
951  return RPC::object_field_error (jss::tx_json);
952 
953  // If the tx_json.SigningPubKey field is missing,
954  // insert an empty one.
955  if (!tx_json.isMember (sfSigningPubKey.getJsonName()))
956  tx_json[sfSigningPubKey.getJsonName()] = "";
957  }
958 
959  // When multi-signing, the "Sequence" and "SigningPubKey" fields must
960  // be passed in by the caller.
961  using namespace detail;
962  {
963  Json::Value err = checkMultiSignFields (jvRequest);
964  if (RPC::contains_error (err))
965  return err;
966  }
967 
968  // Add and amend fields based on the transaction type.
969  Buffer multiSignature;
970  PublicKey multiSignPubKey;
971  SigningForParams signForParams(
972  *signerAccountID, multiSignPubKey, multiSignature);
973 
974  transactionPreProcessResult preprocResult = transactionPreProcessImpl (
975  jvRequest,
976  role,
977  signForParams,
978  validatedLedgerAge,
979  app,
980  ledger);
981 
982  if (!preprocResult.second)
983  return preprocResult.first;
984 
985  {
986  std::shared_ptr<SLE const> account_state = ledger->read(
987  keylet::account(*signerAccountID));
988  // Make sure the account and secret belong together.
989  auto const err = acctMatchesPubKey (
990  account_state,
991  *signerAccountID,
992  multiSignPubKey);
993 
994  if (err != rpcSUCCESS)
995  return rpcError (err);
996  }
997 
998  // Inject the newly generated signature into tx_json.Signers.
999  auto& sttx = preprocResult.second;
1000  {
1001  // Make the signer object that we'll inject.
1002  STObject signer (sfSigner);
1003  signer[sfAccount] = *signerAccountID;
1004  signer.setFieldVL (sfTxnSignature, multiSignature);
1005  signer.setFieldVL (sfSigningPubKey, multiSignPubKey.slice());
1006 
1007  // If there is not yet a Signers array, make one.
1008  if (!sttx->isFieldPresent (sfSigners))
1009  sttx->setFieldArray (sfSigners, {});
1010 
1011  auto& signers = sttx->peekFieldArray (sfSigners);
1012  signers.emplace_back (std::move (signer));
1013 
1014  // The array must be sorted and validated.
1015  auto err = sortAndValidateSigners (signers, (*sttx)[sfAccount]);
1016  if (RPC::contains_error (err))
1017  return err;
1018  }
1019 
1020  // Make sure the STTx makes a legitimate Transaction.
1022  transactionConstructImpl (sttx, ledger->rules(), app);
1023 
1024  if (!txn.second)
1025  return txn.first;
1026 
1027  return transactionFormatResultImpl (txn.second);
1028 }
1029 
1032  Json::Value jvRequest,
1033  NetworkOPs::FailHard failType,
1034  Role role,
1035  std::chrono::seconds validatedLedgerAge,
1036  Application& app,
1037  ProcessTransactionFn const& processTransaction)
1038 {
1039  auto const& ledger = app.openLedger().current();
1040  auto j = app.journal ("RPCHandler");
1041  JLOG (j.debug())
1042  << "transactionSubmitMultiSigned: " << jvRequest;
1043 
1044  // When multi-signing, the "Sequence" and "SigningPubKey" fields must
1045  // be passed in by the caller.
1046  using namespace detail;
1047  {
1048  Json::Value err = checkMultiSignFields (jvRequest);
1049  if (RPC::contains_error (err))
1050  return err;
1051  }
1052 
1053  Json::Value& tx_json (jvRequest ["tx_json"]);
1054 
1055  auto [txJsonResult, srcAddressID] = checkTxJsonFields (
1056  tx_json, role, true, validatedLedgerAge,
1057  app.config(), app.getFeeTrack());
1058 
1059  if (RPC::contains_error (txJsonResult))
1060  return std::move (txJsonResult);
1061 
1062  std::shared_ptr<SLE const> sle = ledger->read(
1063  keylet::account(srcAddressID));
1064 
1065  if (!sle)
1066  {
1067  // If did not find account, error.
1068  JLOG (j.debug())
1069  << "transactionSubmitMultiSigned: Failed to find source account "
1070  << "in current ledger: "
1071  << toBase58(srcAddressID);
1072 
1073  return rpcError (rpcSRC_ACT_NOT_FOUND);
1074  }
1075 
1076  {
1077  Json::Value err = checkFee (
1078  jvRequest, role, false, app.config(), app.getFeeTrack(),
1079  app.getTxQ(), ledger);
1080 
1081  if (RPC::contains_error(err))
1082  return err;
1083 
1084  err = checkPayment (
1085  jvRequest,
1086  tx_json,
1087  srcAddressID,
1088  role,
1089  app,
1090  ledger,
1091  false);
1092 
1093  if (RPC::contains_error(err))
1094  return err;
1095  }
1096 
1097  // Grind through the JSON in tx_json to produce a STTx.
1098  std::shared_ptr<STTx> stpTrans;
1099  {
1100  STParsedJSONObject parsedTx_json ("tx_json", tx_json);
1101  if (!parsedTx_json.object)
1102  {
1103  Json::Value jvResult;
1104  jvResult ["error"] = parsedTx_json.error ["error"];
1105  jvResult ["error_code"] = parsedTx_json.error ["error_code"];
1106  jvResult ["error_message"] = parsedTx_json.error ["error_message"];
1107  return jvResult;
1108  }
1109  try
1110  {
1111  stpTrans = std::make_shared<STTx>(
1112  std::move(parsedTx_json.object.get()));
1113  }
1114  catch (STObject::FieldErr& err)
1115  {
1116  return RPC::make_error (rpcINVALID_PARAMS, err.what());
1117  }
1118  catch (std::exception& ex)
1119  {
1120  std::string reason (ex.what ());
1121  return RPC::make_error (rpcINTERNAL,
1122  "Exception while serializing transaction: " + reason);
1123  }
1124  std::string reason;
1125  if (!passesLocalChecks (*stpTrans, reason))
1126  return RPC::make_error (rpcINVALID_PARAMS, reason);
1127  }
1128 
1129  // Validate the fields in the serialized transaction.
1130  {
1131  // We now have the transaction text serialized and in the right format.
1132  // Verify the values of select fields.
1133  //
1134  // The SigningPubKey must be present but empty.
1135  if (!stpTrans->getFieldVL (sfSigningPubKey).empty ())
1136  {
1137  std::ostringstream err;
1138  err << "Invalid " << sfSigningPubKey.fieldName
1139  << " field. Field must be empty when multi-signing.";
1140  return RPC::make_error (rpcINVALID_PARAMS, err.str ());
1141  }
1142 
1143  // There may not be a TxnSignature field.
1144  if (stpTrans->isFieldPresent (sfTxnSignature))
1145  return rpcError (rpcSIGNING_MALFORMED);
1146 
1147  // The Fee field must be in XRP and greater than zero.
1148  auto const fee = stpTrans->getFieldAmount (sfFee);
1149 
1150  if (!isLegalNet (fee))
1151  {
1152  std::ostringstream err;
1153  err << "Invalid " << sfFee.fieldName
1154  << " field. Fees must be specified in XRP.";
1155  return RPC::make_error (rpcINVALID_PARAMS, err.str ());
1156  }
1157  if (fee <= STAmount{0})
1158  {
1159  std::ostringstream err;
1160  err << "Invalid " << sfFee.fieldName
1161  << " field. Fees must be greater than zero.";
1162  return RPC::make_error (rpcINVALID_PARAMS, err.str ());
1163  }
1164  }
1165 
1166  // Verify that the Signers field is present.
1167  if (! stpTrans->isFieldPresent (sfSigners))
1168  return RPC::missing_field_error ("tx_json.Signers");
1169 
1170  // If the Signers field is present the SField guarantees it to be an array.
1171  // Get a reference to the Signers array so we can verify and sort it.
1172  auto& signers = stpTrans->peekFieldArray (sfSigners);
1173 
1174  if (signers.empty ())
1175  return RPC::make_param_error("tx_json.Signers array may not be empty.");
1176 
1177  // The Signers array may only contain Signer objects.
1178  if (std::find_if_not(signers.begin(), signers.end(), [](STObject const& obj)
1179  {
1180  return (
1181  // A Signer object always contains these fields and no others.
1182  obj.isFieldPresent (sfAccount) &&
1183  obj.isFieldPresent (sfSigningPubKey) &&
1184  obj.isFieldPresent (sfTxnSignature) &&
1185  obj.getCount() == 3);
1186  }) != signers.end())
1187  {
1188  return RPC::make_param_error (
1189  "Signers array may only contain Signer entries.");
1190  }
1191 
1192  // The array must be sorted and validated.
1193  auto err = sortAndValidateSigners (signers, srcAddressID);
1194  if (RPC::contains_error (err))
1195  return err;
1196 
1197  // Make sure the SerializedTransaction makes a legitimate Transaction.
1199  transactionConstructImpl (stpTrans, ledger->rules(), app);
1200 
1201  if (!txn.second)
1202  return txn.first;
1203 
1204  // Finally, submit the transaction.
1205  try
1206  {
1207  // FIXME: For performance, should use asynch interface
1208  processTransaction (
1209  txn.second, isUnlimited (role), true, failType);
1210  }
1211  catch (std::exception&)
1212  {
1213  return RPC::make_error (rpcINTERNAL,
1214  "Exception occurred during transaction submission.");
1215  }
1216 
1217  return transactionFormatResultImpl (txn.second);
1218 }
1219 
1220 } // RPC
1221 } // ripple
ripple::RPC::detail::SigningForParams::multiSigningAcctID_
AccountID const *const multiSigningAcctID_
Definition: TransactionSign.cpp:54
ripple::Application
Definition: Application.h:85
ripple::Application::checkSigs
virtual bool checkSigs() const =0
ripple::sfRegularKey
const SF_Account sfRegularKey(access, STI_ACCOUNT, 8, "RegularKey")
Definition: SField.h:467
ripple::amountFromJsonNoThrow
bool amountFromJsonNoThrow(STAmount &result, Json::Value const &jvSource)
Definition: STAmount.cpp:911
ripple::makeSlice
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Definition: Slice.h:199
ripple::OpenLedger::current
std::shared_ptr< OpenView const > current() const
Returns a view to the current open ledger.
Definition: OpenLedger.cpp:52
ripple::RPC::detail::SigningForParams::SigningForParams
SigningForParams()
Definition: TransactionSign.cpp:59
Json::Value::isObject
bool isObject() const
Definition: json_value.cpp:1069
std::string
STL class.
std::shared_ptr
STL class.
ripple::RPC::transactionSignFor
Json::Value transactionSignFor(Json::Value jvRequest, NetworkOPs::FailHard failType, Role role, std::chrono::seconds validatedLedgerAge, Application &app)
Returns a Json::objectValue.
Definition: TransactionSign.cpp:918
ripple::rpcINVALID_PARAMS
@ rpcINVALID_PARAMS
Definition: ErrorCodes.h:85
std::exception
STL class.
ripple::lsfDisableMaster
@ lsfDisableMaster
Definition: LedgerFormats.h:136
ripple::RPC::missing_field_message
std::string missing_field_message(std::string const &name)
Definition: ErrorCodes.h:224
ripple::Pathfinder
Calculates payment paths.
Definition: Pathfinder.h:37
ripple::sfSigners
const SField sfSigners(access, STI_ARRAY, 3, "Signers", SField::sMD_Default, SField::notSigning)
Definition: SField.h:495
ripple::Slice
An immutable linear range of bytes.
Definition: Slice.h:43
ripple::rpcSRC_ACT_NOT_FOUND
@ rpcSRC_ACT_NOT_FOUND
Definition: ErrorCodes.h:123
std::pair
ripple::RPC::detail::SigningForParams::editFields
bool editFields() const
Definition: TransactionSign.cpp:89
ripple::RPC::detail::SigningForParams::multiSignPublicKey_
PublicKey *const multiSignPublicKey_
Definition: TransactionSign.cpp:55
ripple::sfSigningPubKey
const SF_Blob sfSigningPubKey(access, STI_VL, 3, "SigningPubKey")
Definition: SField.h:442
std::vector< unsigned char >
std::find_if
T find_if(T... args)
ripple::sfSequence
const SF_U32 sfSequence(access, STI_UINT32, 4, "Sequence")
Definition: SField.h:340
ripple::SField::fieldName
const std::string fieldName
Definition: SField.h:136
ripple::rpcSIGNING_MALFORMED
@ rpcSIGNING_MALFORMED
Definition: ErrorCodes.h:119
ripple::RPC::detail::transactionPreProcessResult::second
const std::shared_ptr< STTx > second
Definition: TransactionSign.cpp:316
ripple::sfAccount
const SF_Account sfAccount(access, STI_ACCOUNT, 1, "Account")
Definition: SField.h:460
std::chrono::seconds
iterator
ripple::NEW
@ NEW
Definition: Transaction.h:45
ripple::Issue::currency
Currency currency
Definition: Issue.h:37
ripple::toBase58
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition: AccountID.cpp:29
ripple::RPC::detail::transactionPreProcessResult::first
const Json::Value first
Definition: TransactionSign.cpp:315
std::stringstream
STL class.
ripple::RPC::detail::checkPayment
static Json::Value checkPayment(Json::Value const &params, Json::Value &tx_json, AccountID const &srcAddressID, Role const role, Application &app, std::shared_ptr< ReadView const > const &ledger, bool doPath)
Definition: TransactionSign.cpp:148
ripple::scaleFeeLoad
XRPAmount scaleFeeLoad(FeeUnit64 fee, LoadFeeTrack const &feeTrack, Fees const &fees, bool bUnlimited)
Definition: LoadFeeTrack.cpp:89
ripple::RPC::checkFee
Json::Value checkFee(Json::Value &request, Role const role, bool doAutoFill, Config const &config, LoadFeeTrack const &feeTrack, TxQ const &txQ, std::shared_ptr< OpenView const > const &ledger)
Fill in the fee on behalf of the client.
Definition: TransactionSign.cpp:658
ripple::PublicKey::slice
Slice slice() const noexcept
Definition: PublicKey.h:123
ripple::Pathfinder::findPaths
bool findPaths(int searchLevel)
Definition: Pathfinder.cpp:173
ripple::rpcTOO_BUSY
@ rpcTOO_BUSY
Definition: ErrorCodes.h:57
ripple::Buffer
Like std::vector<char> but better.
Definition: Buffer.h:35
ripple::STParsedJSONObject
Holds the serialized result of parsing an input JSON object.
Definition: STParsedJSON.h:31
ripple::isLegalNet
bool isLegalNet(STAmount const &value)
Definition: STAmount.h:325
std::function
Json::Value::end
const_iterator end() const
Definition: json_value.cpp:1107
ripple::STObject::setFieldVL
void setFieldVL(SField const &field, Blob const &)
Definition: STObject.cpp:631
ripple::sfSigner
const SField sfSigner(access, STI_OBJECT, 16, "Signer")
Definition: SField.h:489
ripple::STAmount::setIssuer
void setIssuer(AccountID const &uIssuer)
Definition: STAmount.h:243
ripple::SField::getJsonName
Json::StaticString const & getJsonName() const
Definition: SField.h:178
ripple::Application::openLedger
virtual OpenLedger & openLedger()=0
ripple::RPC::transactionSign
Json::Value transactionSign(Json::Value jvRequest, NetworkOPs::FailHard failType, Role role, std::chrono::seconds validatedLedgerAge, Application &app)
Returns a Json::objectValue.
Definition: TransactionSign.cpp:756
ripple::SField::jsonName
const Json::StaticString jsonName
Definition: SField.h:140
std::sort
T sort(T... args)
ripple::RPC::detail::transactionConstructImpl
static std::pair< Json::Value, Transaction::pointer > transactionConstructImpl(std::shared_ptr< STTx const > const &stpTrans, Rules const &rules, Application &app)
Definition: TransactionSign.cpp:551
std::shared_ptr::reset
T reset(T... args)
ripple::STPathSet
Definition: STPathSet.h:297
ripple::RPC::object_field_error
Json::Value object_field_error(std::string const &name)
Definition: ErrorCodes.h:244
algorithm
ripple::error_code_i
error_code_i
Definition: ErrorCodes.h:40
ripple::forceValidity
void forceValidity(HashRouter &router, uint256 const &txid, Validity validity)
Sets the validity of a given transaction in the cache.
Definition: apply.cpp:87
ripple::STPathSet::empty
bool empty() const
Definition: STPathSet.h:377
ripple::RPC::detail::transactionPreProcessResult::transactionPreProcessResult
transactionPreProcessResult(std::shared_ptr< STTx > &&st)
Definition: TransactionSign.cpp:335
ripple::Application::getFeeTrack
virtual LoadFeeTrack & getFeeTrack()=0
ripple::STParsedJSONObject::error
Json::Value error
On failure, an appropriate set of error values.
Definition: STParsedJSON.h:52
ripple::RPC::detail::SigningForParams::setPublicKey
void setPublicKey(PublicKey const &multiSignPublicKey)
Definition: TransactionSign.cpp:100
Json::Value::asBool
bool asBool() const
Definition: json_value.cpp:626
ripple::temUNCERTAIN
@ temUNCERTAIN
Definition: TER.h:121
ripple::Validity::SigGoodOnly
@ SigGoodOnly
Signature is good, but local checks fail.
ripple::RPC::detail::acctMatchesPubKey
static error_code_i acctMatchesPubKey(std::shared_ptr< SLE const > accountState, AccountID const &accountID, PublicKey const &publicKey)
Definition: TransactionSign.cpp:113
ripple::RPC::missing_field_error
Json::Value missing_field_error(std::string const &name)
Definition: ErrorCodes.h:229
ripple::Pathfinder::getBestPaths
STPathSet getBestPaths(int maxPaths, STPath &fullLiquidityPath, STPathSet const &extraPaths, AccountID const &srcIssuer)
Definition: Pathfinder.cpp:555
ripple::RPC::detail::SigningForParams::getSigner
AccountID const & getSigner()
Definition: TransactionSign.cpp:95
ripple::verify
bool verify(PublicKey const &publicKey, Slice const &m, Slice const &sig, bool mustBeFullyCanonical)
Verify a signature on a message.
Definition: PublicKey.cpp:277
ripple::base_uint< 160, detail::AccountIDTag >
ripple::RPC::detail::transactionFormatResultImpl
static Json::Value transactionFormatResultImpl(Transaction::pointer tpTrans)
Definition: TransactionSign.cpp:625
ripple::RPC::expected_field_message
std::string expected_field_message(std::string const &name, std::string const &type)
Definition: ErrorCodes.h:274
ripple::rpcSUCCESS
@ rpcSUCCESS
Definition: ErrorCodes.h:45
ripple::STObject::FieldErr
Definition: STObject.h:264
ripple::RPC::transactionSubmit
Json::Value transactionSubmit(Json::Value jvRequest, NetworkOPs::FailHard failType, Role role, std::chrono::seconds validatedLedgerAge, Application &app, ProcessTransactionFn const &processTransaction)
Returns a Json::objectValue.
Definition: TransactionSign.cpp:790
ripple::TxQ
Transaction Queue.
Definition: TxQ.h:54
ripple::checkValidity
std::pair< Validity, std::string > checkValidity(HashRouter &router, STTx const &tx, Rules const &rules, Config const &config)
Checks transaction signature and local checks.
Definition: apply.cpp:37
ripple::passesLocalChecks
bool passesLocalChecks(STObject const &st, std::string &reason)
Definition: STTx.cpp:496
ripple::RPC::contains_error
bool contains_error(Json::Value const &json)
Returns true if the json contains an rpc error specification.
Definition: ErrorCodes.cpp:196
ripple::PublicKey
A public key.
Definition: PublicKey.h:59
ripple::Config
Definition: Config.h:67
ripple::Pathfinder::computePathRanks
void computePathRanks(int maxPaths)
Compute the rankings of the paths.
Definition: Pathfinder.cpp:402
ripple::Config::TRANSACTION_FEE_BASE
static constexpr FeeUnit32 TRANSACTION_FEE_BASE
Definition: Config.h:137
ripple::keylet::account
static const account_t account
Definition: Indexes.h:116
ripple::rpcSRC_ACT_MISSING
@ rpcSRC_ACT_MISSING
Definition: ErrorCodes.h:122
ripple::JsonOptions::none
@ none
ripple::Application::config
virtual Config & config()=0
ripple::rpcALREADY_SINGLE_SIG
@ rpcALREADY_SINGLE_SIG
Definition: ErrorCodes.h:93
ripple::RPC::detail::sortAndValidateSigners
static Json::Value sortAndValidateSigners(STArray &signers, AccountID const &signingForID)
Definition: TransactionSign.cpp:870
ripple::Config::standalone
bool standalone() const
Definition: Config.h:204
ripple::rpcHIGH_FEE
@ rpcHIGH_FEE
Definition: ErrorCodes.h:59
ripple::calcAccountID
AccountID calcAccountID(PublicKey const &pk)
Definition: AccountID.cpp:136
ripple::STArray
Definition: STArray.h:28
ripple::Application::getTxQ
virtual TxQ & getTxQ()=0
ripple::LoadFeeTrack
Manages the current fee schedule.
Definition: LoadFeeTrack.h:43
ripple::tfFullyCanonicalSig
const std::uint32_t tfFullyCanonicalSig
Definition: TxFlags.h:48
ripple::sfTxnSignature
const SF_Blob sfTxnSignature(access, STI_VL, 4, "TxnSignature", SField::sMD_Default, SField::notSigning)
Definition: SField.h:443
ripple::STAmount
Definition: STAmount.h:42
ripple::Serializer::slice
Slice slice() const noexcept
Definition: Serializer.h:67
ripple::RPC::detail::transactionPreProcessResult
Definition: TransactionSign.cpp:313
ripple::TxQ::getAccountTxs
std::map< TxSeq, AccountTxDetails const > getAccountTxs(AccountID const &account, ReadView const &view) const
Returns information about the transactions currently in the queue for the account.
Definition: TxQ.cpp:1417
ripple::SerialIter
Definition: Serializer.h:311
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::rpcNO_CURRENT
@ rpcNO_CURRENT
Definition: ErrorCodes.h:66
ripple::feeunit::TaggedFee
Definition: FeeUnits.h:72
ripple::STParsedJSONObject::object
boost::optional< STObject > object
The STObject if the parse was successful.
Definition: STParsedJSON.h:49
ripple::rpcALREADY_MULTISIG
@ rpcALREADY_MULTISIG
Definition: ErrorCodes.h:92
ripple::NetworkOPs::FailHard
FailHard
Definition: NetworkOPs.h:98
ripple::rpcError
Json::Value rpcError(int iError, Json::Value jvResult)
Definition: RPCErr.cpp:28
ripple::sfFee
const SF_Amount sfFee(access, STI_AMOUNT, 8, "Fee")
Definition: SField.h:430
ripple::Config::PATH_SEARCH_OLD
int PATH_SEARCH_OLD
Definition: Config.h:152
ripple::rpcINTERNAL
@ rpcINTERNAL
Definition: ErrorCodes.h:131
ripple::isUnlimited
bool isUnlimited(Role const &role)
ADMIN and IDENTIFIED roles shall have unlimited resources.
Definition: Role.cpp:86
ripple::RPC::detail::transactionPreProcessImpl
static transactionPreProcessResult transactionPreProcessImpl(Json::Value &params, Role role, SigningForParams &signingArgs, std::chrono::seconds validatedLedgerAge, Application &app, std::shared_ptr< OpenView const > const &ledger)
Definition: TransactionSign.cpp:343
ripple::Serializer
Definition: Serializer.h:43
std::ostringstream
STL class.
ripple::RPC::detail::transactionPreProcessResult::transactionPreProcessResult
transactionPreProcessResult(Json::Value &&json)
Definition: TransactionSign.cpp:330
ripple::RPC::invalid_field_message
std::string invalid_field_message(std::string const &name)
Definition: ErrorCodes.h:254
ripple::STObject
Definition: STObject.h:51
ripple::rpcSRC_ACT_MALFORMED
@ rpcSRC_ACT_MALFORMED
Definition: ErrorCodes.h:121
ripple::STAmount::native
bool native() const noexcept
Definition: STAmount.h:153
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::transResultInfo
bool transResultInfo(TER code, std::string &token, std::string &text)
Definition: TER.cpp:169
ripple::RPC::LegacyPathFind::isOk
bool isOk() const
Definition: LegacyPathFind.h:37
ripple::Application::journal
virtual beast::Journal journal(std::string const &name)=0
ripple::Validity::Valid
@ Valid
Signature and local checks are good / passed.
ripple::sign
Buffer sign(PublicKey const &pk, SecretKey const &sk, Slice const &m)
Generate a signature for a message.
Definition: SecretKey.cpp:132
ripple::RPC::detail::SigningForParams::multiSignature_
Buffer *const multiSignature_
Definition: TransactionSign.cpp:56
ripple::RPC::detail::SigningForParams::moveMultiSignature
void moveMultiSignature(Buffer &&multiSignature)
Definition: TransactionSign.cpp:105
ripple::STAmount::issue
Issue const & issue() const
Definition: STAmount.h:156
std
STL namespace.
ripple::RPC::keypairForSignature
std::pair< PublicKey, SecretKey > keypairForSignature(Json::Value const &params, Json::Value &error)
Definition: RPCHelpers.cpp:659
ripple::toDrops
std::pair< bool, XRPAmount > toDrops(FeeLevel< T > const &level, XRPAmount const &baseFee)
Definition: TxQ.h:765
ripple::LoadFeeTrack::isLoadedCluster
bool isLoadedCluster() const
Definition: LoadFeeTrack.h:119
ripple::STPathSet::getJson
Json::Value getJson(JsonOptions) const override
Definition: STPathSet.cpp:180
ripple::RPC::detail::SigningForParams::isSingleSigning
bool isSingleSigning() const
Definition: TransactionSign.cpp:83
std::adjacent_find
T adjacent_find(T... args)
ripple::RPC::detail::SigningForParams::isMultiSigning
bool isMultiSigning() const
Definition: TransactionSign.cpp:76
std::string::empty
T empty(T... args)
ripple::Rules
Rules controlling protocol behavior.
Definition: ReadView.h:126
ripple::RPC::detail::checkMultiSignFields
static Json::Value checkMultiSignFields(Json::Value const &jvRequest)
Definition: TransactionSign.cpp:841
std::stringstream::str
T str(T... args)
ripple::RPC::detail::transactionPreProcessResult::transactionPreProcessResult
transactionPreProcessResult(transactionPreProcessResult &&rhs)
Definition: TransactionSign.cpp:320
ripple::RPC::detail::SigningForParams::SigningForParams
SigningForParams(AccountID const &multiSigningAcctID, PublicKey &multiSignPublicKey, Buffer &multiSignature)
Definition: TransactionSign.cpp:67
Json::Value::asInt
Int asInt() const
Definition: json_value.cpp:516
ripple::strHex
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:70
ripple::Serializer::getData
Blob getData() const
Definition: Serializer.h:177
ripple::mulDiv
std::pair< bool, Dest > mulDiv(Source1 value, Dest mul, Source2 div)
Definition: FeeUnits.h:487
std::max
T max(T... args)
ripple::TxQ::getMetrics
Metrics getMetrics(OpenView const &view) const
Returns fee metrics in reference fee level units.
Definition: TxQ.cpp:1358
ripple::RPC::make_param_error
Json::Value make_param_error(std::string const &message)
Returns a new json object that indicates invalid parameters.
Definition: ErrorCodes.h:219
ripple::RPC::detail::SigningForParams
Definition: TransactionSign.cpp:51
ripple::rpcBAD_SECRET
@ rpcBAD_SECRET
Definition: ErrorCodes.h:99
ripple::RPC::detail::checkTxJsonFields
static std::pair< Json::Value, AccountID > checkTxJsonFields(Json::Value const &tx_json, Role const role, bool const verify, std::chrono::seconds validatedLedgerAge, Config const &config, LoadFeeTrack const &feeTrack)
Definition: TransactionSign.cpp:250
Json::Value::begin
const_iterator begin() const
Definition: json_value.cpp:1089
ripple::RPC::Tuning::defaultAutoFillFeeMultiplier
static constexpr int defaultAutoFillFeeMultiplier
Definition: rpc/impl/Tuning.h:53
ripple::STPath
Definition: STPathSet.h:205
ripple::RPC::invalid_field_error
Json::Value invalid_field_error(std::string const &name)
Definition: ErrorCodes.h:264
ripple::Application::getHashRouter
virtual HashRouter & getHashRouter()=0
ripple::RPC::Tuning::defaultAutoFillFeeDivisor
static constexpr int defaultAutoFillFeeDivisor
Definition: rpc/impl/Tuning.h:54
ripple::Role
Role
Indicates the level of administrative permission to grant.
Definition: Role.h:40
ripple::rpcMASTER_DISABLED
@ rpcMASTER_DISABLED
Definition: ErrorCodes.h:75
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
ripple::RPC::Tuning::maxValidatedLedgerAge
constexpr auto maxValidatedLedgerAge
Definition: rpc/impl/Tuning.h:58
ripple::RPC::LegacyPathFind
Definition: LegacyPathFind.h:31
ripple::XRPAmount::jsonClipped
Json::Value jsonClipped() const
Definition: XRPAmount.h:223
ripple::buildMultiSigningData
Serializer buildMultiSigningData(STObject const &obj, AccountID const &signingID)
Return a Serializer suitable for computing a multisigning TxnSignature.
Definition: Sign.cpp:83
ripple::Issue::account
AccountID account
Definition: Issue.h:38
std::runtime_error::what
T what(T... args)
Json::Value
Represents a JSON value.
Definition: json_value.h:141
ripple::XRPAmount
Definition: XRPAmount.h:46
ripple::RPC::transactionSubmitMultiSigned
Json::Value transactionSubmitMultiSigned(Json::Value jvRequest, NetworkOPs::FailHard failType, Role role, std::chrono::seconds validatedLedgerAge, Application &app, ProcessTransactionFn const &processTransaction)
Returns a Json::objectValue.
Definition: TransactionSign.cpp:1031
ripple::RPC::detail::transactionPreProcessResult::transactionPreProcessResult
transactionPreProcessResult()=delete
Json::Value::asString
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:482