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