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