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