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