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