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