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