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