rippled
Loading...
Searching...
No Matches
STTx.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012, 2013 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 <xrpl/basics/Blob.h>
21#include <xrpl/basics/Expected.h>
22#include <xrpl/basics/Slice.h>
23#include <xrpl/basics/StringUtilities.h>
24#include <xrpl/basics/base_uint.h>
25#include <xrpl/basics/contract.h>
26#include <xrpl/basics/safe_cast.h>
27#include <xrpl/basics/strHex.h>
28#include <xrpl/beast/utility/Zero.h>
29#include <xrpl/beast/utility/instrumentation.h>
30#include <xrpl/json/json_value.h>
31#include <xrpl/protocol/AccountID.h>
32#include <xrpl/protocol/HashPrefix.h>
33#include <xrpl/protocol/MPTIssue.h>
34#include <xrpl/protocol/Protocol.h>
35#include <xrpl/protocol/PublicKey.h>
36#include <xrpl/protocol/Rules.h>
37#include <xrpl/protocol/SField.h>
38#include <xrpl/protocol/SOTemplate.h>
39#include <xrpl/protocol/STAccount.h>
40#include <xrpl/protocol/STAmount.h>
41#include <xrpl/protocol/STArray.h>
42#include <xrpl/protocol/STBase.h>
43#include <xrpl/protocol/STObject.h>
44#include <xrpl/protocol/STTx.h>
45#include <xrpl/protocol/SecretKey.h>
46#include <xrpl/protocol/SeqProxy.h>
47#include <xrpl/protocol/Serializer.h>
48#include <xrpl/protocol/Sign.h>
49#include <xrpl/protocol/TxFlags.h>
50#include <xrpl/protocol/TxFormats.h>
51#include <xrpl/protocol/jss.h>
52
53#include <boost/container/flat_set.hpp>
54#include <boost/format/format_fwd.hpp>
55#include <boost/format/free_funcs.hpp>
56
57#include <array>
58#include <cstddef>
59#include <cstdint>
60#include <exception>
61#include <functional>
62#include <memory>
63#include <optional>
64#include <stdexcept>
65#include <string>
66#include <string_view>
67#include <type_traits>
68#include <utility>
69
70namespace ripple {
71
72static auto
74{
75 auto format = TxFormats::getInstance().findByType(type);
76
77 if (format == nullptr)
78 {
79 Throw<std::runtime_error>(
80 "Invalid transaction type " +
82 }
83
84 return format;
85}
86
87STTx::STTx(STObject&& object) : STObject(std::move(object))
88{
89 tx_type_ = safe_cast<TxType>(getFieldU16(sfTransactionType));
90 applyTemplate(getTxFormat(tx_type_)->getSOTemplate()); // may throw
92}
93
94STTx::STTx(SerialIter& sit) : STObject(sfTransaction)
95{
96 int length = sit.getBytesLeft();
97
98 if ((length < txMinSizeBytes) || (length > txMaxSizeBytes))
99 Throw<std::runtime_error>("Transaction length invalid");
100
101 if (set(sit))
102 Throw<std::runtime_error>("Transaction contains an object terminator");
103
104 tx_type_ = safe_cast<TxType>(getFieldU16(sfTransactionType));
105
106 applyTemplate(getTxFormat(tx_type_)->getSOTemplate()); // May throw
108}
109
110STTx::STTx(TxType type, std::function<void(STObject&)> assembler)
111 : STObject(sfTransaction)
112{
113 auto format = getTxFormat(type);
114
115 set(format->getSOTemplate());
116 setFieldU16(sfTransactionType, format->getType());
117
118 assembler(*this);
119
120 tx_type_ = safe_cast<TxType>(getFieldU16(sfTransactionType));
121
122 if (tx_type_ != type)
123 LogicError("Transaction type was mutated during assembly");
124
126}
127
128STBase*
129STTx::copy(std::size_t n, void* buf) const
130{
131 return emplace(n, buf, *this);
132}
133
134STBase*
136{
137 return emplace(n, buf, std::move(*this));
138}
139
140// STObject functions.
143{
144 return STI_TRANSACTION;
145}
146
149{
150 std::string ret = "\"";
151 ret += to_string(getTransactionID());
152 ret += "\" = {";
153 ret += STObject::getFullText();
154 ret += "}";
155 return ret;
156}
157
158boost::container::flat_set<AccountID>
160{
161 boost::container::flat_set<AccountID> list;
162
163 for (auto const& it : *this)
164 {
165 if (auto sacc = dynamic_cast<STAccount const*>(&it))
166 {
167 XRPL_ASSERT(
168 !sacc->isDefault(),
169 "ripple::STTx::getMentionedAccounts : account is set");
170 if (!sacc->isDefault())
171 list.insert(sacc->value());
172 }
173 else if (auto samt = dynamic_cast<STAmount const*>(&it))
174 {
175 auto const& issuer = samt->getIssuer();
176 if (!isXRP(issuer))
177 list.insert(issuer);
178 }
179 }
180
181 return list;
182}
183
184static Blob
186{
187 Serializer s;
190 return s.getData();
191}
192
195{
197}
198
199Blob
201{
202 try
203 {
204 return getFieldVL(sfTxnSignature);
205 }
206 catch (std::exception const&)
207 {
208 return Blob();
209 }
210}
211
214{
215 std::uint32_t const seq{getFieldU32(sfSequence)};
216 if (seq != 0)
217 return SeqProxy::sequence(seq);
218
219 std::optional<std::uint32_t> const ticketSeq{operator[](~sfTicketSequence)};
220 if (!ticketSeq)
221 // No TicketSequence specified. Return the Sequence, whatever it is.
222 return SeqProxy::sequence(seq);
223
224 return SeqProxy{SeqProxy::ticket, *ticketSeq};
225}
226
227void
228STTx::sign(PublicKey const& publicKey, SecretKey const& secretKey)
229{
230 auto const data = getSigningData(*this);
231
232 auto const sig = ripple::sign(publicKey, secretKey, makeSlice(data));
233
234 setFieldVL(sfTxnSignature, sig);
236}
237
240 RequireFullyCanonicalSig requireCanonicalSig,
241 Rules const& rules) const
242{
243 try
244 {
245 // Determine whether we're single- or multi-signing by looking
246 // at the SigningPubKey. If it's empty we must be
247 // multi-signing. Otherwise we're single-signing.
248 Blob const& signingPubKey = getFieldVL(sfSigningPubKey);
249 return signingPubKey.empty()
250 ? checkMultiSign(requireCanonicalSig, rules)
251 : checkSingleSign(requireCanonicalSig);
252 }
253 catch (std::exception const&)
254 {
255 }
256 return Unexpected("Internal signature check failure.");
257}
258
261{
263 if (!(options & JsonOptions::disable_API_prior_V2))
264 ret[jss::hash] = to_string(getTransactionID());
265 return ret;
266}
267
269STTx::getJson(JsonOptions options, bool binary) const
270{
271 bool const V1 = !(options & JsonOptions::disable_API_prior_V2);
272
273 if (binary)
274 {
276 std::string const dataBin = strHex(s.peekData());
277
278 if (V1)
279 {
281 ret[jss::tx] = dataBin;
282 ret[jss::hash] = to_string(getTransactionID());
283 return ret;
284 }
285 else
286 return Json::Value{dataBin};
287 }
288
290 if (V1)
291 ret[jss::hash] = to_string(getTransactionID());
292
293 return ret;
294}
295
296std::string const&
298{
299 static std::string const sql =
300 "INSERT OR REPLACE INTO Transactions "
301 "(TransID, TransType, FromAcct, FromSeq, LedgerSeq, Status, RawTxn, "
302 "TxnMeta)"
303 " VALUES ";
304
305 return sql;
306}
307
309STTx::getMetaSQL(std::uint32_t inLedger, std::string const& escapedMetaData)
310 const
311{
312 Serializer s;
313 add(s);
314 return getMetaSQL(s, inLedger, txnSqlValidated, escapedMetaData);
315}
316
317// VFALCO This could be a free function elsewhere
320 Serializer rawTxn,
321 std::uint32_t inLedger,
322 char status,
323 std::string const& escapedMetaData) const
324{
325 static boost::format bfTrans(
326 "('%s', '%s', '%s', '%d', '%d', '%c', %s, %s)");
327 std::string rTxn = sqlBlobLiteral(rawTxn.peekData());
328
330 XRPL_ASSERT(format, "ripple::STTx::getMetaSQL : non-null type format");
331
332 return str(
333 boost::format(bfTrans) % to_string(getTransactionID()) %
334 format->getName() % toBase58(getAccountID(sfAccount)) %
335 getFieldU32(sfSequence) % inLedger % status % rTxn % escapedMetaData);
336}
337
340{
341 // We don't allow both a non-empty sfSigningPubKey and an sfSigners.
342 // That would allow the transaction to be signed two ways. So if both
343 // fields are present the signature is invalid.
344 if (isFieldPresent(sfSigners))
345 return Unexpected("Cannot both single- and multi-sign.");
346
347 bool validSig = false;
348 try
349 {
350 bool const fullyCanonical = (getFlags() & tfFullyCanonicalSig) ||
351 (requireCanonicalSig == RequireFullyCanonicalSig::yes);
352
353 auto const spk = getFieldVL(sfSigningPubKey);
354
355 if (publicKeyType(makeSlice(spk)))
356 {
357 Blob const signature = getFieldVL(sfTxnSignature);
358 Blob const data = getSigningData(*this);
359
360 validSig = verify(
361 PublicKey(makeSlice(spk)),
362 makeSlice(data),
363 makeSlice(signature),
365 }
366 }
367 catch (std::exception const&)
368 {
369 // Assume it was a signature failure.
370 validSig = false;
371 }
372 if (validSig == false)
373 return Unexpected("Invalid signature.");
374 // Signature was verified.
375 return {};
376}
377
380 RequireFullyCanonicalSig requireCanonicalSig,
381 Rules const& rules) const
382{
383 // Make sure the MultiSigners are present. Otherwise they are not
384 // attempting multi-signing and we just have a bad SigningPubKey.
385 if (!isFieldPresent(sfSigners))
386 return Unexpected("Empty SigningPubKey.");
387
388 // We don't allow both an sfSigners and an sfTxnSignature. Both fields
389 // being present would indicate that the transaction is signed both ways.
390 if (isFieldPresent(sfTxnSignature))
391 return Unexpected("Cannot both single- and multi-sign.");
392
393 STArray const& signers{getFieldArray(sfSigners)};
394
395 // There are well known bounds that the number of signers must be within.
396 if (signers.size() < minMultiSigners ||
397 signers.size() > maxMultiSigners(&rules))
398 return Unexpected("Invalid Signers array size.");
399
400 // We can ease the computational load inside the loop a bit by
401 // pre-constructing part of the data that we hash. Fill a Serializer
402 // with the stuff that stays constant from signature to signature.
403 Serializer const dataStart{startMultiSigningData(*this)};
404
405 // We also use the sfAccount field inside the loop. Get it once.
406 auto const txnAccountID = getAccountID(sfAccount);
407
408 // Determine whether signatures must be full canonical.
409 bool const fullyCanonical = (getFlags() & tfFullyCanonicalSig) ||
410 (requireCanonicalSig == RequireFullyCanonicalSig::yes);
411
412 // Signers must be in sorted order by AccountID.
413 AccountID lastAccountID(beast::zero);
414
415 for (auto const& signer : signers)
416 {
417 auto const accountID = signer.getAccountID(sfAccount);
418
419 // The account owner may not multisign for themselves.
420 if (accountID == txnAccountID)
421 return Unexpected("Invalid multisigner.");
422
423 // No duplicate signers allowed.
424 if (lastAccountID == accountID)
425 return Unexpected("Duplicate Signers not allowed.");
426
427 // Accounts must be in order by account ID. No duplicates allowed.
428 if (lastAccountID > accountID)
429 return Unexpected("Unsorted Signers array.");
430
431 // The next signature must be greater than this one.
432 lastAccountID = accountID;
433
434 // Verify the signature.
435 bool validSig = false;
436 try
437 {
438 Serializer s = dataStart;
439 finishMultiSigningData(accountID, s);
440
441 auto spk = signer.getFieldVL(sfSigningPubKey);
442
443 if (publicKeyType(makeSlice(spk)))
444 {
445 Blob const signature = signer.getFieldVL(sfTxnSignature);
446
447 validSig = verify(
448 PublicKey(makeSlice(spk)),
449 s.slice(),
450 makeSlice(signature),
452 }
453 }
454 catch (std::exception const&)
455 {
456 // We assume any problem lies with the signature.
457 validSig = false;
458 }
459 if (!validSig)
460 return Unexpected(
461 std::string("Invalid signature on account ") +
462 toBase58(accountID) + ".");
463 }
464 // All signatures verified.
465 return {};
466}
467
468//------------------------------------------------------------------------------
469
470static bool
471isMemoOkay(STObject const& st, std::string& reason)
472{
473 if (!st.isFieldPresent(sfMemos))
474 return true;
475
476 auto const& memos = st.getFieldArray(sfMemos);
477
478 // The number 2048 is a preallocation hint, not a hard limit
479 // to avoid allocate/copy/free's
480 Serializer s(2048);
481 memos.add(s);
482
483 // FIXME move the memo limit into a config tunable
484 if (s.getDataLength() > 1024)
485 {
486 reason = "The memo exceeds the maximum allowed size.";
487 return false;
488 }
489
490 for (auto const& memo : memos)
491 {
492 auto memoObj = dynamic_cast<STObject const*>(&memo);
493
494 if (!memoObj || (memoObj->getFName() != sfMemo))
495 {
496 reason = "A memo array may contain only Memo objects.";
497 return false;
498 }
499
500 for (auto const& memoElement : *memoObj)
501 {
502 auto const& name = memoElement.getFName();
503
504 if (name != sfMemoType && name != sfMemoData &&
505 name != sfMemoFormat)
506 {
507 reason =
508 "A memo may contain only MemoType, MemoData or "
509 "MemoFormat fields.";
510 return false;
511 }
512
513 // The raw data is stored as hex-octets, which we want to decode.
514 auto optData = strUnHex(memoElement.getText());
515
516 if (!optData)
517 {
518 reason =
519 "The MemoType, MemoData and MemoFormat fields may "
520 "only contain hex-encoded data.";
521 return false;
522 }
523
524 if (name == sfMemoData)
525 continue;
526
527 // The only allowed characters for MemoType and MemoFormat are the
528 // characters allowed in URLs per RFC 3986: alphanumerics and the
529 // following symbols: -._~:/?#[]@!$&'()*+,;=%
530 static constexpr std::array<char, 256> const allowedSymbols = []() {
532
533 std::string_view symbols(
534 "0123456789"
535 "-._~:/?#[]@!$&'()*+,;=%"
536 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
537 "abcdefghijklmnopqrstuvwxyz");
538
539 for (char c : symbols)
540 a[c] = 1;
541 return a;
542 }();
543
544 for (auto c : *optData)
545 {
546 if (!allowedSymbols[c])
547 {
548 reason =
549 "The MemoType and MemoFormat fields may only "
550 "contain characters that are allowed in URLs "
551 "under RFC 3986.";
552 return false;
553 }
554 }
555 }
556 }
557
558 return true;
559}
560
561// Ensure all account fields are 160-bits
562static bool
564{
565 for (int i = 0; i < st.getCount(); ++i)
566 {
567 auto t = dynamic_cast<STAccount const*>(st.peekAtPIndex(i));
568 if (t && t->isDefault())
569 return false;
570 }
571
572 return true;
573}
574
575static bool
577{
578 auto const txType = tx[~sfTransactionType];
579 if (!txType)
580 return false;
581 if (auto const* item =
582 TxFormats::getInstance().findByType(safe_cast<TxType>(*txType)))
583 {
584 for (auto const& e : item->getSOTemplate())
585 {
586 if (tx.isFieldPresent(e.sField()) && e.supportMPT() != soeMPTNone)
587 {
588 if (auto const& field = tx.peekAtField(e.sField());
589 (field.getSType() == STI_AMOUNT &&
590 static_cast<STAmount const&>(field).holds<MPTIssue>()) ||
591 (field.getSType() == STI_ISSUE &&
592 static_cast<STIssue const&>(field).holds<MPTIssue>()))
593 {
594 if (e.supportMPT() != soeMPTSupported)
595 return true;
596 }
597 }
598 }
599 }
600 return false;
601}
602
603bool
605{
606 if (!isMemoOkay(st, reason))
607 return false;
608
609 if (!isAccountFieldOkay(st))
610 {
611 reason = "An account field is invalid.";
612 return false;
613 }
614
615 if (isPseudoTx(st))
616 {
617 reason = "Cannot submit pseudo transactions.";
618 return false;
619 }
620
621 if (invalidMPTAmountInTx(st))
622 {
623 reason = "Amount can not be MPT.";
624 return false;
625 }
626
627 return true;
628}
629
631sterilize(STTx const& stx)
632{
633 Serializer s;
634 stx.add(s);
635 SerialIter sit(s.slice());
636 return std::make_shared<STTx const>(std::ref(sit));
637}
638
639bool
641{
642 auto t = tx[~sfTransactionType];
643 if (!t)
644 return false;
645 auto tt = safe_cast<TxType>(*t);
646 return tt == ttAMENDMENT || tt == ttFEE || tt == ttUNL_MODIFY;
647}
648
649} // namespace ripple
Represents a JSON value.
Definition: json_value.h:148
Item const * findByType(KeyType type) const
Retrieve a format based on its type.
Definition: KnownFormats.h:129
A public key.
Definition: PublicKey.h:62
Rules controlling protocol behavior.
Definition: Rules.h:35
constexpr bool holds() const noexcept
Definition: STAmount.h:456
A type which can be exported to a well known binary format.
Definition: STBase.h:126
static STBase * emplace(std::size_t n, void *buf, T &&val)
Definition: STBase.h:224
bool holds() const
Definition: STIssue.h:114
Blob getFieldVL(SField const &field) const
Definition: STObject.cpp:657
AccountID getAccountID(SField const &field) const
Definition: STObject.cpp:651
const STArray & getFieldArray(SField const &field) const
Definition: STObject.cpp:686
std::uint16_t getFieldU16(SField const &field) const
Definition: STObject.cpp:609
std::uint32_t getFieldU32(SField const &field) const
Definition: STObject.cpp:615
int getCount() const
Definition: STObject.h:968
void setFieldU16(SField const &field, std::uint16_t)
Definition: STObject.cpp:735
const STBase * peekAtPIndex(int offset) const
Definition: STObject.h:986
Serializer getSerializer() const
Definition: STObject.h:952
void add(Serializer &s) const override
Definition: STObject.cpp:141
uint256 getSigningHash(HashPrefix prefix) const
Definition: STObject.cpp:404
T::value_type operator[](TypedField< T > const &f) const
Get the value of a field.
Definition: STObject.h:999
uint256 getHash(HashPrefix prefix) const
Definition: STObject.cpp:395
void set(const SOTemplate &)
Definition: STObject.cpp:156
std::string getFullText() const override
Definition: STObject.cpp:310
const STBase & peekAtField(SField const &field) const
Definition: STObject.cpp:429
bool isFieldPresent(SField const &field) const
Definition: STObject.cpp:484
Json::Value getJson(JsonOptions options) const override
Definition: STObject.cpp:825
void applyTemplate(const SOTemplate &type)
Definition: STObject.cpp:172
void addWithoutSigningFields(Serializer &s) const
Definition: STObject.h:943
void setFieldVL(SField const &field, Blob const &)
Definition: STObject.cpp:777
std::uint32_t getFlags() const
Definition: STObject.cpp:537
boost::container::flat_set< AccountID > getMentionedAccounts() const
Definition: STTx.cpp:159
uint256 getSigningHash() const
Definition: STTx.cpp:194
static std::string const & getMetaSQLInsertReplaceHeader()
Definition: STTx.cpp:297
void sign(PublicKey const &publicKey, SecretKey const &secretKey)
Definition: STTx.cpp:228
Expected< void, std::string > checkMultiSign(RequireFullyCanonicalSig requireCanonicalSig, Rules const &rules) const
Definition: STTx.cpp:379
SeqProxy getSeqProxy() const
Definition: STTx.cpp:213
Json::Value getJson(JsonOptions options) const override
Definition: STTx.cpp:260
Expected< void, std::string > checkSingleSign(RequireFullyCanonicalSig requireCanonicalSig) const
Definition: STTx.cpp:339
STBase * move(std::size_t n, void *buf) override
Definition: STTx.cpp:135
static std::size_t const minMultiSigners
Definition: STTx.h:53
Expected< void, std::string > checkSign(RequireFullyCanonicalSig requireCanonicalSig, Rules const &rules) const
Definition: STTx.cpp:239
static std::size_t maxMultiSigners(Rules const *rules=0)
Definition: STTx.h:57
RequireFullyCanonicalSig
Check the signature.
Definition: STTx.h:123
TxType tx_type_
Definition: STTx.h:50
uint256 tid_
Definition: STTx.h:49
Blob getSignature() const
Definition: STTx.cpp:200
STTx()=delete
std::string getMetaSQL(std::uint32_t inLedger, std::string const &escapedMetaData) const
Definition: STTx.cpp:309
uint256 getTransactionID() const
Definition: STTx.h:194
SerializedTypeID getSType() const override
Definition: STTx.cpp:142
std::string getFullText() const override
Definition: STTx.cpp:148
STBase * copy(std::size_t n, void *buf) const override
Definition: STTx.cpp:129
A secret key.
Definition: SecretKey.h:38
A type that represents either a sequence value or a ticket value.
Definition: SeqProxy.h:56
static constexpr SeqProxy sequence(std::uint32_t v)
Factory function to return a sequence-based SeqProxy.
Definition: SeqProxy.h:76
int getBytesLeft() const noexcept
Definition: Serializer.h:377
Slice slice() const noexcept
Definition: Serializer.h:67
Blob const & peekData() const
Definition: Serializer.h:203
Blob getData() const
Definition: Serializer.h:208
int getDataLength() const
Definition: Serializer.h:219
static TxFormats const & getInstance()
Definition: TxFormats.cpp:70
T empty(T... args)
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:44
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition: AccountID.cpp:114
std::shared_ptr< STTx const > sterilize(STTx const &stx)
Sterilize a transaction.
Definition: STTx.cpp:631
bool isXRP(AccountID const &c)
Definition: AccountID.h:91
std::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
static bool isAccountFieldOkay(STObject const &st)
Definition: STTx.cpp:563
void finishMultiSigningData(AccountID const &signingID, Serializer &s)
Definition: Sign.h:86
TxType
Transaction type identifiers.
Definition: TxFormats.h:57
bool isPseudoTx(STObject const &tx)
Check whether a transaction is a pseudo-transaction.
Definition: STTx.cpp:640
Serializer startMultiSigningData(STObject const &obj)
Break the multi-signing hash computation into 2 parts for optimization.
Definition: Sign.cpp:104
bool verify(PublicKey const &publicKey, Slice const &m, Slice const &sig, bool mustBeFullyCanonical=true) noexcept
Verify a signature on a message.
Definition: PublicKey.cpp:288
base_uint< 256 > uint256
Definition: base_uint.h:558
static bool isMemoOkay(STObject const &st, std::string &reason)
Definition: STTx.cpp:471
SerializedTypeID
Definition: SField.h:108
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:42
std::size_t constexpr txMinSizeBytes
Protocol specific constants.
Definition: Protocol.h:42
static auto getTxFormat(TxType type)
Definition: STTx.cpp:73
Buffer sign(PublicKey const &pk, SecretKey const &sk, Slice const &message)
Generate a signature for a message.
Definition: SecretKey.cpp:256
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
Definition: PublicKey.cpp:223
static bool invalidMPTAmountInTx(STObject const &tx)
Definition: STTx.cpp:576
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:30
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:244
@ txnSqlValidated
Definition: STTx.h:42
std::vector< unsigned char > Blob
Storage for linear binary data.
Definition: Blob.h:30
static Blob getSigningData(STTx const &that)
Definition: STTx.cpp:185
bool passesLocalChecks(STObject const &st, std::string &)
Definition: STTx.cpp:604
@ soeMPTNone
Definition: SOTemplate.h:44
@ soeMPTSupported
Definition: SOTemplate.h:44
std::size_t constexpr txMaxSizeBytes
Largest legal byte size of a transaction.
Definition: Protocol.h:45
std::string to_string(base_uint< Bits, Tag > const &a)
Definition: base_uint.h:630
constexpr std::uint32_t tfFullyCanonicalSig
Transaction flags.
Definition: TxFlags.h:60
@ txSign
inner transaction to sign
@ transactionID
transaction plus signature to give transaction ID
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
Definition: contract.cpp:37
STL namespace.
T ref(T... args)
Note, should be treated as flags that can be | and &.
Definition: STBase.h:38
T to_string(T... args)