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