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