1#include <xrpl/protocol/STTx.h>
3#include <xrpl/basics/Blob.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/SecretKey.h>
28#include <xrpl/protocol/SeqProxy.h>
29#include <xrpl/protocol/Serializer.h>
30#include <xrpl/protocol/Sign.h>
31#include <xrpl/protocol/TxFlags.h>
32#include <xrpl/protocol/TxFormats.h>
33#include <xrpl/protocol/jss.h>
35#include <boost/container/flat_set.hpp>
60 if (format ==
nullptr)
98 set(format->getSOTemplate());
109 logicError(
"Transaction type was mutated during assembly");
124 return emplace(n, buf, std::move(*
this));
131 return STI_TRANSACTION;
145boost::container::flat_set<AccountID>
148 boost::container::flat_set<AccountID> list;
150 for (
auto const& it : *
this)
152 if (
auto sacc =
dynamic_cast<STAccount const*
>(&it))
154 XRPL_ASSERT(!sacc->isDefault(),
"xrpl::STTx::getMentionedAccounts : account is set");
155 if (!sacc->isDefault())
156 list.insert(sacc->value());
158 else if (
auto samt =
dynamic_cast<STAmount const*
>(&it))
160 auto const& issuer = samt->getIssuer();
248std::expected<void, std::string>
257 Blob const& signingPubKey = sigObject.
getFieldVL(sfSigningPubKey);
258 bool const multiSigning = signingPubKey.
empty();
259 auto const prefix =
signingPrefix(role, multiSigning, rules);
269std::expected<void, std::string>
284 auto const sponsorSignatureObj =
getFieldObject(sfSponsorSignature);
299std::expected<void, std::string>
307 UNREACHABLE(
"STTx::checkBatchSign : not a batch transaction");
326 UNREACHABLE(
"STTx::checkBatchSign : batch transactions not built");
331 for (
auto const& signer : signers)
333 Blob const& signingPubKey = signer.getFieldVL(sfSigningPubKey);
372 ret[jss::tx] = dataBin;
391 "INSERT OR REPLACE INTO Transactions "
392 "(TransID, TransType, FromAcct, FromSeq, LedgerSeq, Status, RawTxn, "
418 XRPL_ASSERT(format,
"xrpl::STTx::getMetaSQL : non-null type format");
421 "('{}', '{}', '{}', '{}', '{}', '{}', {}, {})",
432static std::expected<void, std::string>
441 bool validSig =
false;
444 auto const spk = sigObject.
getFieldVL(sfSigningPubKey);
462std::expected<void, std::string>
469std::expected<void, std::string>
472 XRPL_ASSERT(
getTxnType() == ttBATCH,
"STTx::checkBatchSingleSign : batch transaction");
479std::expected<void, std::string>
504 for (
auto const& signer : signers)
506 auto const accountID = signer.getAccountID(sfAccount);
511 if (txnAccountID == accountID)
515 if (lastAccountID == accountID)
519 if (lastAccountID > accountID)
523 lastAccountID = accountID;
526 bool validSig =
false;
530 auto spk = signer.getFieldVL(sfSigningPubKey);
533 Blob const signature = signer.getFieldVL(sfTxnSignature);
542 errorWhat = e.
what();
548 (errorWhat ?
": " + *errorWhat :
"") +
".");
555std::expected<void, std::string>
558 XRPL_ASSERT(
getTxnType() == ttBATCH,
"STTx::checkBatchMultiSign : batch transaction");
562 auto const batchSignerAccount = batchSigner.
getAccountID(sfAccount);
574std::expected<void, std::string>
581 auto const txnAccountID =
603 XRPL_ASSERT(!
isFree(),
"STTx::buildBatchTxns : template applied");
613 UNREACHABLE(
"STTx::buildBatchTxns : missing RawTransactions");
626 txns.reserve(raw.size());
629 if (rb.getFieldU16(sfTransactionType) == ttBATCH)
642 for (
auto const& stx : txns)
650 XRPL_ASSERT(
getTxnType() == ttBATCH,
"STTx::getBatchTransactions : batch transaction");
651 XRPL_ASSERT(
batchTxns_.has_value(),
"STTx::getBatchTransactions : batch transactions built");
654 "STTx::getBatchTransactions : batch transactions size mismatch");
676 return at(sfSponsor);
699 reason =
"The memo exceeds the maximum allowed size.";
703 for (
auto const& memo : memos)
705 auto memoObj =
dynamic_cast<STObject const*
>(&memo);
707 if ((memoObj ==
nullptr) || (memoObj->getFName() != sfMemo))
709 reason =
"A memo array may contain only Memo objects.";
713 for (
auto const& memoElement : *memoObj)
715 auto const& name = memoElement.getFName();
717 if (name != sfMemoType && name != sfMemoData && name != sfMemoFormat)
720 "A memo may contain only MemoType, MemoData or "
721 "MemoFormat fields.";
726 auto optData =
strUnHex(memoElement.getText());
731 "The MemoType, MemoData and MemoFormat fields may "
732 "only contain hex-encoded data.";
736 if (name == sfMemoData)
747 "-._~:/?#[]@!$&'()*+,;=%"
748 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
749 "abcdefghijklmnopqrstuvwxyz");
751 for (
unsigned char const c : symbols)
756 for (
unsigned char const c : *optData)
758 if (kAllowedSymbols[c] == 0)
761 "The MemoType and MemoFormat fields may only "
762 "contain characters that are allowed in URLs "
777 for (
int i = 0; i < st.
getCount(); ++i)
780 if ((t !=
nullptr) && t->isDefault())
790 auto const txType = tx[~sfTransactionType];
795 for (
auto const& e : item->getSOTemplate())
799 if (
auto const& field = tx.
peekAtField(e.sField());
800 (field.getSType() == STI_AMOUNT &&
802 (field.getSType() == STI_ISSUE &&
819 "xrpl::isBatchRawTransactionOkay : raw transactions only on batch");
827 reason =
"Batch transactions must contain raw transactions.";
835 reason =
"BatchSigners array exceeds max entries.";
857 reason =
"An account field is invalid.";
863 reason =
"Cannot submit pseudo transactions.";
869 reason =
"Amount can not be MPT.";
891 auto const t = tx[~sfTransactionType];
898 return tt == ttAMENDMENT || tt == ttFEE || tt == ttUNL_MODIFY;
UInt size() const
Number of values in array or object.
Rules controlling protocol behavior.
A type which can be exported to a well known binary format.
static STBase * emplace(std::size_t n, void *buf, T &&val)
T::value_type at(TypedField< T > const &f) const
Get the value of a field.
STBase const * peekAtPIndex(int offset) const
Blob getFieldVL(SField const &field) const
void addWithoutSigningFields(Serializer &s) const
UInt256 getSigningHash(HashPrefix prefix) const
std::uint32_t getFieldU32(SField const &field) const
void setFieldVL(SField const &field, Blob const &)
void applyTemplate(SOTemplate const &type)
std::string getFullText() const override
STArray const & getFieldArray(SField const &field) const
STObject & peekFieldObject(SField const &field)
json::Value getJson(JsonOptions=JsonOptions::Values::None) const override
void add(Serializer &s) const override
Serializer getSerializer() const
bool isFieldPresent(SField const &field) const
STObject(STObject const &)=default
void setFieldU16(SField const &field, std::uint16_t)
STBase const & peekAtField(SField const &field) const
void set(SOTemplate const &)
UInt256 getHash(HashPrefix prefix) const
STObject getFieldObject(SField const &field) const
AccountID getAccountID(SField const &field) const
std::uint16_t getFieldU16(SField const &field) const
std::uint32_t getFlags() const
std::string getFullText() const override
STBase * move(std::size_t n, void *buf) override
Blob getSignature() const
std::string getMetaSQL(std::uint32_t inLedger, std::string const &escapedMetaData) const
std::optional< std::vector< std::shared_ptr< STTx const > > > batchTxns_
static std::string const & getMetaSQLInsertReplaceHeader()
static constexpr std::size_t kMinMultiSigners
SeqProxy getSeqProxy() const
std::expected< void, std::string > checkBatchSingleSign(STObject const &batchSigner, std::vector< UInt256 > const &txIds) const
std::expected< void, std::string > checkSign(Rules const &rules) const
Check the signature.
std::expected< void, std::string > checkSingleSign(STObject const &sigObject, HashPrefix prefix) const
std::expected< void, std::string > checkBatchMultiSign(STObject const &batchSigner, std::vector< UInt256 > const &txIds) const
void sign(PublicKey const &publicKey, SecretKey const &secretKey)
Sign the transaction as its account.
STBase * copy(std::size_t n, void *buf) const override
static constexpr std::size_t kMaxMultiSigners
TxType getTxnType() const
UInt256 getTransactionID() const
AccountID getFeePayerID() const
UInt256 getSigningHash() const
json::Value getJson(JsonOptions options) const override
std::vector< UInt256 > getBatchTransactionIDs() const
The IDs of the inner transactions of a Batch.
AccountID getInitiator() const
The account responsible for the authorization: the delegate when sfDelegate is present,...
SerializedTypeID getSType() const override
boost::container::flat_set< AccountID > getMentionedAccounts() const
std::expected< void, std::string > checkMultiSign(STObject const &sigObject, HashPrefix prefix) const
std::vector< std::shared_ptr< STTx const > > const & getBatchTransactions() const
The inner transactions of a Batch, built and validated at construction.
std::expected< void, std::string > checkBatchSign() const
A type that represents either a sequence value or a ticket value.
static constexpr SeqProxy rawSequence(std::uint32_t v)
Factory function to return a sequence-based SeqProxy.
static constexpr SeqProxy rawTicket(std::uint32_t v)
Factory function to return a ticket-based SeqProxy.
int getBytesLeft() const noexcept
Blob const & peekData() const
int addBitString(BaseUInt< Bits, Tag > const &v)
Slice slice() const noexcept
int getDataLength() const
An immutable linear range of bytes.
@ Object
object value (collection of name/value pairs).
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
constexpr FlagValue spfSponsorFee
Serializer startMultiSigningData(STObject const &obj, HashPrefix prefix)
Break the multi-signing hash computation into 2 parts for optimization.
constexpr std::size_t kMaxBatchSigners
The maximum number of batch signers.
std::expected< void, std::string > multiSignHelper(STObject const &sigObject, std::optional< AccountID > txnAccountID, std::function< Serializer(AccountID const &)> makeMsg)
TxType
Transaction type identifiers.
bool isXRP(AccountID const &c)
HashPrefix signingPrefix(SignatureRole role, bool multiSigning, Rules const &rules)
The hash prefix that binds a transaction signature to the role that made it.
std::string strHex(FwdIt begin, FwdIt end)
constexpr std::size_t kMaxBatchTxCount
The maximum number of transactions that can be in a batch.
constexpr std::size_t kTxMinSizeBytes
Protocol specific constants.
bool verify(PublicKey const &publicKey, Slice const &m, Slice const &sig) noexcept
Verify a signature on a message.
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
static bool isBatchRawTransactionOkay(STTx const &tx, std::string &reason)
static Blob getSigningData(STTx const &that, HashPrefix prefix)
static bool isMemoOkay(STObject const &st, std::string &reason)
constexpr Dest safeCast(Src s) noexcept
static auto getTxFormat(TxType type)
std::string to_string(BaseUInt< Bits, Tag > const &a)
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.
SField const * signatureField(SignatureRole role)
The field that holds this role's signature.
static bool isAccountFieldOkay(STObject const &st)
bool passesLocalChecks(STTx const &tx, std::string &)
Slice makeSlice(std::array< T, N > const &a)
void finishMultiSigningData(AccountID const &signingID, Serializer &s)
static std::expected< void, std::string > singleSignHelper(STObject const &sigObject, Slice const &data)
std::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
SignatureRole
The signature slots on a transaction.
@ Transaction
The transaction's own signature, in sfTxnSignature or sfSigners.
@ Sponsor
The sponsor's signature, in sfSponsorSignature.
@ Counterparty
The counterparty's signature, in sfCounterpartySignature.
static bool invalidMPTAmountInTx(STObject const &tx)
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
HashPrefix
Prefix for hashing functions.
@ TxSign
inner transaction to sign
@ TransactionId
transaction plus signature to give transaction ID
std::string sqlBlobLiteral(Blob const &blob)
Format arbitrary binary data as an SQLite "blob literal".
Dest safeDowncast(Src *s) noexcept
Buffer sign(PublicKey const &pk, SecretKey const &sk, Slice const &message)
Generate a signature for a message.
std::vector< unsigned char > Blob
Storage for linear binary data.
void serializeBatch(Serializer &msg, AccountID const &outerAccount, std::uint32_t outerSeqValue, std::uint32_t const &flags, std::vector< UInt256 > const &txids)
std::shared_ptr< STTx const > sterilize(STTx const &stx)
Sterilize a transaction.
bool isPseudoTx(STObject const &tx)
Check whether a transaction is a pseudo-transaction.
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
constexpr std::size_t kTxMaxSizeBytes
Largest legal byte size of a transaction.
Note, should be treated as flags that can be | and &.