Generic TransactionSignatureCreator works with both CTransaction and CMutableTransaction
Templated version so that no copying of CMutableTransaction into a CTransaction is necessary. This speeds up the test case transaction_tests/test_big_witness_transaction from 7.9 seconds to 3.1 seconds on my machine.
This commit is contained in:
parent
d792e47421
commit
6b8b63af14
5 changed files with 55 additions and 46 deletions
src/script
|
@ -1089,9 +1089,11 @@ namespace {
|
|||
* Wrapper that serializes like CTransaction, but with the modifications
|
||||
* required for the signature hash done in-place
|
||||
*/
|
||||
class CTransactionSignatureSerializer {
|
||||
template <class T>
|
||||
class CTransactionSignatureSerializer
|
||||
{
|
||||
private:
|
||||
const CTransaction& txTo; //!< reference to the spending transaction (the one being serialized)
|
||||
const T& txTo; //!< reference to the spending transaction (the one being serialized)
|
||||
const CScript& scriptCode; //!< output script being consumed
|
||||
const unsigned int nIn; //!< input index of txTo being signed
|
||||
const bool fAnyoneCanPay; //!< whether the hashtype has the SIGHASH_ANYONECANPAY flag set
|
||||
|
@ -1099,7 +1101,7 @@ private:
|
|||
const bool fHashNone; //!< whether the hashtype is SIGHASH_NONE
|
||||
|
||||
public:
|
||||
CTransactionSignatureSerializer(const CTransaction &txToIn, const CScript &scriptCodeIn, unsigned int nInIn, int nHashTypeIn) :
|
||||
CTransactionSignatureSerializer(const T& txToIn, const CScript& scriptCodeIn, unsigned int nInIn, int nHashTypeIn) :
|
||||
txTo(txToIn), scriptCode(scriptCodeIn), nIn(nInIn),
|
||||
fAnyoneCanPay(!!(nHashTypeIn & SIGHASH_ANYONECANPAY)),
|
||||
fHashSingle((nHashTypeIn & 0x1f) == SIGHASH_SINGLE),
|
||||
|
@ -1180,7 +1182,9 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
uint256 GetPrevoutHash(const CTransaction& txTo) {
|
||||
template <class T>
|
||||
uint256 GetPrevoutHash(const T& txTo)
|
||||
{
|
||||
CHashWriter ss(SER_GETHASH, 0);
|
||||
for (const auto& txin : txTo.vin) {
|
||||
ss << txin.prevout;
|
||||
|
@ -1188,7 +1192,9 @@ uint256 GetPrevoutHash(const CTransaction& txTo) {
|
|||
return ss.GetHash();
|
||||
}
|
||||
|
||||
uint256 GetSequenceHash(const CTransaction& txTo) {
|
||||
template <class T>
|
||||
uint256 GetSequenceHash(const T& txTo)
|
||||
{
|
||||
CHashWriter ss(SER_GETHASH, 0);
|
||||
for (const auto& txin : txTo.vin) {
|
||||
ss << txin.nSequence;
|
||||
|
@ -1196,7 +1202,9 @@ uint256 GetSequenceHash(const CTransaction& txTo) {
|
|||
return ss.GetHash();
|
||||
}
|
||||
|
||||
uint256 GetOutputsHash(const CTransaction& txTo) {
|
||||
template <class T>
|
||||
uint256 GetOutputsHash(const T& txTo)
|
||||
{
|
||||
CHashWriter ss(SER_GETHASH, 0);
|
||||
for (const auto& txout : txTo.vout) {
|
||||
ss << txout;
|
||||
|
@ -1206,7 +1214,8 @@ uint256 GetOutputsHash(const CTransaction& txTo) {
|
|||
|
||||
} // namespace
|
||||
|
||||
PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo)
|
||||
template <class T>
|
||||
PrecomputedTransactionData::PrecomputedTransactionData(const T& txTo)
|
||||
{
|
||||
// Cache is calculated only for transactions with witness
|
||||
if (txTo.HasWitness()) {
|
||||
|
@ -1217,7 +1226,12 @@ PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo)
|
|||
}
|
||||
}
|
||||
|
||||
uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache)
|
||||
// explicit instantiation
|
||||
template PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo);
|
||||
template PrecomputedTransactionData::PrecomputedTransactionData(const CMutableTransaction& txTo);
|
||||
|
||||
template <class T>
|
||||
uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache)
|
||||
{
|
||||
assert(nIn < txTo.vin.size());
|
||||
|
||||
|
@ -1278,7 +1292,7 @@ uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsig
|
|||
}
|
||||
|
||||
// Wrapper to serialize only the necessary parts of the transaction being signed
|
||||
CTransactionSignatureSerializer txTmp(txTo, scriptCode, nIn, nHashType);
|
||||
CTransactionSignatureSerializer<T> txTmp(txTo, scriptCode, nIn, nHashType);
|
||||
|
||||
// Serialize and hash
|
||||
CHashWriter ss(SER_GETHASH, 0);
|
||||
|
@ -1286,12 +1300,14 @@ uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsig
|
|||
return ss.GetHash();
|
||||
}
|
||||
|
||||
bool TransactionSignatureChecker::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
|
||||
template <class T>
|
||||
bool GenericTransactionSignatureChecker<T>::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
|
||||
{
|
||||
return pubkey.Verify(sighash, vchSig);
|
||||
}
|
||||
|
||||
bool TransactionSignatureChecker::CheckSig(const std::vector<unsigned char>& vchSigIn, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
|
||||
template <class T>
|
||||
bool GenericTransactionSignatureChecker<T>::CheckSig(const std::vector<unsigned char>& vchSigIn, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
|
||||
{
|
||||
CPubKey pubkey(vchPubKey);
|
||||
if (!pubkey.IsValid())
|
||||
|
@ -1312,7 +1328,8 @@ bool TransactionSignatureChecker::CheckSig(const std::vector<unsigned char>& vch
|
|||
return true;
|
||||
}
|
||||
|
||||
bool TransactionSignatureChecker::CheckLockTime(const CScriptNum& nLockTime) const
|
||||
template <class T>
|
||||
bool GenericTransactionSignatureChecker<T>::CheckLockTime(const CScriptNum& nLockTime) const
|
||||
{
|
||||
// There are two kinds of nLockTime: lock-by-blockheight
|
||||
// and lock-by-blocktime, distinguished by whether
|
||||
|
@ -1348,7 +1365,8 @@ bool TransactionSignatureChecker::CheckLockTime(const CScriptNum& nLockTime) con
|
|||
return true;
|
||||
}
|
||||
|
||||
bool TransactionSignatureChecker::CheckSequence(const CScriptNum& nSequence) const
|
||||
template <class T>
|
||||
bool GenericTransactionSignatureChecker<T>::CheckSequence(const CScriptNum& nSequence) const
|
||||
{
|
||||
// Relative lock times are supported by comparing the passed
|
||||
// in operand to the sequence number of the input.
|
||||
|
@ -1394,6 +1412,10 @@ bool TransactionSignatureChecker::CheckSequence(const CScriptNum& nSequence) con
|
|||
return true;
|
||||
}
|
||||
|
||||
// explicit instantiation
|
||||
template class GenericTransactionSignatureChecker<CTransaction>;
|
||||
template class GenericTransactionSignatureChecker<CMutableTransaction>;
|
||||
|
||||
static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion, const std::vector<unsigned char>& program, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
|
||||
{
|
||||
std::vector<std::vector<unsigned char> > stack;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue