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  // DeliverMax is an alias to Amount and we use Amount internally
171  if (tx_json.isMember(jss::DeliverMax))
172  {
173  if (tx_json.isMember(jss::Amount))
174  {
175  if (tx_json[jss::DeliverMax] != tx_json[jss::Amount])
176  return RPC::make_error(
178  "Cannot specify differing 'Amount' and 'DeliverMax'");
179  }
180  else
181  tx_json[jss::Amount] = tx_json[jss::DeliverMax];
182 
183  tx_json.removeMember(jss::DeliverMax);
184  }
185 
186  if (!tx_json.isMember(jss::Amount))
187  return RPC::missing_field_error("tx_json.Amount");
188 
189  STAmount amount;
190 
191  if (!amountFromJsonNoThrow(amount, tx_json[jss::Amount]))
192  return RPC::invalid_field_error("tx_json.Amount");
193 
194  if (!tx_json.isMember(jss::Destination))
195  return RPC::missing_field_error("tx_json.Destination");
196 
197  auto const dstAccountID =
198  parseBase58<AccountID>(tx_json[jss::Destination].asString());
199  if (!dstAccountID)
200  return RPC::invalid_field_error("tx_json.Destination");
201 
202  if ((doPath == false) && params.isMember(jss::build_path))
203  return RPC::make_error(
205  "Field 'build_path' not allowed in this context.");
206 
207  if (tx_json.isMember(jss::Paths) && params.isMember(jss::build_path))
208  return RPC::make_error(
210  "Cannot specify both 'tx_json.Paths' and 'build_path'");
211 
212  if (!tx_json.isMember(jss::Paths) && params.isMember(jss::build_path))
213  {
214  STAmount sendMax;
215 
216  if (tx_json.isMember(jss::SendMax))
217  {
218  if (!amountFromJsonNoThrow(sendMax, tx_json[jss::SendMax]))
219  return RPC::invalid_field_error("tx_json.SendMax");
220  }
221  else
222  {
223  // If no SendMax, default to Amount with sender as issuer.
224  sendMax = amount;
225  sendMax.setIssuer(srcAddressID);
226  }
227 
228  if (sendMax.native() && amount.native())
229  return RPC::make_error(
230  rpcINVALID_PARAMS, "Cannot build XRP to XRP paths.");
231 
232  {
233  LegacyPathFind lpf(isUnlimited(role), app);
234  if (!lpf.isOk())
235  return rpcError(rpcTOO_BUSY);
236 
237  STPathSet result;
238 
239  if (auto ledger = app.openLedger().current())
240  {
241  Pathfinder pf(
242  std::make_shared<RippleLineCache>(
243  ledger, app.journal("RippleLineCache")),
244  srcAddressID,
245  *dstAccountID,
246  sendMax.issue().currency,
247  sendMax.issue().account,
248  amount,
249  std::nullopt,
250  app);
251  if (pf.findPaths(app.config().PATH_SEARCH_OLD))
252  {
253  // 4 is the maxium paths
254  pf.computePathRanks(4);
255  STPath fullLiquidityPath;
256  STPathSet paths;
257  result = pf.getBestPaths(
258  4, fullLiquidityPath, paths, sendMax.issue().account);
259  }
260  }
261 
262  auto j = app.journal("RPCHandler");
263  JLOG(j.debug()) << "transactionSign: build_path: "
264  << result.getJson(JsonOptions::none);
265 
266  if (!result.empty())
267  tx_json[jss::Paths] = result.getJson(JsonOptions::none);
268  }
269  }
270  return Json::Value();
271 }
272 
273 //------------------------------------------------------------------------------
274 
275 // Validate (but don't modify) the contents of the tx_json.
276 //
277 // Returns a pair<Json::Value, AccountID>. The Json::Value will contain error
278 // information if there was an error. On success, the account ID is returned
279 // and the Json::Value will be empty.
280 //
281 // This code does not check the "Sequence" field, since the expectations
282 // for that field are particularly context sensitive.
285  Json::Value const& tx_json,
286  Role const role,
287  bool const verify,
288  std::chrono::seconds validatedLedgerAge,
289  Config const& config,
290  LoadFeeTrack const& feeTrack,
291  unsigned apiVersion)
292 {
294 
295  if (!tx_json.isObject())
296  {
297  ret.first = RPC::object_field_error(jss::tx_json);
298  return ret;
299  }
300 
301  if (!tx_json.isMember(jss::TransactionType))
302  {
303  ret.first = RPC::missing_field_error("tx_json.TransactionType");
304  return ret;
305  }
306 
307  if (!tx_json.isMember(jss::Account))
308  {
309  ret.first = RPC::make_error(
310  rpcSRC_ACT_MISSING, RPC::missing_field_message("tx_json.Account"));
311  return ret;
312  }
313 
314  auto const srcAddressID =
315  parseBase58<AccountID>(tx_json[jss::Account].asString());
316 
317  if (!srcAddressID)
318  {
319  ret.first = RPC::make_error(
321  RPC::invalid_field_message("tx_json.Account"));
322  return ret;
323  }
324 
325  // Check for current ledger.
326  if (verify && !config.standalone() &&
327  (validatedLedgerAge > Tuning::maxValidatedLedgerAge))
328  {
329  if (apiVersion == 1)
331  else
333  return ret;
334  }
335 
336  // Check for load.
337  if (feeTrack.isLoadedCluster() && !isUnlimited(role))
338  {
339  ret.first = rpcError(rpcTOO_BUSY);
340  return ret;
341  }
342 
343  // It's all good. Return the AccountID.
344  ret.second = *srcAddressID;
345  return ret;
346 }
347 
348 //------------------------------------------------------------------------------
349 
350 // A move-only struct that makes it easy to return either a Json::Value or a
351 // std::shared_ptr<STTx const> from transactionPreProcessImpl ().
353 {
356 
357  transactionPreProcessResult() = delete;
360 
362  operator=(transactionPreProcessResult const&) = delete;
365 
367  : first(std::move(json)), second()
368  {
369  }
370 
372  : first(), second(std::move(st))
373  {
374  }
375 };
376 
377 static transactionPreProcessResult
379  Json::Value& params,
380  Role role,
381  SigningForParams& signingArgs,
382  std::chrono::seconds validatedLedgerAge,
383  Application& app)
384 {
385  auto j = app.journal("RPCHandler");
386 
387  Json::Value jvResult;
388  auto const [pk, sk] = keypairForSignature(params, jvResult);
389  if (contains_error(jvResult))
390  return jvResult;
391 
392  bool const verify =
393  !(params.isMember(jss::offline) && params[jss::offline].asBool());
394 
395  if (!params.isMember(jss::tx_json))
396  return RPC::missing_field_error(jss::tx_json);
397 
398  Json::Value& tx_json(params[jss::tx_json]);
399 
400  // Check tx_json fields, but don't add any.
401  auto [txJsonResult, srcAddressID] = checkTxJsonFields(
402  tx_json,
403  role,
404  verify,
405  validatedLedgerAge,
406  app.config(),
407  app.getFeeTrack(),
408  getAPIVersionNumber(params, app.config().BETA_RPC_API));
409 
410  if (RPC::contains_error(txJsonResult))
411  return std::move(txJsonResult);
412 
413  // This test covers the case where we're offline so the sequence number
414  // cannot be determined locally. If we're offline then the caller must
415  // provide the sequence number.
416  if (!verify && !tx_json.isMember(jss::Sequence))
417  return RPC::missing_field_error("tx_json.Sequence");
418 
420  if (verify)
421  sle = app.openLedger().current()->read(keylet::account(srcAddressID));
422 
423  if (verify && !sle)
424  {
425  // If not offline and did not find account, error.
426  JLOG(j.debug()) << "transactionSign: Failed to find source account "
427  << "in current ledger: " << toBase58(srcAddressID);
428 
430  }
431 
432  {
433  Json::Value err = checkFee(
434  params,
435  role,
436  verify && signingArgs.editFields(),
437  app.config(),
438  app.getFeeTrack(),
439  app.getTxQ(),
440  app);
441 
442  if (RPC::contains_error(err))
443  return err;
444 
445  err = checkPayment(
446  params,
447  tx_json,
448  srcAddressID,
449  role,
450  app,
451  verify && signingArgs.editFields());
452 
453  if (RPC::contains_error(err))
454  return err;
455  }
456 
457  if (signingArgs.editFields())
458  {
459  if (!tx_json.isMember(jss::Sequence))
460  {
461  bool const hasTicketSeq =
463  if (!hasTicketSeq && !sle)
464  {
465  JLOG(j.debug())
466  << "transactionSign: Failed to find source account "
467  << "in current ledger: " << toBase58(srcAddressID);
468 
470  }
471  tx_json[jss::Sequence] =
472  hasTicketSeq ? 0 : app.getTxQ().nextQueuableSeq(sle).value();
473  }
474 
475  if (!tx_json.isMember(jss::Flags))
476  tx_json[jss::Flags] = tfFullyCanonicalSig;
477  }
478 
479  // If multisigning there should not be a single signature and vice versa.
480  if (signingArgs.isMultiSigning())
481  {
482  if (tx_json.isMember(sfTxnSignature.jsonName))
484 
485  // If multisigning then we need to return the public key.
486  signingArgs.setPublicKey(pk);
487  }
488  else if (signingArgs.isSingleSigning())
489  {
490  if (tx_json.isMember(sfSigners.jsonName))
492  }
493 
494  if (verify)
495  {
496  if (!sle)
497  // XXX Ignore transactions for accounts not created.
499 
500  JLOG(j.trace()) << "verify: " << toBase58(calcAccountID(pk)) << " : "
501  << toBase58(srcAddressID);
502 
503  // Don't do this test if multisigning since the account and secret
504  // probably don't belong together in that case.
505  if (!signingArgs.isMultiSigning())
506  {
507  // Make sure the account and secret belong together.
508  auto const err = acctMatchesPubKey(sle, srcAddressID, pk);
509 
510  if (err != rpcSUCCESS)
511  return rpcError(err);
512  }
513  }
514 
515  STParsedJSONObject parsed(std::string(jss::tx_json), tx_json);
516  if (!parsed.object.has_value())
517  {
518  Json::Value err;
519  err[jss::error] = parsed.error[jss::error];
520  err[jss::error_code] = parsed.error[jss::error_code];
521  err[jss::error_message] = parsed.error[jss::error_message];
522  return err;
523  }
524 
525  std::shared_ptr<STTx> stpTrans;
526  try
527  {
528  // If we're generating a multi-signature the SigningPubKey must be
529  // empty, otherwise it must be the master account's public key.
530  parsed.object->setFieldVL(
532  signingArgs.isMultiSigning() ? Slice(nullptr, 0) : pk.slice());
533 
534  stpTrans = std::make_shared<STTx>(std::move(parsed.object.value()));
535  }
536  catch (STObject::FieldErr& err)
537  {
538  return RPC::make_error(rpcINVALID_PARAMS, err.what());
539  }
540  catch (std::exception&)
541  {
542  return RPC::make_error(
543  rpcINTERNAL,
544  "Exception occurred constructing serialized transaction");
545  }
546 
547  std::string reason;
548  if (!passesLocalChecks(*stpTrans, reason))
549  return RPC::make_error(rpcINVALID_PARAMS, reason);
550 
551  // If multisign then return multiSignature, else set TxnSignature field.
552  if (signingArgs.isMultiSigning())
553  {
554  Serializer s =
555  buildMultiSigningData(*stpTrans, signingArgs.getSigner());
556 
557  auto multisig = ripple::sign(pk, sk, s.slice());
558 
559  signingArgs.moveMultiSignature(std::move(multisig));
560  }
561  else if (signingArgs.isSingleSigning())
562  {
563  stpTrans->sign(pk, sk);
564  }
565 
566  return transactionPreProcessResult{std::move(stpTrans)};
567 }
568 
571  std::shared_ptr<STTx const> const& stpTrans,
572  Rules const& rules,
573  Application& app)
574 {
576 
577  // Turn the passed in STTx into a Transaction.
578  Transaction::pointer tpTrans;
579  {
580  std::string reason;
581  tpTrans = std::make_shared<Transaction>(stpTrans, reason, app);
582  if (tpTrans->getStatus() != NEW)
583  {
584  ret.first = RPC::make_error(
585  rpcINTERNAL, "Unable to construct transaction: " + reason);
586  return ret;
587  }
588  }
589  try
590  {
591  // Make sure the Transaction we just built is legit by serializing it
592  // and then de-serializing it. If the result isn't equivalent
593  // to the initial transaction then there's something wrong with the
594  // passed-in STTx.
595  {
596  Serializer s;
597  tpTrans->getSTransaction()->add(s);
598  Blob transBlob = s.getData();
599  SerialIter sit{makeSlice(transBlob)};
600 
601  // Check the signature if that's called for.
602  auto sttxNew = std::make_shared<STTx const>(sit);
603  if (!app.checkSigs())
605  app.getHashRouter(),
606  sttxNew->getTransactionID(),
608  if (checkValidity(
609  app.getHashRouter(), *sttxNew, rules, app.config())
610  .first != Validity::Valid)
611  {
612  ret.first = RPC::make_error(rpcINTERNAL, "Invalid signature.");
613  return ret;
614  }
615 
616  std::string reason;
617  auto tpTransNew =
618  std::make_shared<Transaction>(sttxNew, reason, app);
619 
620  if (tpTransNew)
621  {
622  if (!tpTransNew->getSTransaction()->isEquivalent(
623  *tpTrans->getSTransaction()))
624  {
625  tpTransNew.reset();
626  }
627  tpTrans = std::move(tpTransNew);
628  }
629  }
630  }
631  catch (std::exception&)
632  {
633  // Assume that any exceptions are related to transaction sterilization.
634  tpTrans.reset();
635  }
636 
637  if (!tpTrans)
638  {
639  ret.first =
640  RPC::make_error(rpcINTERNAL, "Unable to sterilize transaction.");
641  return ret;
642  }
643  ret.second = std::move(tpTrans);
644  return ret;
645 }
646 
647 static Json::Value
649 {
650  Json::Value jvResult;
651  try
652  {
653  if (apiVersion > 1)
654  {
655  jvResult[jss::tx_json] =
656  tpTrans->getJson(JsonOptions::disable_API_prior_V2);
657  jvResult[jss::hash] = to_string(tpTrans->getID());
658  }
659  else
660  jvResult[jss::tx_json] = tpTrans->getJson(JsonOptions::none);
661 
662  jvResult[jss::tx_blob] =
663  strHex(tpTrans->getSTransaction()->getSerializer().peekData());
664 
665  if (temUNCERTAIN != tpTrans->getResult())
666  {
667  std::string sToken;
668  std::string sHuman;
669 
670  transResultInfo(tpTrans->getResult(), sToken, sHuman);
671 
672  jvResult[jss::engine_result] = sToken;
673  jvResult[jss::engine_result_code] = tpTrans->getResult();
674  jvResult[jss::engine_result_message] = sHuman;
675  }
676  }
677  catch (std::exception&)
678  {
679  jvResult = RPC::make_error(
680  rpcINTERNAL, "Exception occurred during JSON handling.");
681  }
682  return jvResult;
683 }
684 
685 } // namespace detail
686 
687 //------------------------------------------------------------------------------
688 
691  Json::Value& request,
692  Role const role,
693  bool doAutoFill,
694  Config const& config,
695  LoadFeeTrack const& feeTrack,
696  TxQ const& txQ,
697  Application const& app)
698 {
699  Json::Value& tx(request[jss::tx_json]);
700  if (tx.isMember(jss::Fee))
701  return Json::Value();
702 
703  if (!doAutoFill)
704  return RPC::missing_field_error("tx_json.Fee");
705 
708  if (request.isMember(jss::fee_mult_max))
709  {
710  if (request[jss::fee_mult_max].isInt())
711  {
712  mult = request[jss::fee_mult_max].asInt();
713  if (mult < 0)
714  return RPC::make_error(
717  jss::fee_mult_max, "a positive integer"));
718  }
719  else
720  {
721  return RPC::make_error(
722  rpcHIGH_FEE,
724  jss::fee_mult_max, "a positive integer"));
725  }
726  }
727  if (request.isMember(jss::fee_div_max))
728  {
729  if (request[jss::fee_div_max].isInt())
730  {
731  div = request[jss::fee_div_max].asInt();
732  if (div <= 0)
733  return RPC::make_error(
736  jss::fee_div_max, "a positive integer"));
737  }
738  else
739  {
740  return RPC::make_error(
741  rpcHIGH_FEE,
743  jss::fee_div_max, "a positive integer"));
744  }
745  }
746 
747  XRPAmount const feeDefault = config.FEES.reference_fee;
748 
749  auto ledger = app.openLedger().current();
750  // Administrative and identified endpoints are exempt from local fees.
751  XRPAmount const loadFee =
752  scaleFeeLoad(feeDefault, feeTrack, ledger->fees(), isUnlimited(role));
753  XRPAmount fee = loadFee;
754  {
755  auto const metrics = txQ.getMetrics(*ledger);
756  auto const baseFee = ledger->fees().base;
757  auto escalatedFee =
758  toDrops(metrics.openLedgerFeeLevel - FeeLevel64(1), baseFee) + 1;
759  fee = std::max(fee, escalatedFee);
760  }
761 
762  auto const limit = [&]() {
763  // Scale fee units to drops:
764  auto const result = mulDiv(feeDefault, mult, div);
765  if (!result)
766  Throw<std::overflow_error>("mulDiv");
767  return *result;
768  }();
769 
770  if (fee > limit)
771  {
773  ss << "Fee of " << fee << " exceeds the requested tx limit of "
774  << limit;
775  return RPC::make_error(rpcHIGH_FEE, ss.str());
776  }
777 
778  tx[jss::Fee] = fee.jsonClipped();
779  return Json::Value();
780 }
781 
782 //------------------------------------------------------------------------------
783 
787  Json::Value jvRequest,
788  unsigned apiVersion,
789  NetworkOPs::FailHard failType,
790  Role role,
791  std::chrono::seconds validatedLedgerAge,
792  Application& app)
793 {
794  using namespace detail;
795 
796  auto j = app.journal("RPCHandler");
797  JLOG(j.debug()) << "transactionSign: " << jvRequest;
798 
799  // Add and amend fields based on the transaction type.
800  SigningForParams signForParams;
801  transactionPreProcessResult preprocResult = transactionPreProcessImpl(
802  jvRequest, role, signForParams, validatedLedgerAge, app);
803 
804  if (!preprocResult.second)
805  return preprocResult.first;
806 
808  if (app.config().reporting())
809  ledger = app.getLedgerMaster().getValidatedLedger();
810  else
811  ledger = app.openLedger().current();
812  // Make sure the STTx makes a legitimate Transaction.
814  transactionConstructImpl(preprocResult.second, ledger->rules(), app);
815 
816  if (!txn.second)
817  return txn.first;
818 
819  return transactionFormatResultImpl(txn.second, apiVersion);
820 }
821 
825  Json::Value jvRequest,
826  unsigned apiVersion,
827  NetworkOPs::FailHard failType,
828  Role role,
829  std::chrono::seconds validatedLedgerAge,
830  Application& app,
831  ProcessTransactionFn const& processTransaction,
832  RPC::SubmitSync sync)
833 {
834  using namespace detail;
835 
836  auto const& ledger = app.openLedger().current();
837  auto j = app.journal("RPCHandler");
838  JLOG(j.debug()) << "transactionSubmit: " << jvRequest;
839 
840  // Add and amend fields based on the transaction type.
841  SigningForParams signForParams;
842  transactionPreProcessResult preprocResult = transactionPreProcessImpl(
843  jvRequest, role, signForParams, validatedLedgerAge, app);
844 
845  if (!preprocResult.second)
846  return preprocResult.first;
847 
848  // Make sure the STTx makes a legitimate Transaction.
850  transactionConstructImpl(preprocResult.second, ledger->rules(), app);
851 
852  if (!txn.second)
853  return txn.first;
854 
855  // Finally, submit the transaction.
856  try
857  {
858  processTransaction(txn.second, isUnlimited(role), sync, failType);
859  }
860  catch (std::exception&)
861  {
862  return RPC::make_error(
863  rpcINTERNAL, "Exception occurred during transaction submission.");
864  }
865 
866  return transactionFormatResultImpl(txn.second, apiVersion);
867 }
868 
869 namespace detail {
870 // There are a some field checks shared by transactionSignFor
871 // and transactionSubmitMultiSigned. Gather them together here.
872 static Json::Value
874 {
875  if (!jvRequest.isMember(jss::tx_json))
876  return RPC::missing_field_error(jss::tx_json);
877 
878  Json::Value const& tx_json(jvRequest[jss::tx_json]);
879 
880  if (!tx_json.isObject())
881  return RPC::invalid_field_message(jss::tx_json);
882 
883  // There are a couple of additional fields we need to check before
884  // we serialize. If we serialize first then we generate less useful
885  // error messages.
886  if (!tx_json.isMember(jss::Sequence))
887  return RPC::missing_field_error("tx_json.Sequence");
888 
889  if (!tx_json.isMember(sfSigningPubKey.getJsonName()))
890  return RPC::missing_field_error("tx_json.SigningPubKey");
891 
892  if (!tx_json[sfSigningPubKey.getJsonName()].asString().empty())
893  return RPC::make_error(
895  "When multi-signing 'tx_json.SigningPubKey' must be empty.");
896 
897  return Json::Value();
898 }
899 
900 // Sort and validate an stSigners array.
901 //
902 // Returns a null Json::Value if there are no errors.
903 static Json::Value
904 sortAndValidateSigners(STArray& signers, AccountID const& signingForID)
905 {
906  if (signers.empty())
907  return RPC::make_param_error("Signers array may not be empty.");
908 
909  // Signers must be sorted by Account.
910  std::sort(
911  signers.begin(),
912  signers.end(),
913  [](STObject const& a, STObject const& b) {
914  return (a[sfAccount] < b[sfAccount]);
915  });
916 
917  // Signers may not contain any duplicates.
918  auto const dupIter = std::adjacent_find(
919  signers.begin(),
920  signers.end(),
921  [](STObject const& a, STObject const& b) {
922  return (a[sfAccount] == b[sfAccount]);
923  });
924 
925  if (dupIter != signers.end())
926  {
927  std::ostringstream err;
928  err << "Duplicate Signers:Signer:Account entries ("
929  << toBase58((*dupIter)[sfAccount]) << ") are not allowed.";
930  return RPC::make_param_error(err.str());
931  }
932 
933  // An account may not sign for itself.
934  if (signers.end() !=
935  std::find_if(
936  signers.begin(),
937  signers.end(),
938  [&signingForID](STObject const& elem) {
939  return elem[sfAccount] == signingForID;
940  }))
941  {
942  std::ostringstream err;
943  err << "A Signer may not be the transaction's Account ("
944  << toBase58(signingForID) << ").";
945  return RPC::make_param_error(err.str());
946  }
947  return {};
948 }
949 
950 } // namespace detail
951 
955  Json::Value jvRequest,
956  unsigned apiVersion,
957  NetworkOPs::FailHard failType,
958  Role role,
959  std::chrono::seconds validatedLedgerAge,
960  Application& app)
961 {
962  auto const& ledger = app.openLedger().current();
963  auto j = app.journal("RPCHandler");
964  JLOG(j.debug()) << "transactionSignFor: " << jvRequest;
965 
966  // Verify presence of the signer's account field.
967  const char accountField[] = "account";
968 
969  if (!jvRequest.isMember(accountField))
970  return RPC::missing_field_error(accountField);
971 
972  // Turn the signer's account into an AccountID for multi-sign.
973  auto const signerAccountID =
974  parseBase58<AccountID>(jvRequest[accountField].asString());
975  if (!signerAccountID)
976  {
977  return RPC::make_error(
979  }
980 
981  if (!jvRequest.isMember(jss::tx_json))
982  return RPC::missing_field_error(jss::tx_json);
983 
984  {
985  Json::Value& tx_json(jvRequest[jss::tx_json]);
986 
987  if (!tx_json.isObject())
988  return RPC::object_field_error(jss::tx_json);
989 
990  // If the tx_json.SigningPubKey field is missing,
991  // insert an empty one.
992  if (!tx_json.isMember(sfSigningPubKey.getJsonName()))
993  tx_json[sfSigningPubKey.getJsonName()] = "";
994  }
995 
996  // When multi-signing, the "Sequence" and "SigningPubKey" fields must
997  // be passed in by the caller.
998  using namespace detail;
999  {
1000  Json::Value err = checkMultiSignFields(jvRequest);
1001  if (RPC::contains_error(err))
1002  return err;
1003  }
1004 
1005  // Add and amend fields based on the transaction type.
1006  Buffer multiSignature;
1007  PublicKey multiSignPubKey;
1008  SigningForParams signForParams(
1009  *signerAccountID, multiSignPubKey, multiSignature);
1010 
1011  transactionPreProcessResult preprocResult = transactionPreProcessImpl(
1012  jvRequest, role, signForParams, validatedLedgerAge, app);
1013 
1014  if (!preprocResult.second)
1015  return preprocResult.first;
1016 
1017  {
1018  std::shared_ptr<SLE const> account_state =
1019  ledger->read(keylet::account(*signerAccountID));
1020  // Make sure the account and secret belong together.
1021  auto const err =
1022  acctMatchesPubKey(account_state, *signerAccountID, multiSignPubKey);
1023 
1024  if (err != rpcSUCCESS)
1025  return rpcError(err);
1026  }
1027 
1028  // Inject the newly generated signature into tx_json.Signers.
1029  auto& sttx = preprocResult.second;
1030  {
1031  // Make the signer object that we'll inject.
1032  STObject signer(sfSigner);
1033  signer[sfAccount] = *signerAccountID;
1034  signer.setFieldVL(sfTxnSignature, multiSignature);
1035  signer.setFieldVL(sfSigningPubKey, multiSignPubKey.slice());
1036 
1037  // If there is not yet a Signers array, make one.
1038  if (!sttx->isFieldPresent(sfSigners))
1039  sttx->setFieldArray(sfSigners, {});
1040 
1041  auto& signers = sttx->peekFieldArray(sfSigners);
1042  signers.emplace_back(std::move(signer));
1043 
1044  // The array must be sorted and validated.
1045  auto err = sortAndValidateSigners(signers, (*sttx)[sfAccount]);
1046  if (RPC::contains_error(err))
1047  return err;
1048  }
1049 
1050  // Make sure the STTx makes a legitimate Transaction.
1052  transactionConstructImpl(sttx, ledger->rules(), app);
1053 
1054  if (!txn.second)
1055  return txn.first;
1056 
1057  return transactionFormatResultImpl(txn.second, apiVersion);
1058 }
1059 
1063  Json::Value jvRequest,
1064  unsigned apiVersion,
1065  NetworkOPs::FailHard failType,
1066  Role role,
1067  std::chrono::seconds validatedLedgerAge,
1068  Application& app,
1069  ProcessTransactionFn const& processTransaction,
1070  RPC::SubmitSync sync)
1071 {
1072  auto const& ledger = app.openLedger().current();
1073  auto j = app.journal("RPCHandler");
1074  JLOG(j.debug()) << "transactionSubmitMultiSigned: " << jvRequest;
1075 
1076  // When multi-signing, the "Sequence" and "SigningPubKey" fields must
1077  // be passed in by the caller.
1078  using namespace detail;
1079  {
1080  Json::Value err = checkMultiSignFields(jvRequest);
1081  if (RPC::contains_error(err))
1082  return err;
1083  }
1084 
1085  Json::Value& tx_json(jvRequest["tx_json"]);
1086 
1087  auto [txJsonResult, srcAddressID] = checkTxJsonFields(
1088  tx_json,
1089  role,
1090  true,
1091  validatedLedgerAge,
1092  app.config(),
1093  app.getFeeTrack(),
1094  getAPIVersionNumber(jvRequest, app.config().BETA_RPC_API));
1095 
1096  if (RPC::contains_error(txJsonResult))
1097  return std::move(txJsonResult);
1098 
1100  ledger->read(keylet::account(srcAddressID));
1101 
1102  if (!sle)
1103  {
1104  // If did not find account, error.
1105  JLOG(j.debug())
1106  << "transactionSubmitMultiSigned: Failed to find source account "
1107  << "in current ledger: " << toBase58(srcAddressID);
1108 
1110  }
1111 
1112  {
1113  Json::Value err = checkFee(
1114  jvRequest,
1115  role,
1116  false,
1117  app.config(),
1118  app.getFeeTrack(),
1119  app.getTxQ(),
1120  app);
1121 
1122  if (RPC::contains_error(err))
1123  return err;
1124 
1125  err = checkPayment(jvRequest, tx_json, srcAddressID, role, app, false);
1126 
1127  if (RPC::contains_error(err))
1128  return err;
1129  }
1130 
1131  // Grind through the JSON in tx_json to produce a STTx.
1132  std::shared_ptr<STTx> stpTrans;
1133  {
1134  STParsedJSONObject parsedTx_json("tx_json", tx_json);
1135  if (!parsedTx_json.object)
1136  {
1137  Json::Value jvResult;
1138  jvResult["error"] = parsedTx_json.error["error"];
1139  jvResult["error_code"] = parsedTx_json.error["error_code"];
1140  jvResult["error_message"] = parsedTx_json.error["error_message"];
1141  return jvResult;
1142  }
1143  try
1144  {
1145  stpTrans =
1146  std::make_shared<STTx>(std::move(parsedTx_json.object.value()));
1147  }
1148  catch (STObject::FieldErr& err)
1149  {
1150  return RPC::make_error(rpcINVALID_PARAMS, err.what());
1151  }
1152  catch (std::exception& ex)
1153  {
1154  std::string reason(ex.what());
1155  return RPC::make_error(
1156  rpcINTERNAL,
1157  "Exception while serializing transaction: " + reason);
1158  }
1159  std::string reason;
1160  if (!passesLocalChecks(*stpTrans, reason))
1161  return RPC::make_error(rpcINVALID_PARAMS, reason);
1162  }
1163 
1164  // Validate the fields in the serialized transaction.
1165  {
1166  // We now have the transaction text serialized and in the right format.
1167  // Verify the values of select fields.
1168  //
1169  // The SigningPubKey must be present but empty.
1170  if (!stpTrans->getFieldVL(sfSigningPubKey).empty())
1171  {
1172  std::ostringstream err;
1173  err << "Invalid " << sfSigningPubKey.fieldName
1174  << " field. Field must be empty when multi-signing.";
1175  return RPC::make_error(rpcINVALID_PARAMS, err.str());
1176  }
1177 
1178  // There may not be a TxnSignature field.
1179  if (stpTrans->isFieldPresent(sfTxnSignature))
1181 
1182  // The Fee field must be in XRP and greater than zero.
1183  auto const fee = stpTrans->getFieldAmount(sfFee);
1184 
1185  if (!isLegalNet(fee))
1186  {
1187  std::ostringstream err;
1188  err << "Invalid " << sfFee.fieldName
1189  << " field. Fees must be specified in XRP.";
1190  return RPC::make_error(rpcINVALID_PARAMS, err.str());
1191  }
1192  if (fee <= STAmount{0})
1193  {
1194  std::ostringstream err;
1195  err << "Invalid " << sfFee.fieldName
1196  << " field. Fees must be greater than zero.";
1197  return RPC::make_error(rpcINVALID_PARAMS, err.str());
1198  }
1199  }
1200 
1201  // Verify that the Signers field is present.
1202  if (!stpTrans->isFieldPresent(sfSigners))
1203  return RPC::missing_field_error("tx_json.Signers");
1204 
1205  // If the Signers field is present the SField guarantees it to be an array.
1206  // Get a reference to the Signers array so we can verify and sort it.
1207  auto& signers = stpTrans->peekFieldArray(sfSigners);
1208 
1209  if (signers.empty())
1210  return RPC::make_param_error("tx_json.Signers array may not be empty.");
1211 
1212  // The Signers array may only contain Signer objects.
1213  if (std::find_if_not(
1214  signers.begin(), signers.end(), [](STObject const& obj) {
1215  return (
1216  // A Signer object always contains these fields and no
1217  // others.
1218  obj.isFieldPresent(sfAccount) &&
1219  obj.isFieldPresent(sfSigningPubKey) &&
1220  obj.isFieldPresent(sfTxnSignature) && obj.getCount() == 3);
1221  }) != signers.end())
1222  {
1223  return RPC::make_param_error(
1224  "Signers array may only contain Signer entries.");
1225  }
1226 
1227  // The array must be sorted and validated.
1228  auto err = sortAndValidateSigners(signers, srcAddressID);
1229  if (RPC::contains_error(err))
1230  return err;
1231 
1232  // Make sure the SerializedTransaction makes a legitimate Transaction.
1234  transactionConstructImpl(stpTrans, ledger->rules(), app);
1235 
1236  if (!txn.second)
1237  return txn.first;
1238 
1239  // Finally, submit the transaction.
1240  try
1241  {
1242  // FIXME: For performance, should use asynch interface
1243  processTransaction(txn.second, isUnlimited(role), sync, failType);
1244  }
1245  catch (std::exception&)
1246  {
1247  return RPC::make_error(
1248  rpcINTERNAL, "Exception occurred during transaction submission.");
1249  }
1250 
1251  return transactionFormatResultImpl(txn.second, apiVersion);
1252 }
1253 
1254 } // namespace RPC
1255 } // namespace ripple
ripple::JsonOptions::disable_API_prior_V2
@ disable_API_prior_V2
Definition: STBase.h:44
ripple::RPC::detail::SigningForParams::multiSigningAcctID_
AccountID const *const multiSigningAcctID_
Definition: TransactionSign.cpp:54
ripple::FeeSetup::reference_fee
XRPAmount reference_fee
The cost of a reference transaction in drops.
Definition: Config.h:75
ripple::Application
Definition: Application.h:116
ripple::Application::checkSigs
virtual bool checkSigs() const =0
ripple::amountFromJsonNoThrow
bool amountFromJsonNoThrow(STAmount &result, Json::Value const &jvSource)
Definition: STAmount.cpp:1032
ripple::RPC::SubmitSync
SubmitSync
Possible values for defining synchronous behavior of the transaction submission API.
Definition: SubmitSync.h:36
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::mulDiv
std::optional< Dest > mulDiv(Source1 value, Dest mul, Source2 div)
Definition: FeeUnits.h:468
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::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:260
ripple::STAmount::issue
Issue const & issue() const
Definition: STAmount.h:350
ripple::RPC::missing_field_message
std::string missing_field_message(std::string const &name)
Definition: ErrorCodes.h:258
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:272
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:992
std::vector< unsigned char >
std::find_if
T find_if(T... args)
ripple::SField::fieldName
const std::string fieldName
Definition: SField.h:159
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:355
std::chrono::seconds
iterator
ripple::NEW
@ NEW
Definition: Transaction.h:47
ripple::Issue::currency
Currency currency
Definition: Issue.h:38
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:58
ripple::RPC::detail::transactionPreProcessResult::first
const Json::Value first
Definition: TransactionSign.cpp:354
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, bool doPath)
Definition: TransactionSign.cpp:158
ripple::PublicKey::slice
Slice slice() const noexcept
Definition: PublicKey.h:125
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:449
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:436
ripple::SField::getJsonName
Json::StaticString const & getJsonName() const
Definition: SField.h:214
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::SField::jsonName
const Json::StaticString jsonName
Definition: SField.h:163
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:570
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:282
algorithm
ripple::error_code_i
error_code_i
Definition: ErrorCodes.h:40
ripple::RPC::transactionSubmitMultiSigned
Json::Value transactionSubmitMultiSigned(Json::Value jvRequest, unsigned apiVersion, NetworkOPs::FailHard failType, Role role, std::chrono::seconds validatedLedgerAge, Application &app, ProcessTransactionFn const &processTransaction, RPC::SubmitSync sync)
Returns a Json::objectValue.
Definition: TransactionSign.cpp:1062
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:371
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:122
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:264
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:690
ripple::base_uint< 160, detail::AccountIDTag >
ripple::RPC::keypairForSignature
std::pair< PublicKey, SecretKey > keypairForSignature(Json::Value const &params, Json::Value &error, unsigned int apiVersion)
Definition: RPCHelpers.cpp:796
ripple::RPC::expected_field_message
std::string expected_field_message(std::string const &name, std::string const &type)
Definition: ErrorCodes.h:318
ripple::rpcSUCCESS
@ rpcSUCCESS
Definition: ErrorCodes.h:44
ripple::STObject::FieldErr
Definition: STObject.h:647
ripple::Config::reporting
bool reporting() const
Definition: Config.h:351
ripple::RPC::detail::transactionPreProcessImpl
static transactionPreProcessResult transactionPreProcessImpl(Json::Value &params, Role role, SigningForParams &signingArgs, std::chrono::seconds validatedLedgerAge, Application &app)
Definition: TransactionSign.cpp:378
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:547
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::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:284
ripple::Application::getLedgerMaster
virtual LedgerMaster & getLedgerMaster()=0
ripple::PublicKey
A public key.
Definition: PublicKey.h:61
ripple::keylet::account
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:142
ripple::Config
Definition: Config.h:92
ripple::RPC::transactionSubmit
Json::Value transactionSubmit(Json::Value jvRequest, unsigned apiVersion, NetworkOPs::FailHard failType, Role role, std::chrono::seconds validatedLedgerAge, Application &app, ProcessTransactionFn const &processTransaction, RPC::SubmitSync sync)
Returns a Json::objectValue.
Definition: TransactionSign.cpp:824
ripple::rpcSRC_ACT_MISSING
@ rpcSRC_ACT_MISSING
Definition: ErrorCodes.h:121
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:904
ripple::Config::standalone
bool standalone() const
Definition: Config.h:346
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::RPC::transactionSign
Json::Value transactionSign(Json::Value jvRequest, unsigned apiVersion, NetworkOPs::FailHard failType, Role role, std::chrono::seconds validatedLedgerAge, Application &app)
Returns a Json::objectValue.
Definition: TransactionSign.cpp:786
ripple::STAmount
Definition: STAmount.h:46
ripple::Serializer::slice
Slice slice() const noexcept
Definition: Serializer.h:64
ripple::Config::BETA_RPC_API
bool BETA_RPC_API
Definition: Config.h:299
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:1587
ripple::RPC::detail::transactionPreProcessResult
Definition: TransactionSign.cpp:352
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:932
ripple::rpcNO_CURRENT
@ rpcNO_CURRENT
Definition: ErrorCodes.h:65
ripple::RPC::transactionSignFor
Json::Value transactionSignFor(Json::Value jvRequest, unsigned apiVersion, NetworkOPs::FailHard failType, Role role, std::chrono::seconds validatedLedgerAge, Application &app)
Returns a Json::objectValue.
Definition: TransactionSign.cpp:954
ripple::feeunit::TaggedFee
Definition: FeeUnits.h:70
ripple::rpcALREADY_MULTISIG
@ rpcALREADY_MULTISIG
Definition: ErrorCodes.h:91
ripple::RPC::SubmitSync::sync
@ sync
ripple::NetworkOPs::FailHard
FailHard
Definition: NetworkOPs.h:95
ripple::sfSigner
const SField sfSigner
ripple::Config::PATH_SEARCH_OLD
int PATH_SEARCH_OLD
Definition: Config.h:205
ripple::RPC::detail::transactionFormatResultImpl
static Json::Value transactionFormatResultImpl(Transaction::pointer tpTrans, unsigned apiVersion)
Definition: TransactionSign.cpp:648
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:40
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:366
ripple::RPC::invalid_field_message
std::string invalid_field_message(std::string const &name)
Definition: ErrorCodes.h:294
ripple::STObject
Definition: STObject.h:53
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:332
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:226
ripple::RPC::LegacyPathFind::isOk
bool isOk() const
Definition: LegacyPathFind.h:38
ripple::Application::journal
virtual beast::Journal journal(std::string const &name)=0
ripple::JsonOptions::none
@ none
Definition: STBase.h:42
Json::Value::removeMember
Value removeMember(const char *key)
Remove and return the named member.
Definition: json_value.cpp:907
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::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:1717
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:873
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::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
ripple::scaleFeeLoad
XRPAmount scaleFeeLoad(XRPAmount fee, LoadFeeTrack const &feeTrack, Fees const &fees, bool bUnlimited)
Definition: LoadFeeTrack.cpp:89
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:174
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:1748
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:252
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::Config::FEES
FeeSetup FEES
Definition: Config.h:214
ripple::RPC::invalid_field_error
Json::Value invalid_field_error(std::string const &name)
Definition: ErrorCodes.h:306
ripple::Application::getHashRouter
virtual HashRouter & getHashRouter()=0
ripple::toDrops
XRPAmount toDrops(FeeLevel< T > const &level, XRPAmount baseFee)
Definition: TxQ.h:863
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:180
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:39
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::detail::transactionPreProcessResult::transactionPreProcessResult
transactionPreProcessResult()=delete
Json::Value::asString
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:469