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