rippled
Loading...
Searching...
No Matches
STTx.cpp
1#include <xrpl/basics/Blob.h>
2#include <xrpl/basics/Expected.h>
3#include <xrpl/basics/Log.h>
4#include <xrpl/basics/Slice.h>
5#include <xrpl/basics/StringUtilities.h>
6#include <xrpl/basics/base_uint.h>
7#include <xrpl/basics/contract.h>
8#include <xrpl/basics/safe_cast.h>
9#include <xrpl/basics/strHex.h>
10#include <xrpl/beast/utility/Zero.h>
11#include <xrpl/beast/utility/instrumentation.h>
12#include <xrpl/json/json_value.h>
13#include <xrpl/protocol/AccountID.h>
14#include <xrpl/protocol/Batch.h>
15#include <xrpl/protocol/HashPrefix.h>
16#include <xrpl/protocol/MPTIssue.h>
17#include <xrpl/protocol/Protocol.h>
18#include <xrpl/protocol/PublicKey.h>
19#include <xrpl/protocol/Rules.h>
20#include <xrpl/protocol/SField.h>
21#include <xrpl/protocol/SOTemplate.h>
22#include <xrpl/protocol/STAccount.h>
23#include <xrpl/protocol/STAmount.h>
24#include <xrpl/protocol/STArray.h>
25#include <xrpl/protocol/STBase.h>
26#include <xrpl/protocol/STObject.h>
27#include <xrpl/protocol/STTx.h>
28#include <xrpl/protocol/STVector256.h>
29#include <xrpl/protocol/SecretKey.h>
30#include <xrpl/protocol/SeqProxy.h>
31#include <xrpl/protocol/Serializer.h>
32#include <xrpl/protocol/Sign.h>
33#include <xrpl/protocol/TxFlags.h>
34#include <xrpl/protocol/TxFormats.h>
35#include <xrpl/protocol/jss.h>
36
37#include <boost/container/flat_set.hpp>
38#include <boost/format/format_fwd.hpp>
39#include <boost/format/free_funcs.hpp>
40
41#include <array>
42#include <cstddef>
43#include <cstdint>
44#include <exception>
45#include <functional>
46#include <memory>
47#include <optional>
48#include <stdexcept>
49#include <string>
50#include <string_view>
51#include <type_traits>
52#include <utility>
53
54namespace xrpl {
55
56static auto
58{
59 auto format = TxFormats::getInstance().findByType(type);
60
61 if (format == nullptr)
62 {
63 Throw<std::runtime_error>(
64 "Invalid transaction type " +
66 }
67
68 return format;
69}
70
71STTx::STTx(STObject&& object) : STObject(std::move(object))
72{
73 tx_type_ = safe_cast<TxType>(getFieldU16(sfTransactionType));
74 applyTemplate(getTxFormat(tx_type_)->getSOTemplate()); // may throw
76}
77
78STTx::STTx(SerialIter& sit) : STObject(sfTransaction)
79{
80 int const length = sit.getBytesLeft();
81
82 if ((length < txMinSizeBytes) || (length > txMaxSizeBytes))
83 Throw<std::runtime_error>("Transaction length invalid");
84
85 if (set(sit))
86 Throw<std::runtime_error>("Transaction contains an object terminator");
87
88 tx_type_ = safe_cast<TxType>(getFieldU16(sfTransactionType));
89
90 applyTemplate(getTxFormat(tx_type_)->getSOTemplate()); // May throw
92}
93
94STTx::STTx(TxType type, std::function<void(STObject&)> assembler) : STObject(sfTransaction)
95{
96 auto format = getTxFormat(type);
97
98 set(format->getSOTemplate());
99 setFieldU16(sfTransactionType, format->getType());
100
101 assembler(*this);
102
103 tx_type_ = safe_cast<TxType>(getFieldU16(sfTransactionType));
104
105 if (tx_type_ != type)
106 LogicError("Transaction type was mutated during assembly");
107
109}
110
111STBase*
112STTx::copy(std::size_t n, void* buf) const
113{
114 return emplace(n, buf, *this);
115}
116
117STBase*
119{
120 return emplace(n, buf, std::move(*this));
121}
122
123// STObject functions.
126{
127 return STI_TRANSACTION;
128}
129
132{
133 std::string ret = "\"";
134 ret += to_string(getTransactionID());
135 ret += "\" = {";
136 ret += STObject::getFullText();
137 ret += "}";
138 return ret;
139}
140
141boost::container::flat_set<AccountID>
143{
144 boost::container::flat_set<AccountID> list;
145
146 for (auto const& it : *this)
147 {
148 if (auto sacc = dynamic_cast<STAccount const*>(&it))
149 {
150 XRPL_ASSERT(!sacc->isDefault(), "xrpl::STTx::getMentionedAccounts : account is set");
151 if (!sacc->isDefault())
152 list.insert(sacc->value());
153 }
154 else if (auto samt = dynamic_cast<STAmount const*>(&it))
155 {
156 auto const& issuer = samt->getIssuer();
157 if (!isXRP(issuer))
158 list.insert(issuer);
159 }
160 }
161
162 return list;
163}
164
165static Blob
167{
168 Serializer s;
171 return s.getData();
172}
173
179
180Blob
182{
183 try
184 {
185 return sigObject.getFieldVL(sfTxnSignature);
186 }
187 catch (std::exception const&)
188 {
189 return Blob();
190 }
191}
192
195{
196 std::uint32_t const seq{getFieldU32(sfSequence)};
197 if (seq != 0)
198 return SeqProxy::sequence(seq);
199
200 std::optional<std::uint32_t> const ticketSeq{operator[](~sfTicketSequence)};
201 if (!ticketSeq)
202 {
203 // No TicketSequence specified. Return the Sequence, whatever it is.
204 return SeqProxy::sequence(seq);
205 }
206
207 return SeqProxy{SeqProxy::ticket, *ticketSeq};
208}
209
212{
213 return getSeqProxy().value();
214}
215
218{
219 // If sfDelegate is present, the delegate account is the payer
220 // note: if a delegate is specified, its authorization to act on behalf of the account is
221 // enforced in `Transactor::checkPermission`
222 // cryptographic signature validity is checked separately (e.g., in `Transactor::checkSign`)
223 if (isFieldPresent(sfDelegate))
224 return getAccountID(sfDelegate);
225
226 // Default payer
227 return getAccountID(sfAccount);
228}
229
230void
232 PublicKey const& publicKey,
233 SecretKey const& secretKey,
235{
236 auto const data = getSigningData(*this);
237
238 auto const sig = xrpl::sign(publicKey, secretKey, makeSlice(data));
239
240 if (signatureTarget)
241 {
242 auto& target = peekFieldObject(*signatureTarget);
243 target.setFieldVL(sfTxnSignature, sig);
244 }
245 else
246 {
247 setFieldVL(sfTxnSignature, sig);
248 }
250}
251
253STTx::checkSign(Rules const& rules, STObject const& sigObject) const
254{
255 try
256 {
257 // Determine whether we're single- or multi-signing by looking
258 // at the SigningPubKey. If it's empty we must be
259 // multi-signing. Otherwise we're single-signing.
260
261 Blob const& signingPubKey = sigObject.getFieldVL(sfSigningPubKey);
262 return signingPubKey.empty() ? checkMultiSign(rules, sigObject)
263 : checkSingleSign(sigObject);
264 }
265 catch (...)
266 {
267 return Unexpected("Internal signature check failure.");
268 }
269}
270
272STTx::checkSign(Rules const& rules) const
273{
274 if (auto const ret = checkSign(rules, *this); !ret)
275 return ret;
276
277 if (isFieldPresent(sfCounterpartySignature))
278 {
279 auto const counterSig = getFieldObject(sfCounterpartySignature);
280 if (auto const ret = checkSign(rules, counterSig); !ret)
281 return Unexpected("Counterparty: " + ret.error());
282 }
283 return {};
284}
285
287STTx::checkBatchSign(Rules const& rules) const
288{
289 try
290 {
291 XRPL_ASSERT(getTxnType() == ttBATCH, "STTx::checkBatchSign : not a batch transaction");
292 if (getTxnType() != ttBATCH)
293 {
294 JLOG(debugLog().fatal()) << "not a batch transaction";
295 return Unexpected("Not a batch transaction.");
296 }
297 STArray const& signers{getFieldArray(sfBatchSigners)};
298 for (auto const& signer : signers)
299 {
300 Blob const& signingPubKey = signer.getFieldVL(sfSigningPubKey);
301 auto const result = signingPubKey.empty() ? checkBatchMultiSign(signer, rules)
302 : checkBatchSingleSign(signer);
303
304 if (!result)
305 return result;
306 }
307 return {};
308 }
309 catch (std::exception const& e)
310 {
311 JLOG(debugLog().error()) << "Batch signature check failed: " << e.what();
312 }
313 return Unexpected("Internal batch signature check failure.");
314}
315
318{
320 if (!(options & JsonOptions::disable_API_prior_V2))
321 ret[jss::hash] = to_string(getTransactionID());
322 return ret;
323}
324
326STTx::getJson(JsonOptions options, bool binary) const
327{
328 bool const V1 = !(options & JsonOptions::disable_API_prior_V2);
329
330 if (binary)
331 {
333 std::string const dataBin = strHex(s.peekData());
334
335 if (V1)
336 {
338 ret[jss::tx] = dataBin;
339 ret[jss::hash] = to_string(getTransactionID());
340 return ret;
341 }
342
343 return Json::Value{dataBin};
344 }
345
347 if (V1)
348 ret[jss::hash] = to_string(getTransactionID());
349
350 return ret;
351}
352
353std::string const&
355{
356 static std::string const sql =
357 "INSERT OR REPLACE INTO Transactions "
358 "(TransID, TransType, FromAcct, FromSeq, LedgerSeq, Status, RawTxn, "
359 "TxnMeta)"
360 " VALUES ";
361
362 return sql;
363}
364
366STTx::getMetaSQL(std::uint32_t inLedger, std::string const& escapedMetaData) const
367{
368 Serializer s;
369 add(s);
370 return getMetaSQL(s, inLedger, TxnSql::txnSqlValidated, escapedMetaData);
371}
372
373// VFALCO This could be a free function elsewhere
376 Serializer rawTxn,
377 std::uint32_t inLedger,
378 TxnSql status,
379 std::string const& escapedMetaData) const
380{
381 static boost::format const bfTrans("('%s', '%s', '%s', '%d', '%d', '%c', %s, %s)");
382 std::string rTxn = sqlBlobLiteral(rawTxn.peekData());
383
385 XRPL_ASSERT(format, "xrpl::STTx::getMetaSQL : non-null type format");
386
387 return str(
388 boost::format(bfTrans) % to_string(getTransactionID()) % format->getName() %
389 toBase58(getAccountID(sfAccount)) % getFieldU32(sfSequence) % inLedger %
390 safe_cast<char>(status) % rTxn % escapedMetaData);
391}
392
394singleSignHelper(STObject const& sigObject, Slice const& data)
395{
396 // We don't allow both a non-empty sfSigningPubKey and an sfSigners.
397 // That would allow the transaction to be signed two ways. So if both
398 // fields are present the signature is invalid.
399 if (sigObject.isFieldPresent(sfSigners))
400 return Unexpected("Cannot both single- and multi-sign.");
401
402 bool validSig = false;
403 try
404 {
405 auto const spk = sigObject.getFieldVL(sfSigningPubKey);
406 if (publicKeyType(makeSlice(spk)))
407 {
408 Blob const signature = sigObject.getFieldVL(sfTxnSignature);
409 validSig = verify(PublicKey(makeSlice(spk)), data, makeSlice(signature));
410 }
411 }
412 catch (std::exception const&)
413 {
414 validSig = false;
415 }
416
417 if (!validSig)
418 return Unexpected("Invalid signature.");
419
420 return {};
421}
422
423Expected<void, std::string>
424STTx::checkSingleSign(STObject const& sigObject) const
425{
426 auto const data = getSigningData(*this);
427 return singleSignHelper(sigObject, makeSlice(data));
428}
429
431STTx::checkBatchSingleSign(STObject const& batchSigner) const
432{
433 Serializer msg;
435 return singleSignHelper(batchSigner, msg.slice());
436}
437
440 STObject const& sigObject,
441 std::optional<AccountID> txnAccountID,
442 std::function<Serializer(AccountID const&)> makeMsg,
443 Rules const& rules)
444{
445 // Make sure the MultiSigners are present. Otherwise they are not
446 // attempting multi-signing and we just have a bad SigningPubKey.
447 if (!sigObject.isFieldPresent(sfSigners))
448 return Unexpected("Empty SigningPubKey.");
449
450 // We don't allow both an sfSigners and an sfTxnSignature. Both fields
451 // being present would indicate that the transaction is signed both ways.
452 if (sigObject.isFieldPresent(sfTxnSignature))
453 return Unexpected("Cannot both single- and multi-sign.");
454
455 STArray const& signers{sigObject.getFieldArray(sfSigners)};
456
457 // There are well known bounds that the number of signers must be within.
458 if (signers.size() < STTx::minMultiSigners || signers.size() > STTx::maxMultiSigners)
459 return Unexpected("Invalid Signers array size.");
460
461 // Signers must be in sorted order by AccountID.
462 AccountID lastAccountID(beast::zero);
463
464 for (auto const& signer : signers)
465 {
466 auto const accountID = signer.getAccountID(sfAccount);
467
468 // The account owner may not usually multisign for themselves.
469 // If they can, txnAccountID will be unseated, which is not equal to any
470 // value.
471 if (txnAccountID == accountID)
472 return Unexpected("Invalid multisigner.");
473
474 // No duplicate signers allowed.
475 if (lastAccountID == accountID)
476 return Unexpected("Duplicate Signers not allowed.");
477
478 // Accounts must be in order by account ID. No duplicates allowed.
479 if (lastAccountID > accountID)
480 return Unexpected("Unsorted Signers array.");
481
482 // The next signature must be greater than this one.
483 lastAccountID = accountID;
484
485 // Verify the signature.
486 bool validSig = false;
488 try
489 {
490 auto spk = signer.getFieldVL(sfSigningPubKey);
491 if (publicKeyType(makeSlice(spk)))
492 {
493 Blob const signature = signer.getFieldVL(sfTxnSignature);
494 validSig = verify(
495 PublicKey(makeSlice(spk)), makeMsg(accountID).slice(), makeSlice(signature));
496 }
497 }
498 catch (std::exception const& e)
499 {
500 // We assume any problem lies with the signature.
501 validSig = false;
502 errorWhat = e.what();
503 }
504 if (!validSig)
505 {
506 return Unexpected(
507 std::string("Invalid signature on account ") + toBase58(accountID) +
508 errorWhat.value_or("") + ".");
509 }
510 }
511 // All signatures verified.
512 return {};
513}
514
515Expected<void, std::string>
516STTx::checkBatchMultiSign(STObject const& batchSigner, Rules const& rules) const
517{
518 // We can ease the computational load inside the loop a bit by
519 // pre-constructing part of the data that we hash. Fill a Serializer
520 // with the stuff that stays constant from signature to signature.
521 Serializer dataStart;
523 return multiSignHelper(
524 batchSigner,
526 [&dataStart](AccountID const& accountID) -> Serializer {
527 Serializer s = dataStart;
528 finishMultiSigningData(accountID, s);
529 return s;
530 },
531 rules);
532}
533
535STTx::checkMultiSign(Rules const& rules, STObject const& sigObject) const
536{
537 // Used inside the loop in multiSignHelper to enforce that
538 // the account owner may not multisign for themselves.
539 auto const txnAccountID =
540 &sigObject != this ? std::nullopt : std::optional<AccountID>(getAccountID(sfAccount));
541
542 // We can ease the computational load inside the loop a bit by
543 // pre-constructing part of the data that we hash. Fill a Serializer
544 // with the stuff that stays constant from signature to signature.
545 Serializer dataStart = startMultiSigningData(*this);
546 return multiSignHelper(
547 sigObject,
548 txnAccountID,
549 [&dataStart](AccountID const& accountID) -> Serializer {
550 Serializer s = dataStart;
551 finishMultiSigningData(accountID, s);
552 return s;
553 },
554 rules);
555}
556
574{
575 XRPL_ASSERT(getTxnType() == ttBATCH, "STTx::getBatchTransactionIDs : not a batch transaction");
576 XRPL_ASSERT(
577 !getFieldArray(sfRawTransactions).empty(),
578 "STTx::getBatchTransactionIDs : empty raw transactions");
579
580 // The list of inner ids is built once, then reused on subsequent calls.
581 // After the list is built, it must always have the same size as the array
582 // `sfRawTransactions`. The assert below verifies that.
583 if (batchTxnIds_.empty())
584 {
585 for (STObject const& rb : getFieldArray(sfRawTransactions))
586 batchTxnIds_.push_back(rb.getHash(HashPrefix::transactionID));
587 }
588
589 XRPL_ASSERT(
590 batchTxnIds_.size() == getFieldArray(sfRawTransactions).size(),
591 "STTx::getBatchTransactionIDs : batch transaction IDs size mismatch");
592 return batchTxnIds_;
593}
594
595//------------------------------------------------------------------------------
596
597static bool
598isMemoOkay(STObject const& st, std::string& reason)
599{
600 if (!st.isFieldPresent(sfMemos))
601 return true;
602
603 auto const& memos = st.getFieldArray(sfMemos);
604
605 // The number 2048 is a preallocation hint, not a hard limit
606 // to avoid allocate/copy/free's
607 Serializer s(2048);
608 memos.add(s);
609
610 // FIXME move the memo limit into a config tunable
611 if (s.getDataLength() > 1024)
612 {
613 reason = "The memo exceeds the maximum allowed size.";
614 return false;
615 }
616
617 for (auto const& memo : memos)
618 {
619 auto memoObj = dynamic_cast<STObject const*>(&memo);
620
621 if ((memoObj == nullptr) || (memoObj->getFName() != sfMemo))
622 {
623 reason = "A memo array may contain only Memo objects.";
624 return false;
625 }
626
627 for (auto const& memoElement : *memoObj)
628 {
629 auto const& name = memoElement.getFName();
630
631 if (name != sfMemoType && name != sfMemoData && name != sfMemoFormat)
632 {
633 reason =
634 "A memo may contain only MemoType, MemoData or "
635 "MemoFormat fields.";
636 return false;
637 }
638
639 // The raw data is stored as hex-octets, which we want to decode.
640 auto optData = strUnHex(memoElement.getText());
641
642 if (!optData)
643 {
644 reason =
645 "The MemoType, MemoData and MemoFormat fields may "
646 "only contain hex-encoded data.";
647 return false;
648 }
649
650 if (name == sfMemoData)
651 continue;
652
653 // The only allowed characters for MemoType and MemoFormat are the
654 // characters allowed in URLs per RFC 3986: alphanumerics and the
655 // following symbols: -._~:/?#[]@!$&'()*+,;=%
656 static constexpr std::array<char, 256> const allowedSymbols = []() {
658
659 std::string_view const symbols(
660 "0123456789"
661 "-._~:/?#[]@!$&'()*+,;=%"
662 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
663 "abcdefghijklmnopqrstuvwxyz");
664
665 for (unsigned char const c : symbols)
666 a[c] = 1;
667 return a;
668 }();
669
670 for (unsigned char const c : *optData)
671 {
672 if (allowedSymbols[c] == 0)
673 {
674 reason =
675 "The MemoType and MemoFormat fields may only "
676 "contain characters that are allowed in URLs "
677 "under RFC 3986.";
678 return false;
679 }
680 }
681 }
682 }
683
684 return true;
685}
686
687// Ensure all account fields are 160-bits
688static bool
690{
691 for (int i = 0; i < st.getCount(); ++i)
692 {
693 auto t = dynamic_cast<STAccount const*>(st.peekAtPIndex(i));
694 if ((t != nullptr) && t->isDefault())
695 return false;
696 }
697
698 return true;
699}
700
701static bool
703{
704 auto const txType = tx[~sfTransactionType];
705 if (!txType)
706 return false;
707 if (auto const* item = TxFormats::getInstance().findByType(safe_cast<TxType>(*txType)))
708 {
709 for (auto const& e : item->getSOTemplate())
710 {
711 if (tx.isFieldPresent(e.sField()) && e.supportMPT() != soeMPTNone)
712 {
713 if (auto const& field = tx.peekAtField(e.sField());
714 (field.getSType() == STI_AMOUNT &&
715 safe_downcast<STAmount const&>(field).holds<MPTIssue>()) ||
716 (field.getSType() == STI_ISSUE &&
717 safe_downcast<STIssue const&>(field).holds<MPTIssue>()))
718 {
719 if (e.supportMPT() != soeMPTSupported)
720 return true;
721 }
722 }
723 }
724 }
725 return false;
726}
727
728static bool
730{
731 if (!st.isFieldPresent(sfRawTransactions))
732 return true;
733
734 if (st.isFieldPresent(sfBatchSigners) &&
735 st.getFieldArray(sfBatchSigners).size() > maxBatchTxCount)
736 {
737 reason = "Batch Signers array exceeds max entries.";
738 return false;
739 }
740
741 auto const& rawTxns = st.getFieldArray(sfRawTransactions);
742 if (rawTxns.size() > maxBatchTxCount)
743 {
744 reason = "Raw Transactions array exceeds max entries.";
745 return false;
746 }
747 for (STObject raw : rawTxns)
748 {
749 try
750 {
751 TxType const tt = safe_cast<TxType>(raw.getFieldU16(sfTransactionType));
752 if (tt == ttBATCH)
753 {
754 reason = "Raw Transactions may not contain batch transactions.";
755 return false;
756 }
757
758 raw.applyTemplate(getTxFormat(tt)->getSOTemplate());
759 }
760 catch (std::exception const& e)
761 {
762 reason = e.what();
763 return false;
764 }
765 }
766 return true;
767}
768
769bool
771{
772 if (!isMemoOkay(st, reason))
773 return false;
774
775 if (!isAccountFieldOkay(st))
776 {
777 reason = "An account field is invalid.";
778 return false;
779 }
780
781 if (isPseudoTx(st))
782 {
783 reason = "Cannot submit pseudo transactions.";
784 return false;
785 }
786
787 if (invalidMPTAmountInTx(st))
788 {
789 reason = "Amount can not be MPT.";
790 return false;
791 }
792
793 if (!isRawTransactionOkay(st, reason))
794 return false;
795
796 return true;
797}
798
800sterilize(STTx const& stx)
801{
802 Serializer s;
803 stx.add(s);
804 SerialIter sit(s.slice());
806}
807
808bool
810{
811 auto const t = tx[~sfTransactionType];
812
813 if (!t)
814 return false;
815
816 auto const tt = safe_cast<TxType>(*t);
817
818 return tt == ttAMENDMENT || tt == ttFEE || tt == ttUNL_MODIFY;
819}
820
821} // namespace xrpl
Represents a JSON value.
Definition json_value.h:130
Item const * findByType(KeyType type) const
Retrieve a format based on its type.
A public key.
Definition PublicKey.h:42
Rules controlling protocol behavior.
Definition Rules.h:18
size_type size() const
Definition STArray.h:225
A type which can be exported to a well known binary format.
Definition STBase.h:115
static STBase * emplace(std::size_t n, void *buf, T &&val)
Definition STBase.h:213
STBase const * peekAtPIndex(int offset) const
Definition STObject.h:1014
Json::Value getJson(JsonOptions=JsonOptions::none) const override
Definition STObject.cpp:831
Blob getFieldVL(SField const &field) const
Definition STObject.cpp:641
void addWithoutSigningFields(Serializer &s) const
Definition STObject.h:971
bool empty() const
Definition STObject.h:953
std::uint32_t getFieldU32(SField const &field) const
Definition STObject.cpp:593
void setFieldVL(SField const &field, Blob const &)
Definition STObject.cpp:777
T::value_type operator[](TypedField< T > const &f) const
Get the value of a field.
Definition STObject.h:1027
void applyTemplate(SOTemplate const &type)
Definition STObject.cpp:154
uint256 getHash(HashPrefix prefix) const
Definition STObject.cpp:367
std::string getFullText() const override
Definition STObject.cpp:286
STArray const & getFieldArray(SField const &field) const
Definition STObject.cpp:680
STObject & peekFieldObject(SField const &field)
Definition STObject.cpp:467
void add(Serializer &s) const override
Definition STObject.cpp:119
Serializer getSerializer() const
Definition STObject.h:980
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:456
int getCount() const
Definition STObject.h:996
void setFieldU16(SField const &field, std::uint16_t)
Definition STObject.cpp:729
STBase const & peekAtField(SField const &field) const
Definition STObject.cpp:401
void set(SOTemplate const &)
Definition STObject.cpp:134
uint256 getSigningHash(HashPrefix prefix) const
Definition STObject.cpp:376
STObject getFieldObject(SField const &field) const
Definition STObject.cpp:670
AccountID getAccountID(SField const &field) const
Definition STObject.cpp:635
std::uint16_t getFieldU16(SField const &field) const
Definition STObject.cpp:587
std::uint32_t getFlags() const
Definition STObject.cpp:509
std::string getFullText() const override
Definition STTx.cpp:131
Expected< void, std::string > checkBatchSingleSign(STObject const &batchSigner) const
Definition STTx.cpp:431
STBase * move(std::size_t n, void *buf) override
Definition STTx.cpp:118
Blob getSignature() const
Definition STTx.h:65
std::string getMetaSQL(std::uint32_t inLedger, std::string const &escapedMetaData) const
Definition STTx.cpp:366
TxType tx_type_
Definition STTx.h:30
Expected< void, std::string > checkMultiSign(Rules const &rules, STObject const &sigObject) const
Definition STTx.cpp:535
uint256 tid_
Definition STTx.h:29
Expected< void, std::string > checkBatchSign(Rules const &rules) const
Definition STTx.cpp:287
Json::Value getJson(JsonOptions options) const override
Definition STTx.cpp:317
static std::string const & getMetaSQLInsertReplaceHeader()
Definition STTx.cpp:354
std::vector< uint256 > const & getBatchTransactionIDs() const
Retrieves a batch of transaction IDs from the STTx.
Definition STTx.cpp:573
Expected< void, std::string > checkBatchMultiSign(STObject const &batchSigner, Rules const &rules) const
Definition STTx.cpp:516
SeqProxy getSeqProxy() const
Definition STTx.cpp:194
AccountID getFeePayer() const
Definition STTx.cpp:217
STBase * copy(std::size_t n, void *buf) const override
Definition STTx.cpp:112
STTx()=delete
static constexpr std::size_t minMultiSigners
Definition STTx.h:33
Expected< void, std::string > checkSign(Rules const &rules) const
Check the signature.
Definition STTx.cpp:272
std::uint32_t getSeqValue() const
Returns the first non-zero value of (Sequence, TicketSequence).
Definition STTx.cpp:211
TxType getTxnType() const
Definition STTx.h:188
std::vector< uint256 > batchTxnIds_
Definition STTx.h:162
Expected< void, std::string > checkSingleSign(STObject const &sigObject) const
Definition STTx.cpp:424
uint256 getSigningHash() const
Definition STTx.cpp:175
static constexpr std::size_t maxMultiSigners
Definition STTx.h:34
uint256 getTransactionID() const
Definition STTx.h:200
SerializedTypeID getSType() const override
Definition STTx.cpp:125
boost::container::flat_set< AccountID > getMentionedAccounts() const
Definition STTx.cpp:142
void sign(PublicKey const &publicKey, SecretKey const &secretKey, std::optional< std::reference_wrapper< SField const > > signatureTarget={})
Definition STTx.cpp:231
A secret key.
Definition SecretKey.h:18
A type that represents either a sequence value or a ticket value.
Definition SeqProxy.h:36
static constexpr SeqProxy sequence(std::uint32_t v)
Factory function to return a sequence-based SeqProxy.
Definition SeqProxy.h:56
constexpr std::uint32_t value() const
Definition SeqProxy.h:62
int getBytesLeft() const noexcept
Definition Serializer.h:349
Blob const & peekData() const
Definition Serializer.h:176
Slice slice() const noexcept
Definition Serializer.h:44
Blob getData() const
Definition Serializer.h:181
int getDataLength() const
Definition Serializer.h:192
An immutable linear range of bytes.
Definition Slice.h:26
static TxFormats const & getInstance()
Definition TxFormats.cpp:55
T empty(T... args)
T is_same_v
@ objectValue
object value (collection of name/value pairs).
Definition json_value.h:26
STL namespace.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
std::size_t constexpr txMinSizeBytes
Protocol specific constants.
Definition Protocol.h:22
Serializer startMultiSigningData(STObject const &obj)
Break the multi-signing hash computation into 2 parts for optimization.
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
TxType
Transaction type identifiers.
Definition TxFormats.h:39
bool isXRP(AccountID const &c)
Definition AccountID.h:70
beast::Journal debugLog()
Returns a debug journal.
Definition Log.cpp:453
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:602
std::string strHex(FwdIt begin, FwdIt end)
Definition strHex.h:10
Expected< void, std::string > multiSignHelper(STObject const &sigObject, std::optional< AccountID > txnAccountID, std::function< Serializer(AccountID const &)> makeMsg, Rules const &rules)
Definition STTx.cpp:439
bool verify(PublicKey const &publicKey, Slice const &m, Slice const &sig) noexcept
Verify a signature on a message.
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition AccountID.cpp:92
static bool isMemoOkay(STObject const &st, std::string &reason)
Definition STTx.cpp:598
static auto getTxFormat(TxType type)
Definition STTx.cpp:57
TxnSql
Definition STTx.h:18
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
base_uint< 256 > uint256
Definition base_uint.h:531
static bool isAccountFieldOkay(STObject const &st)
Definition STTx.cpp:689
void finishMultiSigningData(AccountID const &signingID, Serializer &s)
Definition Sign.h:64
std::size_t constexpr txMaxSizeBytes
Largest legal byte size of a transaction.
Definition Protocol.h:25
std::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
SerializedTypeID
Definition SField.h:90
std::vector< unsigned char > Blob
Storage for linear binary data.
Definition Blob.h:10
bool passesLocalChecks(STObject const &st, std::string &)
Definition STTx.cpp:770
static bool invalidMPTAmountInTx(STObject const &tx)
Definition STTx.cpp:702
std::size_t constexpr maxBatchTxCount
The maximum number of transactions that can be in a batch.
Definition Protocol.h:308
static bool isRawTransactionOkay(STObject const &st, std::string &reason)
Definition STTx.cpp:729
static Expected< void, std::string > singleSignHelper(STObject const &sigObject, Slice const &data)
Definition STTx.cpp:394
@ txSign
inner transaction to sign
@ transactionID
transaction plus signature to give transaction ID
std::string sqlBlobLiteral(Blob const &blob)
Format arbitrary binary data as an SQLite "blob literal".
Buffer sign(PublicKey const &pk, SecretKey const &sk, Slice const &message)
Generate a signature for a message.
static Blob getSigningData(STTx const &that)
Definition STTx.cpp:166
void serializeBatch(Serializer &msg, std::uint32_t const &flags, std::vector< uint256 > const &txids)
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:215
@ soeMPTSupported
Definition SOTemplate.h:24
@ soeMPTNone
Definition SOTemplate.h:24
std::shared_ptr< STTx const > sterilize(STTx const &stx)
Sterilize a transaction.
Definition STTx.cpp:800
constexpr std::enable_if_t< std::is_integral_v< Dest > &&std::is_integral_v< Src >, Dest > safe_cast(Src s) noexcept
Definition safe_cast.h:21
bool isPseudoTx(STObject const &tx)
Check whether a transaction is a pseudo-transaction.
Definition STTx.cpp:809
T ref(T... args)
Note, should be treated as flags that can be | and &.
Definition STBase.h:17
T to_string(T... args)
T value_or(T... args)
T what(T... args)