1414#include < util/check.h>
1515#include < util/moneystr.h>
1616
17+ #include < span>
18+
1719bool IsFinalTx (const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
1820{
1921 if (tx.nLockTime == 0 )
@@ -123,62 +125,73 @@ unsigned int GetLegacySigOpCount(const CTransaction& tx)
123125 return nSigOps;
124126}
125127
126- unsigned int GetP2SHSigOpCount (const CTransaction& tx, const CCoinsViewCache& inputs)
128+ template <Consensus::CoinRef T>
129+ unsigned int GetP2SHSigOpCount (const CTransaction& tx, const std::span<T> coins)
127130{
128131 if (tx.IsCoinBase ())
129132 return 0 ;
130133
131134 unsigned int nSigOps = 0 ;
132- for (unsigned int i = 0 ; i < tx.vin .size (); i++)
133- {
134- const Coin& coin = inputs.AccessCoin (tx.vin [i].prevout );
135+ Assert (coins.size () == tx.vin .size ());
136+ auto input_it = tx.vin .begin ();
137+ for (auto it = coins.begin (); it != coins.end (); ++it, ++input_it) {
138+ const Coin& coin = *it;
135139 assert (!coin.IsSpent ());
136140 const CTxOut &prevout = coin.out ;
137141 if (prevout.scriptPubKey .IsPayToScriptHash ())
138- nSigOps += prevout.scriptPubKey .GetSigOpCount (tx. vin [i]. scriptSig );
142+ nSigOps += prevout.scriptPubKey .GetSigOpCount (input_it-> scriptSig );
139143 }
140144 return nSigOps;
141145}
142146
143- int64_t GetTransactionSigOpCost (const CTransaction& tx, const CCoinsViewCache& inputs, script_verify_flags flags)
147+ template unsigned int GetP2SHSigOpCount<const Coin>(
148+ const CTransaction& tx, const std::span<const Coin>);
149+
150+ template unsigned int GetP2SHSigOpCount<std::reference_wrapper<const Coin>>(
151+ const CTransaction& tx, const std::span<std::reference_wrapper<const Coin>>);
152+
153+ template <Consensus::CoinRef T>
154+ int64_t GetTransactionSigOpCost (const CTransaction& tx, const std::span<T> coins, script_verify_flags flags)
144155{
145156 int64_t nSigOps = GetLegacySigOpCount (tx) * WITNESS_SCALE_FACTOR;
146157
147158 if (tx.IsCoinBase ())
148159 return nSigOps;
149160
150161 if (flags & SCRIPT_VERIFY_P2SH) {
151- nSigOps += GetP2SHSigOpCount (tx, inputs ) * WITNESS_SCALE_FACTOR;
162+ nSigOps += GetP2SHSigOpCount (tx, coins ) * WITNESS_SCALE_FACTOR;
152163 }
153164
154- for (unsigned int i = 0 ; i < tx.vin .size (); i++)
155- {
156- const Coin& coin = inputs.AccessCoin (tx.vin [i].prevout );
165+ Assert (coins.size () == tx.vin .size ());
166+ auto input_it = tx.vin .begin ();
167+ for (auto it = coins.begin (); it != coins.end (); ++it, ++input_it) {
168+ const Coin& coin = *it;
157169 assert (!coin.IsSpent ());
158170 const CTxOut &prevout = coin.out ;
159- nSigOps += CountWitnessSigOps (tx. vin [i]. scriptSig , prevout.scriptPubKey , &tx. vin [i]. scriptWitness , flags);
171+ nSigOps += CountWitnessSigOps (input_it-> scriptSig , prevout.scriptPubKey , &input_it-> scriptWitness , flags);
160172 }
161173 return nSigOps;
162174}
175+ template int64_t GetTransactionSigOpCost<const Coin>(
176+ const CTransaction& tx, std::span<const Coin> coins, script_verify_flags flags);
163177
164- bool Consensus::CheckTxInputs (const CTransaction& tx, TxValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& txfee)
165- {
166- // are the actual inputs available?
167- if (!inputs.HaveInputs (tx)) {
168- return state.Invalid (TxValidationResult::TX_MISSING_INPUTS, " bad-txns-inputs-missingorspent" ,
169- strprintf (" %s: inputs missing/spent" , __func__));
170- }
178+ template int64_t GetTransactionSigOpCost<std::reference_wrapper<const Coin>>(
179+ const CTransaction& tx, const std::span<std::reference_wrapper<const Coin>> coins, script_verify_flags flags);
171180
181+ template <Consensus::CoinRef T>
182+ bool Consensus::CheckTxInputs (const CTransaction& tx, TxValidationState& state, const std::span<T> coins, int nSpendHeight, CAmount& txfee)
183+ {
172184 CAmount nValueIn = 0 ;
173- for (unsigned int i = 0 ; i < tx.vin .size (); ++i) {
174- const COutPoint &prevout = tx.vin [i].prevout ;
175- const Coin& coin = inputs.AccessCoin (prevout);
185+ Assert (coins.size () == tx.vin .size ());
186+ auto input_it = tx.vin .begin ();
187+ for (auto it = coins.begin (); it != coins.end (); ++it, ++input_it) {
188+ const Coin& coin = *it;
176189 assert (!coin.IsSpent ());
177190
178191 // If prev is coinbase, check that it's matured
179192 if (coin.IsCoinBase () && nSpendHeight - coin.nHeight < COINBASE_MATURITY) {
180193 return state.Invalid (TxValidationResult::TX_PREMATURE_SPEND, " bad-txns-premature-spend-of-coinbase" ,
181- strprintf (" tried to spend coinbase at depth %d" , nSpendHeight - coin.nHeight ));
194+ strprintf (" tried to spend coinbase at depth %d" , static_cast < int >( nSpendHeight - coin.nHeight ) ));
182195 }
183196
184197 // Check for negative or overflow input values
@@ -203,3 +216,9 @@ bool Consensus::CheckTxInputs(const CTransaction& tx, TxValidationState& state,
203216 txfee = txfee_aux;
204217 return true ;
205218}
219+
220+ template bool Consensus::CheckTxInputs<const Coin>(
221+ const CTransaction& tx, TxValidationState& state, const std::span<const Coin> coins, int nSpendHeight, CAmount& txfee);
222+
223+ template bool Consensus::CheckTxInputs<std::reference_wrapper<const Coin>>(
224+ const CTransaction& tx, TxValidationState& state, const std::span<std::reference_wrapper<const Coin>> coins, int nSpendHeight, CAmount& txfee);
0 commit comments