1#include <xrpld/rpc/detail/TransactionSign.h>
3#include <xrpld/app/ledger/OpenLedger.h>
4#include <xrpld/app/main/Application.h>
5#include <xrpld/app/misc/DeliverMax.h>
6#include <xrpld/app/misc/Transaction.h>
7#include <xrpld/app/misc/TxQ.h>
8#include <xrpld/rpc/Role.h>
9#include <xrpld/rpc/detail/AssetCache.h>
10#include <xrpld/rpc/detail/LegacyPathFind.h>
11#include <xrpld/rpc/detail/Pathfinder.h>
12#include <xrpld/rpc/detail/RPCHelpers.h>
13#include <xrpld/rpc/detail/Tuning.h>
15#include <xrpl/basics/Blob.h>
16#include <xrpl/basics/Buffer.h>
17#include <xrpl/basics/Log.h>
18#include <xrpl/basics/Number.h>
19#include <xrpl/basics/Slice.h>
20#include <xrpl/basics/base_uint.h>
21#include <xrpl/basics/contract.h>
22#include <xrpl/basics/strHex.h>
23#include <xrpl/beast/utility/instrumentation.h>
24#include <xrpl/core/NetworkIDService.h>
25#include <xrpl/json/json_writer.h>
26#include <xrpl/protocol/AccountID.h>
27#include <xrpl/protocol/ApiVersion.h>
28#include <xrpl/protocol/ErrorCodes.h>
29#include <xrpl/protocol/Feature.h>
30#include <xrpl/protocol/Indexes.h>
31#include <xrpl/protocol/InnerObjectFormats.h>
32#include <xrpl/protocol/Issue.h>
33#include <xrpl/protocol/LedgerFormats.h>
34#include <xrpl/protocol/MPTIssue.h>
35#include <xrpl/protocol/PublicKey.h>
36#include <xrpl/protocol/RPCErr.h>
37#include <xrpl/protocol/SField.h>
38#include <xrpl/protocol/STAmount.h>
39#include <xrpl/protocol/STArray.h>
40#include <xrpl/protocol/STObject.h>
41#include <xrpl/protocol/STParsedJSON.h>
42#include <xrpl/protocol/STPathSet.h>
43#include <xrpl/protocol/STTx.h>
44#include <xrpl/protocol/SecretKey.h>
45#include <xrpl/protocol/Serializer.h>
46#include <xrpl/protocol/Sign.h>
47#include <xrpl/protocol/TER.h>
48#include <xrpl/protocol/Units.h>
49#include <xrpl/protocol/XRPAmount.h>
50#include <xrpl/protocol/jss.h>
51#include <xrpl/server/LoadFeeTrack.h>
52#include <xrpl/tx/apply.h>
53#include <xrpl/tx/applySteps.h>
121 logicError(
"Accessing unknown SigningForParams::getSigner()");
129 logicError(
"Accessing unknown SigningForParams::getPublicKey()");
133 [[nodiscard]]
Buffer const&
173 bool const isMasterKey = publicKeyAcctID == accountID;
185 auto const& sle = *accountState;
188 if (sle.isFlag(lsfDisableMaster))
194 if ((sle.isFieldPresent(sfRegularKey)) && (publicKeyAcctID == sle.getAccountID(sfRegularKey)))
211 if (txJson[jss::TransactionType].asString() != jss::Payment)
215 if (txJson.
isMember(jss::DeliverMax))
219 if (txJson[jss::DeliverMax] != txJson[jss::Amount])
227 txJson[jss::Amount] = txJson[jss::DeliverMax];
241 if (!txJson.
isMember(jss::Destination))
248 if (params.
isMember(jss::build_path) &&
263 if (txJson.
isMember(sfDomainID.jsonName))
266 if (!txJson[sfDomainID.jsonName].
isString() ||
289 [&](
Issue const&) { sendMax.
get<
Issue>().account = srcAddressID; },
326 JLOG(j.debug()) <<
"transactionSign: build_path: "
364 if (!txJson.
isMember(jss::TransactionType))
406 ret.
second = *srcAddressID;
410static std::expected<void, json::Value>
413 if (appNetworkId > 1024)
415 if (!txJson.
isMember(jss::NetworkID))
420 if (!txJson[jss::NetworkID].isIntegral() || txJson[jss::NetworkID].asUInt() != appNetworkId)
426 return std::expected<void, json::Value>();
457static TransactionPreProcessResult
476 bool const verify = !(params.
isMember(jss::offline) && params[jss::offline].asBool());
478 auto const signatureTarget =
480 if (params.
isMember(jss::signature_target))
488 auto const signatureTemplate = signatureTarget
491 auto const signatureRoleOpt =
495 if (!signatureRoleOpt || signatureTemplate ==
nullptr)
518 return std::move(txJsonResult);
533 JLOG(j.debug()) <<
"transactionSign: Failed to find source account "
534 <<
"in current ledger: " <<
toBase58(srcAddressID);
541 if (!txJson.
isMember(jss::Sequence))
543 bool const hasTicketSeq = txJson.
isMember(sfTicketSequence.jsonName);
544 if (!hasTicketSeq && !sle)
546 JLOG(j.debug()) <<
"transactionSign: Failed to find source account "
547 <<
"in current ledger: " <<
toBase58(srcAddressID);
554 if (!txJson.
isMember(jss::NetworkID))
557 if (networkId > 1024)
558 txJson[jss::NetworkID] =
to_string(networkId);
578 params, txJson, srcAddressID, role, app,
verify && signingArgs.
editFields());
587 if (txJson.
isMember(jss::TxnSignature))
611 if (txJson.
isMember(sfDelegate.jsonName))
614 auto const delegateJson = txJson[sfDelegate.jsonName];
615 auto const ptrDelegatedAddressID = delegateJson.
isString()
619 if (!ptrDelegatedAddressID)
625 auto delegatedAddressID = *ptrDelegatedAddressID;
647 if (!parsed.
object.has_value())
650 err[jss::error] = parsed.
error[jss::error];
651 err[jss::error_code] = parsed.
error[jss::error_code];
652 err[jss::error_message] = parsed.
error[jss::error_message];
665 if (!parsed.
object->isFieldPresent(*signatureTarget))
667 parsed.
object->setFieldObject(
668 *signatureTarget,
STObject{*signatureTemplate, *signatureTarget});
670 sigObject = &parsed.
object->peekFieldObject(*signatureTarget);
684 RpcInternal,
"Exception occurred constructing serialized transaction");
703 stTx->sign(pk, sk, *signatureRoleOpt, rules);
736 tpTrans->getSTransaction()->add(s);
758 if (!tpTransNew->getSTransaction()->isEquivalent(*tpTrans->getSTransaction()))
762 tpTrans = std::move(tpTransNew);
777 ret.
second = std::move(tpTrans);
790 jvResult[jss::hash] =
to_string(tpTrans->getID());
798 jvResult[jss::tx_json], tpTrans->getSTransaction()->getTxnType(), apiVersion);
800 jvResult[jss::tx_blob] =
strHex(tpTrans->getSTransaction()->getSerializer().peekData());
809 jvResult[jss::engine_result] = sToken;
810 jvResult[jss::engine_result_code] = tpTrans->getResult();
811 jvResult[jss::engine_result_message] = sHuman;
838 tx[jss::Sequence] =
"0";
841 if (!tx.
isMember(jss::SigningPubKey))
843 tx[jss::SigningPubKey] =
"";
846 if (!tx.
isMember(jss::TxnSignature))
848 tx[jss::TxnSignature] =
"";
853 if (!tx[jss::Signers].isArray())
860 for (
auto& signer : tx[jss::Signers])
862 if (!signer.isMember(jss::Signer) || !signer[jss::Signer].isObject())
864 if (!signer[jss::Signer].isMember(jss::SigningPubKey))
867 signer[jss::Signer][jss::SigningPubKey] =
"";
869 if (!signer[jss::Signer].isMember(jss::TxnSignature))
872 signer[jss::Signer][jss::TxnSignature] =
"";
878 if (!parsed.
object.has_value())
920 auto const baseFee = ledger->fees().base;
925 auto const limit =
mulDiv(feeDefault, mult, div);
932 ss <<
"Fee of " << fee <<
" exceeds the requested tx limit of " << *limit;
958 if (request.
isMember(jss::fee_mult_max))
960 if (request[jss::fee_mult_max].isInt())
962 mult = request[jss::fee_mult_max].
asInt();
976 if (request.
isMember(jss::fee_div_max))
978 if (request[jss::fee_div_max].isInt())
980 div = request[jss::fee_div_max].
asInt();
996 if (feeOrError.isMember(jss::error))
998 tx[jss::Fee] = std::move(feeOrError);
1010 unsigned apiVersion,
1022 JLOG(j.debug()) <<
"transactionSign: " << jvRequest;
1025 SigningForParams signForParams;
1026 TransactionPreProcessResult
const preprocResult = transactionPreProcessImpl(
1027 jvRequest, role, signForParams, validatedLedgerAge, app, ledger->rules());
1029 if (!preprocResult.second)
1030 return preprocResult.first;
1034 transactionConstructImpl(preprocResult.second, ledger->rules(), app);
1039 return transactionFormatResultImpl(txn.
second, apiVersion);
1048 unsigned apiVersion,
1059 JLOG(j.debug()) <<
"transactionSubmit: " << jvRequest;
1062 SigningForParams signForParams;
1063 TransactionPreProcessResult
const preprocResult = transactionPreProcessImpl(
1064 jvRequest, role, signForParams, validatedLedgerAge, app, ledger->rules());
1066 if (!preprocResult.second)
1067 return preprocResult.first;
1071 transactionConstructImpl(preprocResult.second, ledger->rules(), app);
1087 return transactionFormatResultImpl(txn.
second, apiVersion);
1096 if (!jvRequest.
isMember(jss::tx_json))
1099 json::Value const& txJson(jvRequest[jss::tx_json]);
1107 if (!txJson.
isMember(jss::Sequence))
1110 if (!txJson.
isMember(sfSigningPubKey.getJsonName()))
1116 if (!jvRequest.
isMember(jss::signature_target) &&
1120 RpcInvalidParams,
"When multi-signing 'tx_json.SigningPubKey' must be empty.");
1132 if (signers.empty())
1137 return (a[sfAccount] < b[sfAccount]);
1143 [](
STObject const& a,
STObject const& b) {
return (a[sfAccount] == b[sfAccount]); });
1145 if (dupIter != signers.
end())
1148 err <<
"Duplicate Signers:Signer:Account entries (" <<
toBase58((*dupIter)[sfAccount])
1149 <<
") are not allowed.";
1155 return elem[sfAccount] == signingForID;
1159 err <<
"A Signer may not be the transaction's Account (" <<
toBase58(signingForID) <<
").";
1173 unsigned apiVersion,
1181 JLOG(j.debug()) <<
"transactionSignFor: " << jvRequest;
1184 char const accountField[] =
"account";
1186 if (!jvRequest.
isMember(accountField))
1191 if (!signerAccountID)
1196 if (!jvRequest.
isMember(jss::tx_json))
1205 if (
auto checkResult =
1209 return std::move(checkResult).error();
1215 if (!txJson.
isMember(sfSigningPubKey.getJsonName()))
1216 txJson[sfSigningPubKey.getJsonName()] =
"";
1223 json::Value err = checkMultiSignFields(jvRequest);
1229 SigningForParams signForParams(*signerAccountID);
1231 TransactionPreProcessResult
const preprocResult = transactionPreProcessImpl(
1232 jvRequest, role, signForParams, validatedLedgerAge, app, ledger->rules());
1234 if (!preprocResult.second)
1235 return preprocResult.first;
1238 signForParams.validMultiSign(),
"xrpl::rpc::transactionSignFor : valid multi-signature");
1244 acctMatchesPubKey(accountState, *signerAccountID, signForParams.getPublicKey());
1251 auto& sttx = preprocResult.second;
1255 signer[sfAccount] = *signerAccountID;
1256 signer.
setFieldVL(sfTxnSignature, signForParams.getSignature());
1257 signer.
setFieldVL(sfSigningPubKey, signForParams.getPublicKey().slice());
1260 auto const target = signForParams.getSignatureTarget();
1262 return sttx->peekFieldObject(*target);
1270 signers.emplaceBack(std::move(signer));
1275 auto err = sortAndValidateSigners(signers, sttx->getInitiator());
1282 transactionConstructImpl(sttx, ledger->rules(), app);
1287 return transactionFormatResultImpl(txn.
second, apiVersion);
1296 unsigned apiVersion,
1305 JLOG(j.debug()) <<
"transactionSubmitMultiSigned: " << jvRequest;
1311 json::Value err = checkMultiSignFields(jvRequest);
1318 auto [txJsonResult, srcAddressID] = checkTxJsonFields(
1328 return std::move(txJsonResult);
1335 JLOG(j.debug()) <<
"transactionSubmitMultiSigned: Failed to find source account "
1336 <<
"in current ledger: " <<
toBase58(srcAddressID);
1348 err = checkPayment(jvRequest, txJson, srcAddressID, role, app,
false);
1358 if (!parsedTxJson.
object)
1361 jvResult[
"error"] = parsedTxJson.
error[
"error"];
1362 jvResult[
"error_code"] = parsedTxJson.
error[
"error_code"];
1363 jvResult[
"error_message"] = parsedTxJson.
error[
"error_message"];
1378 RpcInternal,
"Exception while serializing transaction: " + reason);
1391 if (!stTx->getFieldVL(sfSigningPubKey).empty())
1394 err <<
"Invalid " << sfSigningPubKey.fieldName
1395 <<
" field. Field must be empty when multi-signing.";
1400 if (stTx->isFieldPresent(sfTxnSignature))
1404 auto const fee = stTx->getFieldAmount(sfFee);
1409 err <<
"Invalid " << sfFee.fieldName <<
" field. Fees must be specified in XRP.";
1415 err <<
"Invalid " << sfFee.fieldName <<
" field. Fees must be greater than zero.";
1421 if (!stTx->isFieldPresent(sfSigners))
1426 auto& signers = stTx->peekFieldArray(sfSigners);
1428 if (signers.empty())
1438 }) != signers.
end())
1446 auto err = sortAndValidateSigners(signers, stTx->getInitiator());
1452 transactionConstructImpl(stTx, ledger->rules(), app);
1468 return transactionFormatResultImpl(txn.
second, apiVersion);
T adjacent_find(T... args)
Value removeMember(char const *key)
Remove and return the named member.
const_iterator end() const
std::string asString() const
Returns the unquoted string value.
bool isMember(char const *key) const
Return true if the object has a member named key.
virtual Config & config()=0
virtual bool checkSigs() const =0
constexpr auto visit(Visitors &&... visitors) const -> decltype(auto)
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Like std::vector<char> but better.
A currency issued by an account.
Manages the current fee schedule.
bool isLoadedCluster() const
virtual std::uint32_t getNetworkID() const noexcept=0
Get the configured network ID.
std::shared_ptr< OpenView const > current() const
Returns a view to the current open ledger.
Calculates payment paths.
STPathSet getBestPaths(int maxPaths, STPath &fullLiquidityPath, STPathSet const &extraPaths, AccountID const &srcIssuer, std::function< bool(void)> const &continueCallback={})
bool findPaths(int searchLevel, std::function< bool(void)> const &continueCallback={})
void computePathRanks(int maxPaths, std::function< bool(void)> const &continueCallback={})
Compute the rankings of the paths.
Slice slice() const noexcept
Rules controlling protocol behavior.
static SField const & getField(int fieldCode)
constexpr bool holds() const noexcept
constexpr TIss const & get() const
bool native() const noexcept
Asset const & asset() const
AccountID const & getIssuer() const
std::shared_ptr< STLedgerEntry const > const_pointer
void setFieldVL(SField const &field, Blob const &)
STArray & peekFieldArray(SField const &field)
void setFieldArray(SField const &field, STArray const &v)
bool isFieldPresent(SField const &field) const
static STObject makeInnerObject(SField const &name)
Holds the serialized result of parsing an input JSON object.
std::optional< STObject > object
The STObject if the parse was successful.
json::Value error
On failure, an appropriate set of error values.
json::Value getJson(JsonOptions) const override
static constexpr std::size_t kMaxMultiSigners
constexpr std::uint32_t value() const
Slice slice() const noexcept
virtual beast::Journal getJournal(std::string const &name)=0
virtual OpenLedger & getOpenLedger()=0
virtual NetworkIDService & getNetworkIDService()=0
virtual LoadFeeTrack & getFeeTrack()=0
virtual HashRouter & getHashRouter()=0
An immutable linear range of bytes.
std::shared_ptr< Transaction > pointer
Metrics getMetrics(OpenView const &view) const
Returns fee metrics in reference fee level units.
SeqProxy nextQueuableSeq(SLE::ConstRef sleAccount) const
Return the next sequence that would go in the TxQ for an account.
json::Value jsonClipped() const
std::optional< std::reference_wrapper< SField const > > const & getSignatureTarget() const
bool isSingleSigning() const
bool validMultiSign() const
SigningForParams(AccountID const &multiSigningAcctID)
PublicKey const & getPublicKey() const
SigningForParams(SigningForParams const &rhs)=delete
Buffer const & getSignature() const
void moveMultiSignature(Buffer &&multiSignature)
std::optional< std::reference_wrapper< SField const > > signatureTarget_
void setSignatureTarget(std::optional< std::reference_wrapper< SField const > > const &field)
AccountID const *const multiSigningAcctID_
std::optional< PublicKey > multiSignPublicKey_
void setPublicKey(PublicKey const &multiSignPublicKey)
bool isMultiSigning() const
AccountID const & getSigner() const
JSON (JavaScript Object Notation).
Keylet account(AccountID const &id) noexcept
AccountID root.
static std::pair< json::Value, AccountID > checkTxJsonFields(json::Value const &txJson, Role const role, bool const verify, std::chrono::seconds validatedLedgerAge, Config const &config, LoadFeeTrack const &feeTrack, unsigned apiVersion)
static ErrorCodeI acctMatchesPubKey(SLE::const_pointer accountState, AccountID const &accountID, PublicKey const &publicKey)
static json::Value transactionFormatResultImpl(Transaction::pointer tpTrans, unsigned apiVersion)
static std::pair< json::Value, Transaction::pointer > transactionConstructImpl(std::shared_ptr< STTx const > const &stTx, Rules const &rules, Application &app)
static std::expected< void, json::Value > checkNetworkID(json::Value const &txJson, uint32_t appNetworkId)
static json::Value checkMultiSignFields(json::Value const &jvRequest)
static TransactionPreProcessResult transactionPreProcessImpl(json::Value ¶ms, Role role, SigningForParams &signingArgs, std::chrono::seconds validatedLedgerAge, Application &app, Rules const &rules)
static json::Value checkPayment(json::Value const ¶ms, json::Value &txJson, AccountID const &srcAddressID, Role const role, Application &app, bool doPath)
static json::Value sortAndValidateSigners(STArray &signers, AccountID const &signingForID)
static constexpr int kDefaultAutoFillFeeMultiplier
static constexpr int kDefaultAutoFillFeeDivisor
constexpr auto kMaxValidatedLedgerAge
API version numbers used in later API versions.
bool containsError(json::Value const &json)
Returns true if the json contains an rpc error specification.
json::Value getCurrentNetworkFee(Role const role, Config const &config, LoadFeeTrack const &feeTrack, TxQ const &txQ, Application const &app, json::Value const &tx, int mult, int div)
json::Value transactionSubmit(json::Value jvRequest, unsigned apiVersion, NetworkOPs::FailHard failType, Role role, std::chrono::seconds validatedLedgerAge, Application &app, ProcessTransactionFn const &processTransaction)
Returns a json::ValueType::Object.
std::function< void( std::shared_ptr< Transaction > &transaction, bool bUnlimited, bool bLocal, NetworkOPs::FailHard failType)> ProcessTransactionFn
void insertDeliverMax(json::Value &txJson, TxType txnType, unsigned int apiVersion)
Copy Amount field to DeliverMax field in transaction output JSON.
static XRPAmount getTxFee(Application const &app, Config const &config, json::Value tx)
std::string invalidFieldMessage(std::string const &name)
json::Value makeParamError(std::string const &message)
Returns a new json object that indicates invalid parameters.
unsigned int getAPIVersionNumber(json::Value const &jv, bool betaEnabled)
Retrieve the api version number from the json value.
json::Value invalidFieldError(std::string const &name)
std::string expectedFieldMessage(std::string const &name, std::string const &type)
json::Value transactionSignFor(json::Value jvRequest, unsigned apiVersion, NetworkOPs::FailHard failType, Role role, std::chrono::seconds validatedLedgerAge, Application &app)
Returns a json::ValueType::Object.
std::string missingFieldMessage(std::string const &name)
json::Value transactionSubmitMultiSigned(json::Value jvRequest, unsigned apiVersion, NetworkOPs::FailHard failType, Role role, std::chrono::seconds validatedLedgerAge, Application &app, ProcessTransactionFn const &processTransaction)
Returns a json::ValueType::Object.
json::Value transactionSign(json::Value jvRequest, unsigned apiVersion, NetworkOPs::FailHard failType, Role role, std::chrono::seconds validatedLedgerAge, Application &app)
Returns a json::ValueType::Object.
json::Value missingFieldError(std::string const &name)
json::Value makeError(ErrorCodeI code)
Returns a new json object that reflects the error code.
json::Value objectFieldError(std::string const &name)
std::optional< std::pair< PublicKey, SecretKey > > keypairForSignature(json::Value const ¶ms, json::Value &error, unsigned int apiVersion)
Generates a keypair for signature from RPC parameters.
json::Value checkFee(json::Value &request, Role const role, bool doAutoFill, Config const &config, LoadFeeTrack const &feeTrack, TxQ const &txQ, Application const &app)
Fill in the fee on behalf of the client.
std::optional< SignatureRole > signatureRole(SField const &sigField)
The role that signs into the given field.
std::optional< std::uint64_t > mulDiv(std::uint64_t value, std::uint64_t mul, std::uint64_t div)
Return value*mul/div accurately.
std::expected< XRPAmount, TER > calculateBaseFee(ReadView const &view, STTx const &tx)
Compute only the expected base fee for a transaction.
@ Valid
Signature and local checks are good / passed.
@ SigGoodOnly
Signature is good, but local checks fail.
std::optional< AccountID > parseBase58(std::string const &s)
Parse AccountID from checked, base58 string.
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)
std::pair< Validity, std::string > checkValidity(HashRouter &router, STTx const &tx, Rules const &rules)
Checks transaction signature and local checks.
bool verify(PublicKey const &publicKey, Slice const &m, Slice const &sig) noexcept
Verify a signature on a message.
bool isLegalNet(STAmount const &value)
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
XRPAmount toDrops(FeeLevel< T > const &level, XRPAmount baseFee)
bool transResultInfo(TER code, std::string &token, std::string &text)
std::string to_string(BaseUInt< Bits, Tag > const &a)
void logicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
bool passesLocalChecks(STTx const &tx, std::string &)
Slice makeSlice(std::array< T, N > const &a)
void forceValidity(HashRouter &router, UInt256 const &txid, Validity validity)
Sets the validity of a given transaction in the cache.
json::Value rpcError(ErrorCodeI iError)
Role
Indicates the level of administrative permission to grant.
bool amountFromJsonNoThrow(STAmount &result, json::Value const &jvSource)
@ Transaction
The transaction's own signature, in sfTxnSignature or sfSigners.
FeeLevel< std::uint64_t > FeeLevel64
AccountID calcAccountID(PublicKey const &pk)
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
XRPAmount scaleFeeLoad(XRPAmount fee, LoadFeeTrack const &feeTrack, Fees const &fees, bool bUnlimited)
Buffer sign(PublicKey const &pk, SecretKey const &sk, Slice const &message)
Generate a signature for a message.
bool isUnlimited(Role const &role)
ADMIN and IDENTIFIED roles shall have unlimited resources.
std::vector< unsigned char > Blob
Storage for linear binary data.
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Serializer buildMultiSigningData(STObject const &obj, AccountID const &signingID, HashPrefix prefix)
Return a Serializer suitable for computing a multisigning TxnSignature.
XRPAmount referenceFee
The cost of a reference transaction in drops.
TransactionPreProcessResult & operator=(TransactionPreProcessResult const &)=delete
std::shared_ptr< STTx > const second
TransactionPreProcessResult(std::shared_ptr< STTx > &&st)
TransactionPreProcessResult(TransactionPreProcessResult const &)=delete
TransactionPreProcessResult()=delete
TransactionPreProcessResult & operator=(TransactionPreProcessResult &&)=delete
TransactionPreProcessResult(TransactionPreProcessResult &&rhs)=default
TransactionPreProcessResult(json::Value &&json)