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