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  std::shared_ptr<ReadView const> const& ledger,
165  bool doPath)
166 {
167  // Only path find for Payments.
168  if (tx_json[jss::TransactionType].asString() != jss::Payment)
169  return Json::Value();
170 
171  if (!tx_json.isMember(jss::Amount))
172  return RPC::missing_field_error("tx_json.Amount");
173 
174  STAmount amount;
175 
176  if (!amountFromJsonNoThrow(amount, tx_json[jss::Amount]))
177  return RPC::invalid_field_error("tx_json.Amount");
178 
179  if (!tx_json.isMember(jss::Destination))
180  return RPC::missing_field_error("tx_json.Destination");
181 
182  auto const dstAccountID =
183  parseBase58<AccountID>(tx_json[jss::Destination].asString());
184  if (!dstAccountID)
185  return RPC::invalid_field_error("tx_json.Destination");
186 
187  if ((doPath == false) && params.isMember(jss::build_path))
188  return RPC::make_error(
190  "Field 'build_path' not allowed in this context.");
191 
192  if (tx_json.isMember(jss::Paths) && params.isMember(jss::build_path))
193  return RPC::make_error(
195  "Cannot specify both 'tx_json.Paths' and 'build_path'");
196 
197  if (!tx_json.isMember(jss::Paths) && params.isMember(jss::build_path))
198  {
199  STAmount sendMax;
200 
201  if (tx_json.isMember(jss::SendMax))
202  {
203  if (!amountFromJsonNoThrow(sendMax, tx_json[jss::SendMax]))
204  return RPC::invalid_field_error("tx_json.SendMax");
205  }
206  else
207  {
208  // If no SendMax, default to Amount with sender as issuer.
209  sendMax = amount;
210  sendMax.setIssuer(srcAddressID);
211  }
212 
213  if (sendMax.native() && amount.native())
214  return RPC::make_error(
215  rpcINVALID_PARAMS, "Cannot build XRP to XRP paths.");
216 
217  {
218  LegacyPathFind lpf(isUnlimited(role), app);
219  if (!lpf.isOk())
220  return rpcError(rpcTOO_BUSY);
221 
222  STPathSet result;
223  if (ledger)
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  boost::none,
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  std::shared_ptr<OpenView const> const& ledger)
368 {
369  auto j = app.journal("RPCHandler");
370 
371  Json::Value jvResult;
372  auto const [pk, sk] = keypairForSignature(params, jvResult);
373  if (contains_error(jvResult))
374  return jvResult;
375 
376  bool const verify =
377  !(params.isMember(jss::offline) && params[jss::offline].asBool());
378 
379  if (!params.isMember(jss::tx_json))
380  return RPC::missing_field_error(jss::tx_json);
381 
382  Json::Value& tx_json(params[jss::tx_json]);
383 
384  // Check tx_json fields, but don't add any.
385  auto [txJsonResult, srcAddressID] = checkTxJsonFields(
386  tx_json,
387  role,
388  verify,
389  validatedLedgerAge,
390  app.config(),
391  app.getFeeTrack(),
392  getAPIVersionNumber(params));
393 
394  if (RPC::contains_error(txJsonResult))
395  return std::move(txJsonResult);
396 
397  // This test covers the case where we're offline so the sequence number
398  // cannot be determined locally. If we're offline then the caller must
399  // provide the sequence number.
400  if (!verify && !tx_json.isMember(jss::Sequence))
401  return RPC::missing_field_error("tx_json.Sequence");
402 
404  ledger->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  ledger);
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  ledger,
435  verify && signingArgs.editFields());
436 
437  if (RPC::contains_error(err))
438  return err;
439  }
440 
441  if (signingArgs.editFields())
442  {
443  if (!tx_json.isMember(jss::Sequence))
444  {
445  if (!sle)
446  {
447  JLOG(j.debug())
448  << "transactionSign: Failed to find source account "
449  << "in current ledger: " << toBase58(srcAddressID);
450 
452  }
453  tx_json[jss::Sequence] = app.getTxQ().nextQueuableSeq(sle).value();
454  }
455 
456  if (!tx_json.isMember(jss::Flags))
457  tx_json[jss::Flags] = tfFullyCanonicalSig;
458  }
459 
460  // If multisigning there should not be a single signature and vice versa.
461  if (signingArgs.isMultiSigning())
462  {
463  if (tx_json.isMember(sfTxnSignature.jsonName))
465 
466  // If multisigning then we need to return the public key.
467  signingArgs.setPublicKey(pk);
468  }
469  else if (signingArgs.isSingleSigning())
470  {
471  if (tx_json.isMember(sfSigners.jsonName))
473  }
474 
475  if (verify)
476  {
477  if (!sle)
478  // XXX Ignore transactions for accounts not created.
480 
481  JLOG(j.trace()) << "verify: " << toBase58(calcAccountID(pk)) << " : "
482  << toBase58(srcAddressID);
483 
484  // Don't do this test if multisigning since the account and secret
485  // probably don't belong together in that case.
486  if (!signingArgs.isMultiSigning())
487  {
488  // Make sure the account and secret belong together.
489  auto const err = acctMatchesPubKey(sle, srcAddressID, pk);
490 
491  if (err != rpcSUCCESS)
492  return rpcError(err);
493  }
494  }
495 
496  STParsedJSONObject parsed(std::string(jss::tx_json), tx_json);
497  if (parsed.object == boost::none)
498  {
499  Json::Value err;
500  err[jss::error] = parsed.error[jss::error];
501  err[jss::error_code] = parsed.error[jss::error_code];
502  err[jss::error_message] = parsed.error[jss::error_message];
503  return err;
504  }
505 
506  std::shared_ptr<STTx> stpTrans;
507  try
508  {
509  // If we're generating a multi-signature the SigningPubKey must be
510  // empty, otherwise it must be the master account's public key.
511  parsed.object->setFieldVL(
513  signingArgs.isMultiSigning() ? Slice(nullptr, 0) : pk.slice());
514 
515  stpTrans = std::make_shared<STTx>(std::move(parsed.object.get()));
516  }
517  catch (STObject::FieldErr& err)
518  {
519  return RPC::make_error(rpcINVALID_PARAMS, err.what());
520  }
521  catch (std::exception&)
522  {
523  return RPC::make_error(
524  rpcINTERNAL,
525  "Exception occurred constructing serialized transaction");
526  }
527 
528  std::string reason;
529  if (!passesLocalChecks(*stpTrans, reason))
530  return RPC::make_error(rpcINVALID_PARAMS, reason);
531 
532  // If multisign then return multiSignature, else set TxnSignature field.
533  if (signingArgs.isMultiSigning())
534  {
535  Serializer s =
536  buildMultiSigningData(*stpTrans, signingArgs.getSigner());
537 
538  auto multisig = ripple::sign(pk, sk, s.slice());
539 
540  signingArgs.moveMultiSignature(std::move(multisig));
541  }
542  else if (signingArgs.isSingleSigning())
543  {
544  stpTrans->sign(pk, sk);
545  }
546 
547  return transactionPreProcessResult{std::move(stpTrans)};
548 }
549 
552  std::shared_ptr<STTx const> const& stpTrans,
553  Rules const& rules,
554  Application& app)
555 {
557 
558  // Turn the passed in STTx into a Transaction.
559  Transaction::pointer tpTrans;
560  {
561  std::string reason;
562  tpTrans = std::make_shared<Transaction>(stpTrans, reason, app);
563  if (tpTrans->getStatus() != NEW)
564  {
565  ret.first = RPC::make_error(
566  rpcINTERNAL, "Unable to construct transaction: " + reason);
567  return ret;
568  }
569  }
570  try
571  {
572  // Make sure the Transaction we just built is legit by serializing it
573  // and then de-serializing it. If the result isn't equivalent
574  // to the initial transaction then there's something wrong with the
575  // passed-in STTx.
576  {
577  Serializer s;
578  tpTrans->getSTransaction()->add(s);
579  Blob transBlob = s.getData();
580  SerialIter sit{makeSlice(transBlob)};
581 
582  // Check the signature if that's called for.
583  auto sttxNew = std::make_shared<STTx const>(sit);
584  if (!app.checkSigs())
586  app.getHashRouter(),
587  sttxNew->getTransactionID(),
589  if (checkValidity(
590  app.getHashRouter(), *sttxNew, rules, app.config())
591  .first != Validity::Valid)
592  {
593  ret.first = RPC::make_error(rpcINTERNAL, "Invalid signature.");
594  return ret;
595  }
596 
597  std::string reason;
598  auto tpTransNew =
599  std::make_shared<Transaction>(sttxNew, reason, app);
600 
601  if (tpTransNew)
602  {
603  if (!tpTransNew->getSTransaction()->isEquivalent(
604  *tpTrans->getSTransaction()))
605  {
606  tpTransNew.reset();
607  }
608  tpTrans = std::move(tpTransNew);
609  }
610  }
611  }
612  catch (std::exception&)
613  {
614  // Assume that any exceptions are related to transaction sterilization.
615  tpTrans.reset();
616  }
617 
618  if (!tpTrans)
619  {
620  ret.first =
621  RPC::make_error(rpcINTERNAL, "Unable to sterilize transaction.");
622  return ret;
623  }
624  ret.second = std::move(tpTrans);
625  return ret;
626 }
627 
628 static Json::Value
630 {
631  Json::Value jvResult;
632  try
633  {
634  jvResult[jss::tx_json] = tpTrans->getJson(JsonOptions::none);
635  jvResult[jss::tx_blob] =
636  strHex(tpTrans->getSTransaction()->getSerializer().peekData());
637 
638  if (temUNCERTAIN != tpTrans->getResult())
639  {
640  std::string sToken;
641  std::string sHuman;
642 
643  transResultInfo(tpTrans->getResult(), sToken, sHuman);
644 
645  jvResult[jss::engine_result] = sToken;
646  jvResult[jss::engine_result_code] = tpTrans->getResult();
647  jvResult[jss::engine_result_message] = sHuman;
648  }
649  }
650  catch (std::exception&)
651  {
652  jvResult = RPC::make_error(
653  rpcINTERNAL, "Exception occurred during JSON handling.");
654  }
655  return jvResult;
656 }
657 
658 } // namespace detail
659 
660 //------------------------------------------------------------------------------
661 
664  Json::Value& request,
665  Role const role,
666  bool doAutoFill,
667  Config const& config,
668  LoadFeeTrack const& feeTrack,
669  TxQ const& txQ,
670  std::shared_ptr<OpenView const> const& ledger)
671 {
672  Json::Value& tx(request[jss::tx_json]);
673  if (tx.isMember(jss::Fee))
674  return Json::Value();
675 
676  if (!doAutoFill)
677  return RPC::missing_field_error("tx_json.Fee");
678 
681  if (request.isMember(jss::fee_mult_max))
682  {
683  if (request[jss::fee_mult_max].isInt())
684  {
685  mult = request[jss::fee_mult_max].asInt();
686  if (mult < 0)
687  return RPC::make_error(
690  jss::fee_mult_max, "a positive integer"));
691  }
692  else
693  {
694  return RPC::make_error(
695  rpcHIGH_FEE,
697  jss::fee_mult_max, "a positive integer"));
698  }
699  }
700  if (request.isMember(jss::fee_div_max))
701  {
702  if (request[jss::fee_div_max].isInt())
703  {
704  div = request[jss::fee_div_max].asInt();
705  if (div <= 0)
706  return RPC::make_error(
709  jss::fee_div_max, "a positive integer"));
710  }
711  else
712  {
713  return RPC::make_error(
714  rpcHIGH_FEE,
716  jss::fee_div_max, "a positive integer"));
717  }
718  }
719 
720  // Default fee in fee units.
721  FeeUnit32 const feeDefault = config.TRANSACTION_FEE_BASE;
722 
723  // Administrative and identified endpoints are exempt from local fees.
724  XRPAmount const loadFee =
725  scaleFeeLoad(feeDefault, feeTrack, ledger->fees(), isUnlimited(role));
726  XRPAmount fee = loadFee;
727  {
728  auto const metrics = txQ.getMetrics(*ledger);
729  auto const baseFee = ledger->fees().base;
730  auto escalatedFee =
731  toDrops(metrics.openLedgerFeeLevel - FeeLevel64(1), baseFee) + 1;
732  fee = std::max(fee, escalatedFee);
733  }
734 
735  auto const limit = [&]() {
736  // Scale fee units to drops:
737  auto const drops =
738  mulDiv(feeDefault, ledger->fees().base, ledger->fees().units);
739  if (!drops.first)
740  Throw<std::overflow_error>("mulDiv");
741  auto const result = mulDiv(drops.second, mult, div);
742  if (!result.first)
743  Throw<std::overflow_error>("mulDiv");
744  return result.second;
745  }();
746 
747  if (fee > limit)
748  {
750  ss << "Fee of " << fee << " exceeds the requested tx limit of "
751  << limit;
752  return RPC::make_error(rpcHIGH_FEE, ss.str());
753  }
754 
755  tx[jss::Fee] = fee.jsonClipped();
756  return Json::Value();
757 }
758 
759 //------------------------------------------------------------------------------
760 
764  Json::Value jvRequest,
765  NetworkOPs::FailHard failType,
766  Role role,
767  std::chrono::seconds validatedLedgerAge,
768  Application& app)
769 {
770  using namespace detail;
771 
772  auto const& ledger = app.openLedger().current();
773  auto j = app.journal("RPCHandler");
774  JLOG(j.debug()) << "transactionSign: " << jvRequest;
775 
776  // Add and amend fields based on the transaction type.
777  SigningForParams signForParams;
778  transactionPreProcessResult preprocResult = transactionPreProcessImpl(
779  jvRequest, role, signForParams, validatedLedgerAge, app, ledger);
780 
781  if (!preprocResult.second)
782  return preprocResult.first;
783 
784  // Make sure the STTx makes a legitimate Transaction.
786  transactionConstructImpl(preprocResult.second, ledger->rules(), app);
787 
788  if (!txn.second)
789  return txn.first;
790 
792 }
793 
797  Json::Value jvRequest,
798  NetworkOPs::FailHard failType,
799  Role role,
800  std::chrono::seconds validatedLedgerAge,
801  Application& app,
802  ProcessTransactionFn const& processTransaction)
803 {
804  using namespace detail;
805 
806  auto const& ledger = app.openLedger().current();
807  auto j = app.journal("RPCHandler");
808  JLOG(j.debug()) << "transactionSubmit: " << jvRequest;
809 
810  // Add and amend fields based on the transaction type.
811  SigningForParams signForParams;
812  transactionPreProcessResult preprocResult = transactionPreProcessImpl(
813  jvRequest, role, signForParams, validatedLedgerAge, app, ledger);
814 
815  if (!preprocResult.second)
816  return preprocResult.first;
817 
818  // Make sure the STTx makes a legitimate Transaction.
820  transactionConstructImpl(preprocResult.second, ledger->rules(), app);
821 
822  if (!txn.second)
823  return txn.first;
824 
825  // Finally, submit the transaction.
826  try
827  {
828  // FIXME: For performance, should use asynch interface
829  processTransaction(txn.second, isUnlimited(role), true, failType);
830  }
831  catch (std::exception&)
832  {
833  return RPC::make_error(
834  rpcINTERNAL, "Exception occurred during transaction submission.");
835  }
836 
838 }
839 
840 namespace detail {
841 // There are a some field checks shared by transactionSignFor
842 // and transactionSubmitMultiSigned. Gather them together here.
843 static Json::Value
845 {
846  if (!jvRequest.isMember(jss::tx_json))
847  return RPC::missing_field_error(jss::tx_json);
848 
849  Json::Value const& tx_json(jvRequest[jss::tx_json]);
850 
851  if (!tx_json.isObject())
852  return RPC::invalid_field_message(jss::tx_json);
853 
854  // There are a couple of additional fields we need to check before
855  // we serialize. If we serialize first then we generate less useful
856  // error messages.
857  if (!tx_json.isMember(jss::Sequence))
858  return RPC::missing_field_error("tx_json.Sequence");
859 
860  if (!tx_json.isMember(sfSigningPubKey.getJsonName()))
861  return RPC::missing_field_error("tx_json.SigningPubKey");
862 
863  if (!tx_json[sfSigningPubKey.getJsonName()].asString().empty())
864  return RPC::make_error(
866  "When multi-signing 'tx_json.SigningPubKey' must be empty.");
867 
868  return Json::Value();
869 }
870 
871 // Sort and validate an stSigners array.
872 //
873 // Returns a null Json::Value if there are no errors.
874 static Json::Value
875 sortAndValidateSigners(STArray& signers, AccountID const& signingForID)
876 {
877  if (signers.empty())
878  return RPC::make_param_error("Signers array may not be empty.");
879 
880  // Signers must be sorted by Account.
881  std::sort(
882  signers.begin(),
883  signers.end(),
884  [](STObject const& a, STObject const& b) {
885  return (a[sfAccount] < b[sfAccount]);
886  });
887 
888  // Signers may not contain any duplicates.
889  auto const dupIter = std::adjacent_find(
890  signers.begin(),
891  signers.end(),
892  [](STObject const& a, STObject const& b) {
893  return (a[sfAccount] == b[sfAccount]);
894  });
895 
896  if (dupIter != signers.end())
897  {
898  std::ostringstream err;
899  err << "Duplicate Signers:Signer:Account entries ("
900  << toBase58((*dupIter)[sfAccount]) << ") are not allowed.";
901  return RPC::make_param_error(err.str());
902  }
903 
904  // An account may not sign for itself.
905  if (signers.end() !=
906  std::find_if(
907  signers.begin(),
908  signers.end(),
909  [&signingForID](STObject const& elem) {
910  return elem[sfAccount] == signingForID;
911  }))
912  {
913  std::ostringstream err;
914  err << "A Signer may not be the transaction's Account ("
915  << toBase58(signingForID) << ").";
916  return RPC::make_param_error(err.str());
917  }
918  return {};
919 }
920 
921 } // namespace detail
922 
926  Json::Value jvRequest,
927  NetworkOPs::FailHard failType,
928  Role role,
929  std::chrono::seconds validatedLedgerAge,
930  Application& app)
931 {
932  auto const& ledger = app.openLedger().current();
933  auto j = app.journal("RPCHandler");
934  JLOG(j.debug()) << "transactionSignFor: " << jvRequest;
935 
936  // Verify presence of the signer's account field.
937  const char accountField[] = "account";
938 
939  if (!jvRequest.isMember(accountField))
940  return RPC::missing_field_error(accountField);
941 
942  // Turn the signer's account into an AccountID for multi-sign.
943  auto const signerAccountID =
944  parseBase58<AccountID>(jvRequest[accountField].asString());
945  if (!signerAccountID)
946  {
947  return RPC::make_error(
949  }
950 
951  if (!jvRequest.isMember(jss::tx_json))
952  return RPC::missing_field_error(jss::tx_json);
953 
954  {
955  Json::Value& tx_json(jvRequest[jss::tx_json]);
956 
957  if (!tx_json.isObject())
958  return RPC::object_field_error(jss::tx_json);
959 
960  // If the tx_json.SigningPubKey field is missing,
961  // insert an empty one.
962  if (!tx_json.isMember(sfSigningPubKey.getJsonName()))
963  tx_json[sfSigningPubKey.getJsonName()] = "";
964  }
965 
966  // When multi-signing, the "Sequence" and "SigningPubKey" fields must
967  // be passed in by the caller.
968  using namespace detail;
969  {
970  Json::Value err = checkMultiSignFields(jvRequest);
971  if (RPC::contains_error(err))
972  return err;
973  }
974 
975  // Add and amend fields based on the transaction type.
976  Buffer multiSignature;
977  PublicKey multiSignPubKey;
978  SigningForParams signForParams(
979  *signerAccountID, multiSignPubKey, multiSignature);
980 
981  transactionPreProcessResult preprocResult = transactionPreProcessImpl(
982  jvRequest, role, signForParams, validatedLedgerAge, app, ledger);
983 
984  if (!preprocResult.second)
985  return preprocResult.first;
986 
987  {
988  std::shared_ptr<SLE const> account_state =
989  ledger->read(keylet::account(*signerAccountID));
990  // Make sure the account and secret belong together.
991  auto const err =
992  acctMatchesPubKey(account_state, *signerAccountID, multiSignPubKey);
993 
994  if (err != rpcSUCCESS)
995  return rpcError(err);
996  }
997 
998  // Inject the newly generated signature into tx_json.Signers.
999  auto& sttx = preprocResult.second;
1000  {
1001  // Make the signer object that we'll inject.
1002  STObject signer(sfSigner);
1003  signer[sfAccount] = *signerAccountID;
1004  signer.setFieldVL(sfTxnSignature, multiSignature);
1005  signer.setFieldVL(sfSigningPubKey, multiSignPubKey.slice());
1006 
1007  // If there is not yet a Signers array, make one.
1008  if (!sttx->isFieldPresent(sfSigners))
1009  sttx->setFieldArray(sfSigners, {});
1010 
1011  auto& signers = sttx->peekFieldArray(sfSigners);
1012  signers.emplace_back(std::move(signer));
1013 
1014  // The array must be sorted and validated.
1015  auto err = sortAndValidateSigners(signers, (*sttx)[sfAccount]);
1016  if (RPC::contains_error(err))
1017  return err;
1018  }
1019 
1020  // Make sure the STTx makes a legitimate Transaction.
1022  transactionConstructImpl(sttx, ledger->rules(), app);
1023 
1024  if (!txn.second)
1025  return txn.first;
1026 
1027  return transactionFormatResultImpl(txn.second);
1028 }
1029 
1033  Json::Value jvRequest,
1034  NetworkOPs::FailHard failType,
1035  Role role,
1036  std::chrono::seconds validatedLedgerAge,
1037  Application& app,
1038  ProcessTransactionFn const& processTransaction)
1039 {
1040  auto const& ledger = app.openLedger().current();
1041  auto j = app.journal("RPCHandler");
1042  JLOG(j.debug()) << "transactionSubmitMultiSigned: " << jvRequest;
1043 
1044  // When multi-signing, the "Sequence" and "SigningPubKey" fields must
1045  // be passed in by the caller.
1046  using namespace detail;
1047  {
1048  Json::Value err = checkMultiSignFields(jvRequest);
1049  if (RPC::contains_error(err))
1050  return err;
1051  }
1052 
1053  Json::Value& tx_json(jvRequest["tx_json"]);
1054 
1055  auto [txJsonResult, srcAddressID] = checkTxJsonFields(
1056  tx_json,
1057  role,
1058  true,
1059  validatedLedgerAge,
1060  app.config(),
1061  app.getFeeTrack(),
1062  getAPIVersionNumber(jvRequest));
1063 
1064  if (RPC::contains_error(txJsonResult))
1065  return std::move(txJsonResult);
1066 
1068  ledger->read(keylet::account(srcAddressID));
1069 
1070  if (!sle)
1071  {
1072  // If did not find account, error.
1073  JLOG(j.debug())
1074  << "transactionSubmitMultiSigned: Failed to find source account "
1075  << "in current ledger: " << toBase58(srcAddressID);
1076 
1078  }
1079 
1080  {
1081  Json::Value err = checkFee(
1082  jvRequest,
1083  role,
1084  false,
1085  app.config(),
1086  app.getFeeTrack(),
1087  app.getTxQ(),
1088  ledger);
1089 
1090  if (RPC::contains_error(err))
1091  return err;
1092 
1093  err = checkPayment(
1094  jvRequest, tx_json, srcAddressID, role, app, ledger, false);
1095 
1096  if (RPC::contains_error(err))
1097  return err;
1098  }
1099 
1100  // Grind through the JSON in tx_json to produce a STTx.
1101  std::shared_ptr<STTx> stpTrans;
1102  {
1103  STParsedJSONObject parsedTx_json("tx_json", tx_json);
1104  if (!parsedTx_json.object)
1105  {
1106  Json::Value jvResult;
1107  jvResult["error"] = parsedTx_json.error["error"];
1108  jvResult["error_code"] = parsedTx_json.error["error_code"];
1109  jvResult["error_message"] = parsedTx_json.error["error_message"];
1110  return jvResult;
1111  }
1112  try
1113  {
1114  stpTrans =
1115  std::make_shared<STTx>(std::move(parsedTx_json.object.get()));
1116  }
1117  catch (STObject::FieldErr& err)
1118  {
1119  return RPC::make_error(rpcINVALID_PARAMS, err.what());
1120  }
1121  catch (std::exception& ex)
1122  {
1123  std::string reason(ex.what());
1124  return RPC::make_error(
1125  rpcINTERNAL,
1126  "Exception while serializing transaction: " + reason);
1127  }
1128  std::string reason;
1129  if (!passesLocalChecks(*stpTrans, reason))
1130  return RPC::make_error(rpcINVALID_PARAMS, reason);
1131  }
1132 
1133  // Validate the fields in the serialized transaction.
1134  {
1135  // We now have the transaction text serialized and in the right format.
1136  // Verify the values of select fields.
1137  //
1138  // The SigningPubKey must be present but empty.
1139  if (!stpTrans->getFieldVL(sfSigningPubKey).empty())
1140  {
1141  std::ostringstream err;
1142  err << "Invalid " << sfSigningPubKey.fieldName
1143  << " field. Field must be empty when multi-signing.";
1144  return RPC::make_error(rpcINVALID_PARAMS, err.str());
1145  }
1146 
1147  // There may not be a TxnSignature field.
1148  if (stpTrans->isFieldPresent(sfTxnSignature))
1150 
1151  // The Fee field must be in XRP and greater than zero.
1152  auto const fee = stpTrans->getFieldAmount(sfFee);
1153 
1154  if (!isLegalNet(fee))
1155  {
1156  std::ostringstream err;
1157  err << "Invalid " << sfFee.fieldName
1158  << " field. Fees must be specified in XRP.";
1159  return RPC::make_error(rpcINVALID_PARAMS, err.str());
1160  }
1161  if (fee <= STAmount{0})
1162  {
1163  std::ostringstream err;
1164  err << "Invalid " << sfFee.fieldName
1165  << " field. Fees must be greater than zero.";
1166  return RPC::make_error(rpcINVALID_PARAMS, err.str());
1167  }
1168  }
1169 
1170  // Verify that the Signers field is present.
1171  if (!stpTrans->isFieldPresent(sfSigners))
1172  return RPC::missing_field_error("tx_json.Signers");
1173 
1174  // If the Signers field is present the SField guarantees it to be an array.
1175  // Get a reference to the Signers array so we can verify and sort it.
1176  auto& signers = stpTrans->peekFieldArray(sfSigners);
1177 
1178  if (signers.empty())
1179  return RPC::make_param_error("tx_json.Signers array may not be empty.");
1180 
1181  // The Signers array may only contain Signer objects.
1182  if (std::find_if_not(
1183  signers.begin(), signers.end(), [](STObject const& obj) {
1184  return (
1185  // A Signer object always contains these fields and no
1186  // others.
1187  obj.isFieldPresent(sfAccount) &&
1188  obj.isFieldPresent(sfSigningPubKey) &&
1189  obj.isFieldPresent(sfTxnSignature) && obj.getCount() == 3);
1190  }) != signers.end())
1191  {
1192  return RPC::make_param_error(
1193  "Signers array may only contain Signer entries.");
1194  }
1195 
1196  // The array must be sorted and validated.
1197  auto err = sortAndValidateSigners(signers, srcAddressID);
1198  if (RPC::contains_error(err))
1199  return err;
1200 
1201  // Make sure the SerializedTransaction makes a legitimate Transaction.
1203  transactionConstructImpl(stpTrans, ledger->rules(), app);
1204 
1205  if (!txn.second)
1206  return txn.first;
1207 
1208  // Finally, submit the transaction.
1209  try
1210  {
1211  // FIXME: For performance, should use asynch interface
1212  processTransaction(txn.second, isUnlimited(role), true, failType);
1213  }
1214  catch (std::exception&)
1215  {
1216  return RPC::make_error(
1217  rpcINTERNAL, "Exception occurred during transaction submission.");
1218  }
1219 
1220  return transactionFormatResultImpl(txn.second);
1221 }
1222 
1223 } // namespace RPC
1224 } // namespace ripple
ripple::RPC::detail::SigningForParams::multiSigningAcctID_
AccountID const *const multiSigningAcctID_
Definition: TransactionSign.cpp:54
ripple::Application
Definition: Application.h:97
ripple::Application::checkSigs
virtual bool checkSigs() const =0
ripple::amountFromJsonNoThrow
bool amountFromJsonNoThrow(STAmount &result, Json::Value const &jvSource)
Definition: STAmount.cpp:931
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:925
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:230
ripple::Pathfinder
Calculates payment paths.
Definition: Pathfinder.h:37
ripple::RPC::getAPIVersionNumber
unsigned int getAPIVersionNumber(Json::Value const &jv)
Retrieve the api version number from the json value.
Definition: RPCHelpers.cpp:839
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
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:45
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::RPC::detail::checkPayment
static Json::Value checkPayment(Json::Value const &params, Json::Value &tx_json, AccountID const &srcAddressID, Role const role, Application &app, std::shared_ptr< ReadView const > const &ledger, bool doPath)
Definition: TransactionSign.cpp:158
ripple::scaleFeeLoad
XRPAmount scaleFeeLoad(FeeUnit64 fee, LoadFeeTrack const &feeTrack, Fees const &fees, bool bUnlimited)
Definition: LoadFeeTrack.cpp:89
ripple::RPC::checkFee
Json::Value checkFee(Json::Value &request, Role const role, bool doAutoFill, Config const &config, LoadFeeTrack const &feeTrack, TxQ const &txQ, std::shared_ptr< OpenView const > const &ledger)
Fill in the fee on behalf of the client.
Definition: TransactionSign.cpp:663
ripple::PublicKey::slice
Slice slice() const noexcept
Definition: PublicKey.h:123
ripple::Pathfinder::findPaths
bool findPaths(int searchLevel)
Definition: Pathfinder.cpp:187
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::isLegalNet
bool isLegalNet(STAmount const &value)
Definition: STAmount.h:385
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:303
ripple::SField::getJsonName
Json::StaticString const & getJsonName() const
Definition: SField.h:184
ripple::Application::openLedger
virtual OpenLedger & openLedger()=0
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:763
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:551
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:254
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:119
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:236
ripple::Pathfinder::getBestPaths
STPathSet getBestPaths(int maxPaths, STPath &fullLiquidityPath, STPathSet const &extraPaths, AccountID const &srcIssuer)
Definition: Pathfinder.cpp:566
ripple::RPC::detail::SigningForParams::getSigner
AccountID const & getSigner()
Definition: TransactionSign.cpp:101
ripple::verify
bool verify(PublicKey const &publicKey, Slice const &m, Slice const &sig, bool mustBeFullyCanonical)
Verify a signature on a message.
Definition: PublicKey.cpp:268
ripple::base_uint< 160, detail::AccountIDTag >
ripple::RPC::detail::transactionFormatResultImpl
static Json::Value transactionFormatResultImpl(Transaction::pointer tpTrans)
Definition: TransactionSign.cpp:629
ripple::RPC::expected_field_message
std::string expected_field_message(std::string const &name, std::string const &type)
Definition: ErrorCodes.h:290
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:826
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:796
ripple::TxQ
Transaction Queue.
Definition: TxQ.h:55
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:511
ripple::RPC::contains_error
bool contains_error(Json::Value const &json)
Returns true if the json contains an rpc error specification.
Definition: ErrorCodes.cpp:218
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::PublicKey
A public key.
Definition: PublicKey.h:59
ripple::keylet::account
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:134
ripple::Config
Definition: Config.h:69
ripple::Pathfinder::computePathRanks
void computePathRanks(int maxPaths)
Compute the rankings of the paths.
Definition: Pathfinder.cpp:411
ripple::Config::TRANSACTION_FEE_BASE
static constexpr FeeUnit32 TRANSACTION_FEE_BASE
Definition: Config.h:134
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:875
ripple::Config::standalone
bool standalone() const
Definition: Config.h:249
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:42
ripple::Serializer::slice
Slice slice() const noexcept
Definition: Serializer.h:63
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:1546
ripple::RPC::detail::transactionPreProcessResult
Definition: TransactionSign.cpp:335
ripple::SerialIter
Definition: Serializer.h:308
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::STParsedJSONObject::object
boost::optional< STObject > object
The STObject if the parse was successful.
Definition: STParsedJSON.h:50
ripple::rpcALREADY_MULTISIG
@ rpcALREADY_MULTISIG
Definition: ErrorCodes.h:91
ripple::NetworkOPs::FailHard
FailHard
Definition: NetworkOPs.h:96
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:158
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::RPC::detail::transactionPreProcessImpl
static transactionPreProcessResult transactionPreProcessImpl(Json::Value &params, Role role, SigningForParams &signingArgs, std::chrono::seconds validatedLedgerAge, Application &app, std::shared_ptr< OpenView const > const &ledger)
Definition: TransactionSign.cpp:361
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:266
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:182
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:180
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:124
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:197
std
STL namespace.
ripple::RPC::keypairForSignature
std::pair< PublicKey, SecretKey > keypairForSignature(Json::Value const &params, Json::Value &error)
Definition: RPCHelpers.cpp:660
ripple::LoadFeeTrack::isLoadedCluster
bool isLoadedCluster() const
Definition: LoadFeeTrack.h:130
ripple::STPathSet::getJson
Json::Value getJson(JsonOptions) const override
Definition: STPathSet.cpp:176
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
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:844
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:171
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:1713
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:224
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:278
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:202
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:1032
ripple::RPC::detail::transactionPreProcessResult::transactionPreProcessResult
transactionPreProcessResult()=delete
Json::Value::asString
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:469