Skip to content

Commit f6fb7ac

Browse files
committed
Move CTxInWitness inside CTxIn
1 parent d04aeba commit f6fb7ac

18 files changed

+96
-176
lines changed

src/bench/verify_script.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ static CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, co
3636
txSpend.nLockTime = 0;
3737
txSpend.vin.resize(1);
3838
txSpend.vout.resize(1);
39-
txSpend.wit.vtxinwit.resize(1);
4039
txSpend.vin[0].prevout.hash = txCredit.GetHash();
4140
txSpend.vin[0].prevout.n = 0;
4241
txSpend.vin[0].scriptSig = scriptSig;
@@ -68,7 +67,7 @@ static void VerifyScriptBench(benchmark::State& state)
6867
CScript witScriptPubkey = CScript() << OP_DUP << OP_HASH160 << ToByteVector(pubkeyHash) << OP_EQUALVERIFY << OP_CHECKSIG;
6968
CTransaction txCredit = BuildCreditingTransaction(scriptPubKey);
7069
CMutableTransaction txSpend = BuildSpendingTransaction(scriptSig, txCredit);
71-
CScriptWitness& witness = txSpend.wit.vtxinwit[0].scriptWitness;
70+
CScriptWitness& witness = txSpend.vin[0].scriptWitness;
7271
witness.stack.emplace_back();
7372
key.Sign(SignatureHash(witScriptPubkey, txSpend, 0, SIGHASH_ALL, txCredit.vout[0].nValue, SIGVERSION_WITNESS_V0), witness.stack.back(), 0);
7473
witness.stack.back().push_back(static_cast<unsigned char>(SIGHASH_ALL));
@@ -80,7 +79,7 @@ static void VerifyScriptBench(benchmark::State& state)
8079
bool success = VerifyScript(
8180
txSpend.vin[0].scriptSig,
8281
txCredit.vout[0].scriptPubKey,
83-
&txSpend.wit.vtxinwit[0].scriptWitness,
82+
&txSpend.vin[0].scriptWitness,
8483
flags,
8584
MutableTransactionSignatureChecker(&txSpend, 0, txCredit.vout[0].nValue),
8685
&err);

src/bitcoin-tx.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr)
494494
sigdata = CombineSignatures(prevPubKey, MutableTransactionSignatureChecker(&mergedTx, i, amount), sigdata, DataFromTransaction(txv, i));
495495
UpdateTransaction(mergedTx, i, sigdata);
496496

497-
if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i, amount)))
497+
if (!VerifyScript(txin.scriptSig, prevPubKey, &txin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i, amount)))
498498
fComplete = false;
499499
}
500500

src/core_memusage.h

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,35 +18,19 @@ static inline size_t RecursiveDynamicUsage(const COutPoint& out) {
1818
}
1919

2020
static inline size_t RecursiveDynamicUsage(const CTxIn& in) {
21-
return RecursiveDynamicUsage(in.scriptSig) + RecursiveDynamicUsage(in.prevout);
22-
}
23-
24-
static inline size_t RecursiveDynamicUsage(const CTxOut& out) {
25-
return RecursiveDynamicUsage(out.scriptPubKey);
26-
}
27-
28-
static inline size_t RecursiveDynamicUsage(const CScriptWitness& scriptWit) {
29-
size_t mem = memusage::DynamicUsage(scriptWit.stack);
30-
for (std::vector<std::vector<unsigned char> >::const_iterator it = scriptWit.stack.begin(); it != scriptWit.stack.end(); it++) {
31-
mem += memusage::DynamicUsage(*it);
21+
size_t mem = RecursiveDynamicUsage(in.scriptSig) + RecursiveDynamicUsage(in.prevout) + memusage::DynamicUsage(in.scriptWitness.stack);
22+
for (std::vector<std::vector<unsigned char> >::const_iterator it = in.scriptWitness.stack.begin(); it != in.scriptWitness.stack.end(); it++) {
23+
mem += memusage::DynamicUsage(*it);
3224
}
3325
return mem;
3426
}
3527

36-
static inline size_t RecursiveDynamicUsage(const CTxInWitness& txinwit) {
37-
return RecursiveDynamicUsage(txinwit.scriptWitness);
38-
}
39-
40-
static inline size_t RecursiveDynamicUsage(const CTxWitness& txwit) {
41-
size_t mem = memusage::DynamicUsage(txwit.vtxinwit);
42-
for (std::vector<CTxInWitness>::const_iterator it = txwit.vtxinwit.begin(); it != txwit.vtxinwit.end(); it++) {
43-
mem += RecursiveDynamicUsage(*it);
44-
}
45-
return mem;
28+
static inline size_t RecursiveDynamicUsage(const CTxOut& out) {
29+
return RecursiveDynamicUsage(out.scriptPubKey);
4630
}
4731

4832
static inline size_t RecursiveDynamicUsage(const CTransaction& tx) {
49-
size_t mem = memusage::DynamicUsage(tx.vin) + memusage::DynamicUsage(tx.vout) + RecursiveDynamicUsage(tx.wit);
33+
size_t mem = memusage::DynamicUsage(tx.vin) + memusage::DynamicUsage(tx.vout);
5034
for (std::vector<CTxIn>::const_iterator it = tx.vin.begin(); it != tx.vin.end(); it++) {
5135
mem += RecursiveDynamicUsage(*it);
5236
}
@@ -57,7 +41,7 @@ static inline size_t RecursiveDynamicUsage(const CTransaction& tx) {
5741
}
5842

5943
static inline size_t RecursiveDynamicUsage(const CMutableTransaction& tx) {
60-
size_t mem = memusage::DynamicUsage(tx.vin) + memusage::DynamicUsage(tx.vout) + RecursiveDynamicUsage(tx.wit);
44+
size_t mem = memusage::DynamicUsage(tx.vin) + memusage::DynamicUsage(tx.vout);
6145
for (std::vector<CTxIn>::const_iterator it = tx.vin.begin(); it != tx.vin.end(); it++) {
6246
mem += RecursiveDynamicUsage(*it);
6347
}

src/core_write.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,9 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry)
168168
o.pushKV("asm", ScriptToAsmStr(txin.scriptSig, true));
169169
o.pushKV("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()));
170170
in.pushKV("scriptSig", o);
171-
if (!tx.wit.IsNull() && i < tx.wit.vtxinwit.size() && !tx.wit.vtxinwit[i].IsNull()) {
171+
if (!tx.vin[i].scriptWitness.IsNull()) {
172172
UniValue txinwitness(UniValue::VARR);
173-
for (const auto& item : tx.wit.vtxinwit[i].scriptWitness.stack) {
173+
for (const auto& item : tx.vin[i].scriptWitness.stack) {
174174
txinwitness.push_back(HexStr(item.begin(), item.end()));
175175
}
176176
in.pushKV("txinwitness", txinwitness);

src/miner.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ bool BlockAssembler::TestPackageTransactions(const CTxMemPool::setEntries& packa
245245
BOOST_FOREACH (const CTxMemPool::txiter it, package) {
246246
if (!IsFinalTx(it->GetTx(), nHeight, nLockTimeCutoff))
247247
return false;
248-
if (!fIncludeWitness && !it->GetTx().wit.IsNull())
248+
if (!fIncludeWitness && it->GetTx().HasWitness())
249249
return false;
250250
if (fNeedSizeAccounting) {
251251
uint64_t nTxSize = ::GetSerializeSize(it->GetTx(), SER_NETWORK, PROTOCOL_VERSION);
@@ -554,7 +554,7 @@ void BlockAssembler::addPriorityTxs()
554554
}
555555

556556
// cannot accept witness transactions into a non-witness block
557-
if (!fIncludeWitness && !iter->GetTx().wit.IsNull())
557+
if (!fIncludeWitness && iter->GetTx().HasWitness())
558558
continue;
559559

560560
// If tx is dependent on other mempool txs which haven't yet been included

src/net_processing.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1666,7 +1666,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
16661666
// Probably non-standard or insufficient fee/priority
16671667
LogPrint("mempool", " removed orphan tx %s\n", orphanHash.ToString());
16681668
vEraseQueue.push_back(orphanHash);
1669-
if (orphanTx.wit.IsNull() && !stateDummy.CorruptionPossible()) {
1669+
if (!orphanTx.HasWitness() && !stateDummy.CorruptionPossible()) {
16701670
// Do not use rejection cache for witness transactions or
16711671
// witness-stripped transactions, as they can have been malleated.
16721672
// See https://github.com/bitcoin/bitcoin/issues/8279 for details.
@@ -1708,7 +1708,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
17081708
LogPrint("mempool", "not keeping orphan with rejected parents %s\n",tx.GetHash().ToString());
17091709
}
17101710
} else {
1711-
if (tx.wit.IsNull() && !state.CorruptionPossible()) {
1711+
if (!tx.HasWitness() && !state.CorruptionPossible()) {
17121712
// Do not use rejection cache for witness transactions or
17131713
// witness-stripped transactions, as they can have been malleated.
17141714
// See https://github.com/bitcoin/bitcoin/issues/8279 for details.

src/policy/policy.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
163163
{
164164
// We don't care if witness for this input is empty, since it must not be bloated.
165165
// If the script is invalid without witness, it would be caught sooner or later during validation.
166-
if (tx.wit.vtxinwit[i].IsNull())
166+
if (tx.vin[i].scriptWitness.IsNull())
167167
continue;
168168

169169
const CTxOut &prev = mapInputs.GetOutputFor(tx.vin[i]);
@@ -192,13 +192,13 @@ bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
192192

193193
// Check P2WSH standard limits
194194
if (witnessversion == 0 && witnessprogram.size() == 32) {
195-
if (tx.wit.vtxinwit[i].scriptWitness.stack.back().size() > MAX_STANDARD_P2WSH_SCRIPT_SIZE)
195+
if (tx.vin[i].scriptWitness.stack.back().size() > MAX_STANDARD_P2WSH_SCRIPT_SIZE)
196196
return false;
197-
size_t sizeWitnessStack = tx.wit.vtxinwit[i].scriptWitness.stack.size() - 1;
197+
size_t sizeWitnessStack = tx.vin[i].scriptWitness.stack.size() - 1;
198198
if (sizeWitnessStack > MAX_STANDARD_P2WSH_STACK_ITEMS)
199199
return false;
200200
for (unsigned int j = 0; j < sizeWitnessStack; j++) {
201-
if (tx.wit.vtxinwit[i].scriptWitness.stack[j].size() > MAX_STANDARD_P2WSH_STACK_ITEM_SIZE)
201+
if (tx.vin[i].scriptWitness.stack[j].size() > MAX_STANDARD_P2WSH_STACK_ITEM_SIZE)
202202
return false;
203203
}
204204
}

src/primitives/transaction.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ std::string CTxOut::ToString() const
5555
}
5656

5757
CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nLockTime(0) {}
58-
CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), wit(tx.wit), nLockTime(tx.nLockTime) {}
58+
CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {}
5959

6060
uint256 CMutableTransaction::GetHash() const
6161
{
@@ -74,8 +74,8 @@ uint256 CTransaction::GetWitnessHash() const
7474

7575
/* For backward compatibility, the hash is initialized to 0. TODO: remove the need for this default constructor entirely. */
7676
CTransaction::CTransaction() : nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0), hash() {}
77-
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), wit(tx.wit), nLockTime(tx.nLockTime), hash(ComputeHash()) {}
78-
CTransaction::CTransaction(CMutableTransaction &&tx) : nVersion(tx.nVersion), vin(std::move(tx.vin)), vout(std::move(tx.vout)), wit(std::move(tx.wit)), nLockTime(tx.nLockTime), hash(ComputeHash()) {}
77+
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime), hash(ComputeHash()) {}
78+
CTransaction::CTransaction(CMutableTransaction &&tx) : nVersion(tx.nVersion), vin(std::move(tx.vin)), vout(std::move(tx.vout)), nLockTime(tx.nLockTime), hash(ComputeHash()) {}
7979

8080
CAmount CTransaction::GetValueOut() const
8181
{
@@ -131,8 +131,8 @@ std::string CTransaction::ToString() const
131131
nLockTime);
132132
for (unsigned int i = 0; i < vin.size(); i++)
133133
str += " " + vin[i].ToString() + "\n";
134-
for (unsigned int i = 0; i < wit.vtxinwit.size(); i++)
135-
str += " " + wit.vtxinwit[i].scriptWitness.ToString() + "\n";
134+
for (unsigned int i = 0; i < vin.size(); i++)
135+
str += " " + vin[i].scriptWitness.ToString() + "\n";
136136
for (unsigned int i = 0; i < vout.size(); i++)
137137
str += " " + vout[i].ToString() + "\n";
138138
return str;

src/primitives/transaction.h

Lines changed: 31 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ class CTxIn
6565
COutPoint prevout;
6666
CScript scriptSig;
6767
uint32_t nSequence;
68+
CScriptWitness scriptWitness; //! Only serialized through CTransaction
6869

6970
/* Setting nSequence to this value for every input in a transaction
7071
* disables nLockTime. */
@@ -211,62 +212,6 @@ class CTxOut
211212
std::string ToString() const;
212213
};
213214

214-
class CTxInWitness
215-
{
216-
public:
217-
CScriptWitness scriptWitness;
218-
219-
ADD_SERIALIZE_METHODS;
220-
221-
template <typename Stream, typename Operation>
222-
inline void SerializationOp(Stream& s, Operation ser_action)
223-
{
224-
READWRITE(scriptWitness.stack);
225-
}
226-
227-
bool IsNull() const { return scriptWitness.IsNull(); }
228-
229-
CTxInWitness() { }
230-
};
231-
232-
class CTxWitness
233-
{
234-
public:
235-
/** In case vtxinwit is missing, all entries are treated as if they were empty CTxInWitnesses */
236-
std::vector<CTxInWitness> vtxinwit;
237-
238-
ADD_SERIALIZE_METHODS;
239-
240-
bool IsEmpty() const { return vtxinwit.empty(); }
241-
242-
bool IsNull() const
243-
{
244-
for (size_t n = 0; n < vtxinwit.size(); n++) {
245-
if (!vtxinwit[n].IsNull()) {
246-
return false;
247-
}
248-
}
249-
return true;
250-
}
251-
252-
void SetNull()
253-
{
254-
vtxinwit.clear();
255-
}
256-
257-
template <typename Stream, typename Operation>
258-
inline void SerializationOp(Stream& s, Operation ser_action)
259-
{
260-
for (size_t n = 0; n < vtxinwit.size(); n++) {
261-
READWRITE(vtxinwit[n]);
262-
}
263-
if (IsNull()) {
264-
/* It's illegal to encode a witness when all vtxinwit entries are empty. */
265-
throw std::ios_base::failure("Superfluous witness record");
266-
}
267-
}
268-
};
269-
270215
struct CMutableTransaction;
271216

272217
/**
@@ -294,7 +239,6 @@ inline void UnserializeTransaction(TxType& tx, Stream& s) {
294239
unsigned char flags = 0;
295240
tx.vin.clear();
296241
tx.vout.clear();
297-
tx.wit.SetNull();
298242
/* Try to read the vin. In case the dummy is there, this will be read as an empty vector. */
299243
s >> tx.vin;
300244
if (tx.vin.size() == 0 && fAllowWitness) {
@@ -311,8 +255,9 @@ inline void UnserializeTransaction(TxType& tx, Stream& s) {
311255
if ((flags & 1) && fAllowWitness) {
312256
/* The witness flag is present, and we support witnesses. */
313257
flags ^= 1;
314-
tx.wit.vtxinwit.resize(tx.vin.size());
315-
s >> tx.wit;
258+
for (size_t i = 0; i < tx.vin.size(); i++) {
259+
s >> tx.vin[i].scriptWitness.stack;
260+
}
316261
}
317262
if (flags) {
318263
/* Unknown flag in the serialization */
@@ -328,10 +273,9 @@ inline void SerializeTransaction(const TxType& tx, Stream& s) {
328273
s << tx.nVersion;
329274
unsigned char flags = 0;
330275
// Consistency check
331-
assert(tx.wit.vtxinwit.size() <= tx.vin.size());
332276
if (fAllowWitness) {
333277
/* Check whether witnesses need to be serialized. */
334-
if (!tx.wit.IsNull()) {
278+
if (tx.HasWitness()) {
335279
flags |= 1;
336280
}
337281
}
@@ -345,11 +289,7 @@ inline void SerializeTransaction(const TxType& tx, Stream& s) {
345289
s << tx.vout;
346290
if (flags & 1) {
347291
for (size_t i = 0; i < tx.vin.size(); i++) {
348-
if (i < tx.wit.vtxinwit.size()) {
349-
s << tx.wit.vtxinwit[i];
350-
} else {
351-
s << CTxInWitness();
352-
}
292+
s << tx.vin[i].scriptWitness.stack;
353293
}
354294
}
355295
s << tx.nLockTime;
@@ -379,7 +319,6 @@ class CTransaction
379319
const int32_t nVersion;
380320
const std::vector<CTxIn> vin;
381321
const std::vector<CTxOut> vout;
382-
CTxWitness wit; // Not const: can change without invalidating the txid cache
383322
const uint32_t nLockTime;
384323

385324
private:
@@ -451,6 +390,16 @@ class CTransaction
451390
}
452391

453392
std::string ToString() const;
393+
394+
bool HasWitness() const
395+
{
396+
for (size_t i = 0; i < vin.size(); i++) {
397+
if (!vin[i].scriptWitness.IsNull()) {
398+
return true;
399+
}
400+
}
401+
return false;
402+
}
454403
};
455404

456405
/** A mutable version of CTransaction. */
@@ -459,7 +408,6 @@ struct CMutableTransaction
459408
int32_t nVersion;
460409
std::vector<CTxIn> vin;
461410
std::vector<CTxOut> vout;
462-
CTxWitness wit;
463411
uint32_t nLockTime;
464412

465413
CMutableTransaction();
@@ -485,6 +433,21 @@ struct CMutableTransaction
485433
* fly, as opposed to GetHash() in CTransaction, which uses a cached result.
486434
*/
487435
uint256 GetHash() const;
436+
437+
friend bool operator==(const CMutableTransaction& a, const CMutableTransaction& b)
438+
{
439+
return a.GetHash() == b.GetHash();
440+
}
441+
442+
bool HasWitness() const
443+
{
444+
for (size_t i = 0; i < vin.size(); i++) {
445+
if (!vin[i].scriptWitness.IsNull()) {
446+
return true;
447+
}
448+
}
449+
return false;
450+
}
488451
};
489452

490453
typedef std::shared_ptr<const CTransaction> CTransactionRef;

src/rpc/rawtransaction.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,16 +82,13 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
8282
o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
8383
in.push_back(Pair("scriptSig", o));
8484
}
85-
if (!tx.wit.IsNull()) {
86-
if (!tx.wit.vtxinwit[i].IsNull()) {
85+
if (tx.HasWitness()) {
8786
UniValue txinwitness(UniValue::VARR);
88-
for (unsigned int j = 0; j < tx.wit.vtxinwit[i].scriptWitness.stack.size(); j++) {
89-
std::vector<unsigned char> item = tx.wit.vtxinwit[i].scriptWitness.stack[j];
87+
for (unsigned int j = 0; j < tx.vin[i].scriptWitness.stack.size(); j++) {
88+
std::vector<unsigned char> item = tx.vin[i].scriptWitness.stack[j];
9089
txinwitness.push_back(HexStr(item.begin(), item.end()));
9190
}
9291
in.push_back(Pair("txinwitness", txinwitness));
93-
}
94-
9592
}
9693
in.push_back(Pair("sequence", (int64_t)txin.nSequence));
9794
vin.push_back(in);
@@ -840,7 +837,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request)
840837
UpdateTransaction(mergedTx, i, sigdata);
841838

842839
ScriptError serror = SCRIPT_ERR_OK;
843-
if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) {
840+
if (!VerifyScript(txin.scriptSig, prevPubKey, &txin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) {
844841
TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror));
845842
}
846843
}

0 commit comments

Comments
 (0)