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  jvResult[jss::tx_json] = tpTrans->getJson(JsonOptions::none);
654  jvResult[jss::tx_blob] =
655  strHex(tpTrans->getSTransaction()->getSerializer().peekData());
656 
657  if (temUNCERTAIN != tpTrans->getResult())
658  {
659  std::string sToken;
660  std::string sHuman;
661 
662  transResultInfo(tpTrans->getResult(), sToken, sHuman);
663 
664  jvResult[jss::engine_result] = sToken;
665  jvResult[jss::engine_result_code] = tpTrans->getResult();
666  jvResult[jss::engine_result_message] = sHuman;
667  }
668  }
669  catch (std::exception&)
670  {
671  jvResult = RPC::make_error(
672  rpcINTERNAL, "Exception occurred during JSON handling.");
673  }
674  return jvResult;
675 }
676 
677 } // namespace detail
678 
679 //------------------------------------------------------------------------------
680 
683  Json::Value& request,
684  Role const role,
685  bool doAutoFill,
686  Config const& config,
687  LoadFeeTrack const& feeTrack,
688  TxQ const& txQ,
689  Application const& app)
690 {
691  Json::Value& tx(request[jss::tx_json]);
692  if (tx.isMember(jss::Fee))
693  return Json::Value();
694 
695  if (!doAutoFill)
696  return RPC::missing_field_error("tx_json.Fee");
697 
700  if (request.isMember(jss::fee_mult_max))
701  {
702  if (request[jss::fee_mult_max].isInt())
703  {
704  mult = request[jss::fee_mult_max].asInt();
705  if (mult < 0)
706  return RPC::make_error(
709  jss::fee_mult_max, "a positive integer"));
710  }
711  else
712  {
713  return RPC::make_error(
714  rpcHIGH_FEE,
716  jss::fee_mult_max, "a positive integer"));
717  }
718  }
719  if (request.isMember(jss::fee_div_max))
720  {
721  if (request[jss::fee_div_max].isInt())
722  {
723  div = request[jss::fee_div_max].asInt();
724  if (div <= 0)
725  return RPC::make_error(
728  jss::fee_div_max, "a positive integer"));
729  }
730  else
731  {
732  return RPC::make_error(
733  rpcHIGH_FEE,
735  jss::fee_div_max, "a positive integer"));
736  }
737  }
738 
739  XRPAmount const feeDefault = config.FEES.reference_fee;
740 
741  auto ledger = app.openLedger().current();
742  // Administrative and identified endpoints are exempt from local fees.
743  XRPAmount const loadFee =
744  scaleFeeLoad(feeDefault, feeTrack, ledger->fees(), isUnlimited(role));
745  XRPAmount fee = loadFee;
746  {
747  auto const metrics = txQ.getMetrics(*ledger);
748  auto const baseFee = ledger->fees().base;
749  auto escalatedFee =
750  toDrops(metrics.openLedgerFeeLevel - FeeLevel64(1), baseFee) + 1;
751  fee = std::max(fee, escalatedFee);
752  }
753 
754  auto const limit = [&]() {
755  // Scale fee units to drops:
756  auto const result = mulDiv(feeDefault, mult, div);
757  if (!result)
758  Throw<std::overflow_error>("mulDiv");
759  return *result;
760  }();
761 
762  if (fee > limit)
763  {
765  ss << "Fee of " << fee << " exceeds the requested tx limit of "
766  << limit;
767  return RPC::make_error(rpcHIGH_FEE, ss.str());
768  }
769 
770  tx[jss::Fee] = fee.jsonClipped();
771  return Json::Value();
772 }
773 
774 //------------------------------------------------------------------------------
775 
779  Json::Value jvRequest,
780  NetworkOPs::FailHard failType,
781  Role role,
782  std::chrono::seconds validatedLedgerAge,
783  Application& app)
784 {
785  using namespace detail;
786 
787  auto j = app.journal("RPCHandler");
788  JLOG(j.debug()) << "transactionSign: " << jvRequest;
789 
790  // Add and amend fields based on the transaction type.
791  SigningForParams signForParams;
792  transactionPreProcessResult preprocResult = transactionPreProcessImpl(
793  jvRequest, role, signForParams, validatedLedgerAge, app);
794 
795  if (!preprocResult.second)
796  return preprocResult.first;
797 
799  if (app.config().reporting())
800  ledger = app.getLedgerMaster().getValidatedLedger();
801  else
802  ledger = app.openLedger().current();
803  // Make sure the STTx makes a legitimate Transaction.
805  transactionConstructImpl(preprocResult.second, ledger->rules(), app);
806 
807  if (!txn.second)
808  return txn.first;
809 
811 }
812 
816  Json::Value jvRequest,
817  NetworkOPs::FailHard failType,
818  Role role,
819  std::chrono::seconds validatedLedgerAge,
820  Application& app,
821  ProcessTransactionFn const& processTransaction,
822  RPC::SubmitSync sync)
823 {
824  using namespace detail;
825 
826  auto const& ledger = app.openLedger().current();
827  auto j = app.journal("RPCHandler");
828  JLOG(j.debug()) << "transactionSubmit: " << jvRequest;
829 
830  // Add and amend fields based on the transaction type.
831  SigningForParams signForParams;
832  transactionPreProcessResult preprocResult = transactionPreProcessImpl(
833  jvRequest, role, signForParams, validatedLedgerAge, app);
834 
835  if (!preprocResult.second)
836  return preprocResult.first;
837 
838  // Make sure the STTx makes a legitimate Transaction.
840  transactionConstructImpl(preprocResult.second, ledger->rules(), app);
841 
842  if (!txn.second)
843  return txn.first;
844 
845  // Finally, submit the transaction.
846  try
847  {
848  processTransaction(txn.second, isUnlimited(role), sync, failType);
849  }
850  catch (std::exception&)
851  {
852  return RPC::make_error(
853  rpcINTERNAL, "Exception occurred during transaction submission.");
854  }
855 
857 }
858 
859 namespace detail {
860 // There are a some field checks shared by transactionSignFor
861 // and transactionSubmitMultiSigned. Gather them together here.
862 static Json::Value
864 {
865  if (!jvRequest.isMember(jss::tx_json))
866  return RPC::missing_field_error(jss::tx_json);
867 
868  Json::Value const& tx_json(jvRequest[jss::tx_json]);
869 
870  if (!tx_json.isObject())
871  return RPC::invalid_field_message(jss::tx_json);
872 
873  // There are a couple of additional fields we need to check before
874  // we serialize. If we serialize first then we generate less useful
875  // error messages.
876  if (!tx_json.isMember(jss::Sequence))
877  return RPC::missing_field_error("tx_json.Sequence");
878 
879  if (!tx_json.isMember(sfSigningPubKey.getJsonName()))
880  return RPC::missing_field_error("tx_json.SigningPubKey");
881 
882  if (!tx_json[sfSigningPubKey.getJsonName()].asString().empty())
883  return RPC::make_error(
885  "When multi-signing 'tx_json.SigningPubKey' must be empty.");
886 
887  return Json::Value();
888 }
889 
890 // Sort and validate an stSigners array.
891 //
892 // Returns a null Json::Value if there are no errors.
893 static Json::Value
894 sortAndValidateSigners(STArray& signers, AccountID const& signingForID)
895 {
896  if (signers.empty())
897  return RPC::make_param_error("Signers array may not be empty.");
898 
899  // Signers must be sorted by Account.
900  std::sort(
901  signers.begin(),
902  signers.end(),
903  [](STObject const& a, STObject const& b) {
904  return (a[sfAccount] < b[sfAccount]);
905  });
906 
907  // Signers may not contain any duplicates.
908  auto const dupIter = std::adjacent_find(
909  signers.begin(),
910  signers.end(),
911  [](STObject const& a, STObject const& b) {
912  return (a[sfAccount] == b[sfAccount]);
913  });
914 
915  if (dupIter != signers.end())
916  {
917  std::ostringstream err;
918  err << "Duplicate Signers:Signer:Account entries ("
919  << toBase58((*dupIter)[sfAccount]) << ") are not allowed.";
920  return RPC::make_param_error(err.str());
921  }
922 
923  // An account may not sign for itself.
924  if (signers.end() !=
925  std::find_if(
926  signers.begin(),
927  signers.end(),
928  [&signingForID](STObject const& elem) {
929  return elem[sfAccount] == signingForID;
930  }))
931  {
932  std::ostringstream err;
933  err << "A Signer may not be the transaction's Account ("
934  << toBase58(signingForID) << ").";
935  return RPC::make_param_error(err.str());
936  }
937  return {};
938 }
939 
940 } // namespace detail
941 
945  Json::Value jvRequest,
946  NetworkOPs::FailHard failType,
947  Role role,
948  std::chrono::seconds validatedLedgerAge,
949  Application& app)
950 {
951  auto const& ledger = app.openLedger().current();
952  auto j = app.journal("RPCHandler");
953  JLOG(j.debug()) << "transactionSignFor: " << jvRequest;
954 
955  // Verify presence of the signer's account field.
956  const char accountField[] = "account";
957 
958  if (!jvRequest.isMember(accountField))
959  return RPC::missing_field_error(accountField);
960 
961  // Turn the signer's account into an AccountID for multi-sign.
962  auto const signerAccountID =
963  parseBase58<AccountID>(jvRequest[accountField].asString());
964  if (!signerAccountID)
965  {
966  return RPC::make_error(
968  }
969 
970  if (!jvRequest.isMember(jss::tx_json))
971  return RPC::missing_field_error(jss::tx_json);
972 
973  {
974  Json::Value& tx_json(jvRequest[jss::tx_json]);
975 
976  if (!tx_json.isObject())
977  return RPC::object_field_error(jss::tx_json);
978 
979  // If the tx_json.SigningPubKey field is missing,
980  // insert an empty one.
981  if (!tx_json.isMember(sfSigningPubKey.getJsonName()))
982  tx_json[sfSigningPubKey.getJsonName()] = "";
983  }
984 
985  // When multi-signing, the "Sequence" and "SigningPubKey" fields must
986  // be passed in by the caller.
987  using namespace detail;
988  {
989  Json::Value err = checkMultiSignFields(jvRequest);
990  if (RPC::contains_error(err))
991  return err;
992  }
993 
994  // Add and amend fields based on the transaction type.
995  Buffer multiSignature;
996  PublicKey multiSignPubKey;
997  SigningForParams signForParams(
998  *signerAccountID, multiSignPubKey, multiSignature);
999 
1000  transactionPreProcessResult preprocResult = transactionPreProcessImpl(
1001  jvRequest, role, signForParams, validatedLedgerAge, app);
1002 
1003  if (!preprocResult.second)
1004  return preprocResult.first;
1005 
1006  {
1007  std::shared_ptr<SLE const> account_state =
1008  ledger->read(keylet::account(*signerAccountID));
1009  // Make sure the account and secret belong together.
1010  auto const err =
1011  acctMatchesPubKey(account_state, *signerAccountID, multiSignPubKey);
1012 
1013  if (err != rpcSUCCESS)
1014  return rpcError(err);
1015  }
1016 
1017  // Inject the newly generated signature into tx_json.Signers.
1018  auto& sttx = preprocResult.second;
1019  {
1020  // Make the signer object that we'll inject.
1021  STObject signer(sfSigner);
1022  signer[sfAccount] = *signerAccountID;
1023  signer.setFieldVL(sfTxnSignature, multiSignature);
1024  signer.setFieldVL(sfSigningPubKey, multiSignPubKey.slice());
1025 
1026  // If there is not yet a Signers array, make one.
1027  if (!sttx->isFieldPresent(sfSigners))
1028  sttx->setFieldArray(sfSigners, {});
1029 
1030  auto& signers = sttx->peekFieldArray(sfSigners);
1031  signers.emplace_back(std::move(signer));
1032 
1033  // The array must be sorted and validated.
1034  auto err = sortAndValidateSigners(signers, (*sttx)[sfAccount]);
1035  if (RPC::contains_error(err))
1036  return err;
1037  }
1038 
1039  // Make sure the STTx makes a legitimate Transaction.
1041  transactionConstructImpl(sttx, ledger->rules(), app);
1042 
1043  if (!txn.second)
1044  return txn.first;
1045 
1046  return transactionFormatResultImpl(txn.second);
1047 }
1048 
1052  Json::Value jvRequest,
1053  NetworkOPs::FailHard failType,
1054  Role role,
1055  std::chrono::seconds validatedLedgerAge,
1056  Application& app,
1057  ProcessTransactionFn const& processTransaction,
1058  RPC::SubmitSync sync)
1059 {
1060  auto const& ledger = app.openLedger().current();
1061  auto j = app.journal("RPCHandler");
1062  JLOG(j.debug()) << "transactionSubmitMultiSigned: " << jvRequest;
1063 
1064  // When multi-signing, the "Sequence" and "SigningPubKey" fields must
1065  // be passed in by the caller.
1066  using namespace detail;
1067  {
1068  Json::Value err = checkMultiSignFields(jvRequest);
1069  if (RPC::contains_error(err))
1070  return err;
1071  }
1072 
1073  Json::Value& tx_json(jvRequest["tx_json"]);
1074 
1075  auto [txJsonResult, srcAddressID] = checkTxJsonFields(
1076  tx_json,
1077  role,
1078  true,
1079  validatedLedgerAge,
1080  app.config(),
1081  app.getFeeTrack(),
1082  getAPIVersionNumber(jvRequest, app.config().BETA_RPC_API));
1083 
1084  if (RPC::contains_error(txJsonResult))
1085  return std::move(txJsonResult);
1086 
1088  ledger->read(keylet::account(srcAddressID));
1089 
1090  if (!sle)
1091  {
1092  // If did not find account, error.
1093  JLOG(j.debug())
1094  << "transactionSubmitMultiSigned: Failed to find source account "
1095  << "in current ledger: " << toBase58(srcAddressID);
1096 
1098  }
1099 
1100  {
1101  Json::Value err = checkFee(
1102  jvRequest,
1103  role,
1104  false,
1105  app.config(),
1106  app.getFeeTrack(),
1107  app.getTxQ(),
1108  app);
1109 
1110  if (RPC::contains_error(err))
1111  return err;
1112 
1113  err = checkPayment(jvRequest, tx_json, srcAddressID, role, app, false);
1114 
1115  if (RPC::contains_error(err))
1116  return err;
1117  }
1118 
1119  // Grind through the JSON in tx_json to produce a STTx.
1120  std::shared_ptr<STTx> stpTrans;
1121  {
1122  STParsedJSONObject parsedTx_json("tx_json", tx_json);
1123  if (!parsedTx_json.object)
1124  {
1125  Json::Value jvResult;
1126  jvResult["error"] = parsedTx_json.error["error"];
1127  jvResult["error_code"] = parsedTx_json.error["error_code"];
1128  jvResult["error_message"] = parsedTx_json.error["error_message"];
1129  return jvResult;
1130  }
1131  try
1132  {
1133  stpTrans =
1134  std::make_shared<STTx>(std::move(parsedTx_json.object.value()));
1135  }
1136  catch (STObject::FieldErr& err)
1137  {
1138  return RPC::make_error(rpcINVALID_PARAMS, err.what());
1139  }
1140  catch (std::exception& ex)
1141  {
1142  std::string reason(ex.what());
1143  return RPC::make_error(
1144  rpcINTERNAL,
1145  "Exception while serializing transaction: " + reason);
1146  }
1147  std::string reason;
1148  if (!passesLocalChecks(*stpTrans, reason))
1149  return RPC::make_error(rpcINVALID_PARAMS, reason);
1150  }
1151 
1152  // Validate the fields in the serialized transaction.
1153  {
1154  // We now have the transaction text serialized and in the right format.
1155  // Verify the values of select fields.
1156  //
1157  // The SigningPubKey must be present but empty.
1158  if (!stpTrans->getFieldVL(sfSigningPubKey).empty())
1159  {
1160  std::ostringstream err;
1161  err << "Invalid " << sfSigningPubKey.fieldName
1162  << " field. Field must be empty when multi-signing.";
1163  return RPC::make_error(rpcINVALID_PARAMS, err.str());
1164  }
1165 
1166  // There may not be a TxnSignature field.
1167  if (stpTrans->isFieldPresent(sfTxnSignature))
1169 
1170  // The Fee field must be in XRP and greater than zero.
1171  auto const fee = stpTrans->getFieldAmount(sfFee);
1172 
1173  if (!isLegalNet(fee))
1174  {
1175  std::ostringstream err;
1176  err << "Invalid " << sfFee.fieldName
1177  << " field. Fees must be specified in XRP.";
1178  return RPC::make_error(rpcINVALID_PARAMS, err.str());
1179  }
1180  if (fee <= STAmount{0})
1181  {
1182  std::ostringstream err;
1183  err << "Invalid " << sfFee.fieldName
1184  << " field. Fees must be greater than zero.";
1185  return RPC::make_error(rpcINVALID_PARAMS, err.str());
1186  }
1187  }
1188 
1189  // Verify that the Signers field is present.
1190  if (!stpTrans->isFieldPresent(sfSigners))
1191  return RPC::missing_field_error("tx_json.Signers");
1192 
1193  // If the Signers field is present the SField guarantees it to be an array.
1194  // Get a reference to the Signers array so we can verify and sort it.
1195  auto& signers = stpTrans->peekFieldArray(sfSigners);
1196 
1197  if (signers.empty())
1198  return RPC::make_param_error("tx_json.Signers array may not be empty.");
1199 
1200  // The Signers array may only contain Signer objects.
1201  if (std::find_if_not(
1202  signers.begin(), signers.end(), [](STObject const& obj) {
1203  return (
1204  // A Signer object always contains these fields and no
1205  // others.
1206  obj.isFieldPresent(sfAccount) &&
1207  obj.isFieldPresent(sfSigningPubKey) &&
1208  obj.isFieldPresent(sfTxnSignature) && obj.getCount() == 3);
1209  }) != signers.end())
1210  {
1211  return RPC::make_param_error(
1212  "Signers array may only contain Signer entries.");
1213  }
1214 
1215  // The array must be sorted and validated.
1216  auto err = sortAndValidateSigners(signers, srcAddressID);
1217  if (RPC::contains_error(err))
1218  return err;
1219 
1220  // Make sure the SerializedTransaction makes a legitimate Transaction.
1222  transactionConstructImpl(stpTrans, ledger->rules(), app);
1223 
1224  if (!txn.second)
1225  return txn.first;
1226 
1227  // Finally, submit the transaction.
1228  try
1229  {
1230  // FIXME: For performance, should use asynch interface
1231  processTransaction(txn.second, isUnlimited(role), sync, failType);
1232  }
1233  catch (std::exception&)
1234  {
1235  return RPC::make_error(
1236  rpcINTERNAL, "Exception occurred during transaction submission.");
1237  }
1238 
1239  return transactionFormatResultImpl(txn.second);
1240 }
1241 
1242 } // namespace RPC
1243 } // namespace ripple
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::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:944
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:1046
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:46
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
ripple::RPC::transactionSubmit
Json::Value transactionSubmit(Json::Value jvRequest, NetworkOPs::FailHard failType, Role role, std::chrono::seconds validatedLedgerAge, Application &app, ProcessTransactionFn const &processTransaction, RPC::SubmitSync sync)
Returns a Json::objectValue.
Definition: TransactionSign.cpp:815
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::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:778
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::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:682
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:850
ripple::RPC::detail::transactionFormatResultImpl
static Json::Value transactionFormatResultImpl(Transaction::pointer tpTrans)
Definition: TransactionSign.cpp:648
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:646
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: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: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::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:894
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::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::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::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::transactionSubmitMultiSigned
Json::Value transactionSubmitMultiSigned(Json::Value jvRequest, NetworkOPs::FailHard failType, Role role, std::chrono::seconds validatedLedgerAge, Application &app, ProcessTransactionFn const &processTransaction, RPC::SubmitSync sync)
Returns a Json::objectValue.
Definition: TransactionSign.cpp:1051
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:52
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
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:1669
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:863
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::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