mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Cache tid in STTx:
The digest for a transaction (its transaction ID, or tid) is computed once upon constructed when the STTx is deserialized. Subsequent calls to retrieve the digest use the cached value. Any code which modifies the STTx and then attempts to retrieve the digest will terminate the process with a logic error contract violation. * Nested types removed * All STTx are contained as const (Except in transaction sign, which must modify) * tid in STTx is computed once on deserialization
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
#include <ripple/protocol/TxFormats.h>
|
||||
#include <boost/container/flat_set.hpp>
|
||||
#include <boost/logic/tribool.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -42,9 +43,6 @@ class STTx final
|
||||
public:
|
||||
static char const* getCountedObjectName () { return "STTx"; }
|
||||
|
||||
using pointer = std::shared_ptr<STTx>;
|
||||
using ref = const std::shared_ptr<STTx>&;
|
||||
|
||||
static std::size_t const minMultiSigners = 1;
|
||||
static std::size_t const maxMultiSigners = 8;
|
||||
|
||||
@@ -134,11 +132,22 @@ private:
|
||||
bool checkSingleSign () const;
|
||||
bool checkMultiSign () const;
|
||||
|
||||
boost::optional<uint256> tid_;
|
||||
TxType tx_type_;
|
||||
};
|
||||
|
||||
bool passesLocalChecks (STObject const& st, std::string&);
|
||||
|
||||
/** Sterilize a transaction.
|
||||
|
||||
The transaction is serialized and then deserialized,
|
||||
ensuring that all equivalent transactions are in canonical
|
||||
form. This also ensures that program metadata such as
|
||||
the transaction's digest, are all computed.
|
||||
*/
|
||||
std::shared_ptr<STTx const>
|
||||
sterilize (STTx const& stx);
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <ripple/protocol/STArray.h>
|
||||
#include <ripple/protocol/TxFlags.h>
|
||||
#include <ripple/protocol/types.h>
|
||||
#include <ripple/basics/contract.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/basics/StringUtilities.h>
|
||||
#include <ripple/json/to_string.h>
|
||||
@@ -34,6 +35,7 @@
|
||||
#include <beast/cxx14/memory.h> // <memory>
|
||||
#include <boost/format.hpp>
|
||||
#include <array>
|
||||
#include <utility>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -74,6 +76,8 @@ STTx::STTx (STObject&& object)
|
||||
"Transaction not legal for format";
|
||||
throw std::runtime_error ("transaction not valid");
|
||||
}
|
||||
|
||||
tid_ = getHash(HashPrefix::transactionID);
|
||||
}
|
||||
|
||||
STTx::STTx (SerialIter& sit)
|
||||
@@ -106,6 +110,8 @@ STTx::STTx (SerialIter& sit)
|
||||
"Transaction not legal for format";
|
||||
throw std::runtime_error ("transaction not valid");
|
||||
}
|
||||
|
||||
tid_ = getHash(HashPrefix::transactionID);
|
||||
}
|
||||
|
||||
std::string
|
||||
@@ -161,7 +167,10 @@ STTx::getSigningHash () const
|
||||
uint256
|
||||
STTx::getTransactionID () const
|
||||
{
|
||||
return getHash (HashPrefix::transactionID);
|
||||
assert(tid_);
|
||||
if (! tid_)
|
||||
LogicError("digest is undefined");
|
||||
return *tid_;
|
||||
}
|
||||
|
||||
Blob STTx::getSignature () const
|
||||
@@ -180,6 +189,7 @@ void STTx::sign (RippleAddress const& private_key)
|
||||
{
|
||||
Blob const signature = private_key.accountPrivateSign (getSigningData (*this));
|
||||
setFieldVL (sfTxnSignature, signature);
|
||||
tid_ = getHash(HashPrefix::transactionID);
|
||||
}
|
||||
|
||||
bool STTx::checkSign(bool allowMultiSign) const
|
||||
@@ -499,4 +509,13 @@ bool passesLocalChecks (STObject const& st, std::string& reason)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<STTx const>
|
||||
sterilize (STTx const& stx)
|
||||
{
|
||||
Serializer s;
|
||||
stx.add(s);
|
||||
SerialIter sit(s.slice());
|
||||
return std::make_shared<STTx const>(std::ref(sit));
|
||||
}
|
||||
|
||||
} // ripple
|
||||
|
||||
Reference in New Issue
Block a user