Skip to content

Commit 9f5e40d

Browse files
committed
Move CTxInWitness inside CTxIn
1 parent 232529f commit 9f5e40d

File tree

14 files changed

+93
-160
lines changed

14 files changed

+93
-160
lines changed

src/bitcoin-tx.cpp

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

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

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/main.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,7 +1041,7 @@ int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& i
10411041
for (unsigned int i = 0; i < tx.vin.size(); i++)
10421042
{
10431043
const CTxOut &prevout = inputs.GetOutputFor(tx.vin[i]);
1044-
nSigOps += CountWitnessSigOps(tx.vin[i].scriptSig, prevout.scriptPubKey, i < tx.wit.vtxinwit.size() ? &tx.wit.vtxinwit[i].scriptWitness : NULL, flags);
1044+
nSigOps += CountWitnessSigOps(tx.vin[i].scriptSig, prevout.scriptPubKey, &tx.vin[i].scriptWitness, flags);
10451045
}
10461046
return nSigOps;
10471047
}
@@ -1144,7 +1144,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
11441144

11451145
// Reject transactions with witness before segregated witness activates (override with -prematurewitness)
11461146
bool witnessEnabled = IsWitnessEnabled(chainActive.Tip(), Params().GetConsensus());
1147-
if (!GetBoolArg("-prematurewitness",false) && !tx.wit.IsNull() && !witnessEnabled) {
1147+
if (!GetBoolArg("-prematurewitness",false) && tx.HasWitness() && !witnessEnabled) {
11481148
return state.DoS(0, false, REJECT_NONSTANDARD, "no-witness-yet", true);
11491149
}
11501150

@@ -1914,7 +1914,7 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight)
19141914

19151915
bool CScriptCheck::operator()() {
19161916
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
1917-
const CScriptWitness *witness = (nIn < ptxTo->wit.vtxinwit.size()) ? &ptxTo->wit.vtxinwit[nIn].scriptWitness : NULL;
1917+
const CScriptWitness *witness = &ptxTo->vin[nIn].scriptWitness;
19181918
if (!VerifyScript(scriptSig, scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore), &error)) {
19191919
return false;
19201920
}
@@ -3460,10 +3460,9 @@ void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPr
34603460
{
34613461
int commitpos = GetWitnessCommitmentIndex(block);
34623462
static const std::vector<unsigned char> nonce(32, 0x00);
3463-
if (commitpos != -1 && IsWitnessEnabled(pindexPrev, consensusParams) && block.vtx[0].wit.IsEmpty()) {
3464-
block.vtx[0].wit.vtxinwit.resize(1);
3465-
block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.resize(1);
3466-
block.vtx[0].wit.vtxinwit[0].scriptWitness.stack[0] = nonce;
3463+
if (commitpos != -1 && IsWitnessEnabled(pindexPrev, consensusParams) && !block.vtx[0].HasWitness()) {
3464+
block.vtx[0].vin[0].scriptWitness.stack.resize(1);
3465+
block.vtx[0].vin[0].scriptWitness.stack[0] = nonce;
34673466
}
34683467
}
34693468

@@ -3473,7 +3472,7 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc
34733472
int commitpos = GetWitnessCommitmentIndex(block);
34743473
bool fHaveWitness = false;
34753474
for (size_t t = 1; t < block.vtx.size(); t++) {
3476-
if (!block.vtx[t].wit.IsNull()) {
3475+
if (block.vtx[t].HasWitness()) {
34773476
fHaveWitness = true;
34783477
break;
34793478
}
@@ -3574,10 +3573,10 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Co
35743573
// The malleation check is ignored; as the transaction tree itself
35753574
// already does not permit it, it is impossible to trigger in the
35763575
// witness tree.
3577-
if (block.vtx[0].wit.vtxinwit.size() != 1 || block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.size() != 1 || block.vtx[0].wit.vtxinwit[0].scriptWitness.stack[0].size() != 32) {
3576+
if (block.vtx[0].vin[0].scriptWitness.stack.size() != 1 || block.vtx[0].vin[0].scriptWitness.stack[0].size() != 32) {
35783577
return state.DoS(100, false, REJECT_INVALID, "bad-witness-nonce-size", true, strprintf("%s : invalid witness nonce size", __func__));
35793578
}
3580-
CHash256().Write(hashWitness.begin(), 32).Write(&block.vtx[0].wit.vtxinwit[0].scriptWitness.stack[0][0], 32).Finalize(hashWitness.begin());
3579+
CHash256().Write(hashWitness.begin(), 32).Write(&block.vtx[0].vin[0].scriptWitness.stack[0][0], 32).Finalize(hashWitness.begin());
35813580
if (memcmp(hashWitness.begin(), &block.vtx[0].vout[commitpos].scriptPubKey[6], 32)) {
35823581
return state.DoS(100, false, REJECT_INVALID, "bad-witness-merkle-match", true, strprintf("%s : witness merkle commitment mismatch", __func__));
35833582
}
@@ -3588,7 +3587,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Co
35883587
// No witness data is allowed in blocks that don't commit to witness data, as this would otherwise leave room for spam
35893588
if (!fHaveWitness) {
35903589
for (size_t i = 0; i < block.vtx.size(); i++) {
3591-
if (!block.vtx[i].wit.IsNull()) {
3590+
if (block.vtx[i].HasWitness()) {
35923591
return state.DoS(100, false, REJECT_INVALID, "unexpected-witness", true, strprintf("%s : unexpected witness data found", __func__));
35933592
}
35943593
}

src/miner.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ bool BlockAssembler::TestPackageTransactions(const CTxMemPool::setEntries& packa
242242
BOOST_FOREACH (const CTxMemPool::txiter it, package) {
243243
if (!IsFinalTx(it->GetTx(), nHeight, nLockTimeCutoff))
244244
return false;
245-
if (!fIncludeWitness && !it->GetTx().wit.IsNull())
245+
if (!fIncludeWitness && it->GetTx().HasWitness())
246246
return false;
247247
if (fNeedSizeAccounting) {
248248
uint64_t nTxSize = ::GetSerializeSize(it->GetTx(), SER_NETWORK, PROTOCOL_VERSION);
@@ -551,7 +551,7 @@ void BlockAssembler::addPriorityTxs()
551551
}
552552

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

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

src/primitives/transaction.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ std::string CTxOut::ToString() const
6060
}
6161

6262
CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nLockTime(0) {}
63-
CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), wit(tx.wit), nLockTime(tx.nLockTime) {}
63+
CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {}
6464

6565
uint256 CMutableTransaction::GetHash() const
6666
{
@@ -79,15 +79,14 @@ uint256 CTransaction::GetWitnessHash() const
7979

8080
CTransaction::CTransaction() : nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0) { }
8181

82-
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), wit(tx.wit), nLockTime(tx.nLockTime) {
82+
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {
8383
UpdateHash();
8484
}
8585

8686
CTransaction& CTransaction::operator=(const CTransaction &tx) {
8787
nVersion = tx.nVersion;
8888
vin = tx.vin;
8989
vout = tx.vout;
90-
wit = tx.wit;
9190
nLockTime = tx.nLockTime;
9291
hash = tx.hash;
9392
return *this;
@@ -142,8 +141,8 @@ std::string CTransaction::ToString() const
142141
nLockTime);
143142
for (unsigned int i = 0; i < vin.size(); i++)
144143
str += " " + vin[i].ToString() + "\n";
145-
for (unsigned int i = 0; i < wit.vtxinwit.size(); i++)
146-
str += " " + wit.vtxinwit[i].scriptWitness.ToString() + "\n";
144+
for (unsigned int i = 0; i < vin.size(); i++)
145+
str += " " + vin[i].scriptWitness.ToString() + "\n";
147146
for (unsigned int i = 0; i < vout.size(); i++)
148147
str += " " + vout[i].ToString() + "\n";
149148
return str;

src/primitives/transaction.h

Lines changed: 41 additions & 65 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 CTxInWitnessSerializer
6869

6970
/* Setting nSequence to this value for every input in a transaction
7071
* disables nLockTime. */
@@ -125,6 +126,33 @@ class CTxIn
125126
std::string ToString() const;
126127
};
127128

129+
class CTxInsWitnessSerializer
130+
{
131+
private:
132+
std::vector<CTxIn>* ptr;
133+
134+
public:
135+
CTxInsWitnessSerializer(std::vector<CTxIn>* txin) : ptr(txin) {}
136+
137+
ADD_SERIALIZE_METHODS;
138+
139+
template <typename Stream, typename Operation>
140+
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
141+
for (unsigned int i = 0; i < ptr->size(); i++) {
142+
READWRITE((*ptr)[i].scriptWitness.stack);
143+
}
144+
}
145+
146+
bool IsNull() {
147+
for (unsigned int i = 0; i < ptr->size(); i++) {
148+
if (!(*ptr)[i].scriptWitness.IsNull()) {
149+
return false;
150+
}
151+
}
152+
return true;
153+
}
154+
};
155+
128156
/** An output of a transaction. It contains the public key that the next input
129157
* must be able to sign with to claim it.
130158
*/
@@ -213,62 +241,6 @@ class CTxOut
213241
std::string ToString() const;
214242
};
215243

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

274246
/**
@@ -297,7 +269,6 @@ inline void SerializeTransaction(TxType& tx, Stream& s, Operation ser_action, in
297269
if (ser_action.ForRead()) {
298270
tx.vin.clear();
299271
tx.vout.clear();
300-
tx.wit.SetNull();
301272
/* Try to read the vin. In case the dummy is there, this will be read as an empty vector. */
302273
READWRITE(tx.vin);
303274
if (tx.vin.size() == 0 && fAllowWitness) {
@@ -314,19 +285,22 @@ inline void SerializeTransaction(TxType& tx, Stream& s, Operation ser_action, in
314285
if ((flags & 1) && fAllowWitness) {
315286
/* The witness flag is present, and we support witnesses. */
316287
flags ^= 1;
317-
tx.wit.vtxinwit.resize(tx.vin.size());
318-
READWRITE(tx.wit);
288+
CTxInsWitnessSerializer ser(&tx.vin);
289+
READWRITE(ser);
290+
if (ser.IsNull()) {
291+
/* It's illegal to encode a witness when all vtxinwit entries are empty. */
292+
throw std::ios_base::failure("Superfluous witness record");
293+
}
319294
}
320295
if (flags) {
321296
/* Unknown flag in the serialization */
322297
throw std::ios_base::failure("Unknown transaction optional data");
323298
}
324299
} else {
325300
// Consistency check
326-
assert(tx.wit.vtxinwit.size() <= tx.vin.size());
327301
if (fAllowWitness) {
328302
/* Check whether witnesses need to be serialized. */
329-
if (!tx.wit.IsNull()) {
303+
if (tx.HasWitness()) {
330304
flags |= 1;
331305
}
332306
}
@@ -339,8 +313,8 @@ inline void SerializeTransaction(TxType& tx, Stream& s, Operation ser_action, in
339313
READWRITE(tx.vin);
340314
READWRITE(tx.vout);
341315
if (flags & 1) {
342-
tx.wit.vtxinwit.resize(tx.vin.size());
343-
READWRITE(tx.wit);
316+
CTxInsWitnessSerializer ser(&tx.vin);
317+
READWRITE(ser);
344318
}
345319
}
346320
READWRITE(tx.nLockTime);
@@ -376,7 +350,6 @@ class CTransaction
376350
int32_t nVersion;
377351
std::vector<CTxIn> vin;
378352
std::vector<CTxOut> vout;
379-
CTxWitness wit;
380353
uint32_t nLockTime;
381354

382355
/** Construct a CTransaction that qualifies as IsNull() */
@@ -437,6 +410,8 @@ class CTransaction
437410
std::string ToString() const;
438411

439412
void UpdateHash();
413+
414+
bool HasWitness() const { return !CTxInsWitnessSerializer(const_cast<std::vector<CTxIn>*>(&vin)).IsNull(); }
440415
};
441416

442417
/** A mutable version of CTransaction. */
@@ -445,7 +420,6 @@ struct CMutableTransaction
445420
int32_t nVersion;
446421
std::vector<CTxIn> vin;
447422
std::vector<CTxOut> vout;
448-
CTxWitness wit;
449423
uint32_t nLockTime;
450424

451425
CMutableTransaction();
@@ -462,6 +436,8 @@ struct CMutableTransaction
462436
* fly, as opposed to GetHash() in CTransaction, which uses a cached result.
463437
*/
464438
uint256 GetHash() const;
439+
440+
bool HasWitness() const { return !CTxInsWitnessSerializer(const_cast<std::vector<CTxIn>*>(&vin)).IsNull(); }
465441
};
466442

467443
/** Compute the weight of a transaction, as defined by BIP 141 */

0 commit comments

Comments
 (0)