diff --git a/src/consensus/tx_verify.cpp b/src/consensus/tx_verify.cpp index 14561a5156..a3a984ec62 100644 --- a/src/consensus/tx_verify.cpp +++ b/src/consensus/tx_verify.cpp @@ -162,7 +162,8 @@ int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& i CTxOut prevout; if (tx.vin[i].m_is_pegin) { std::string err; - if (tx.witness.vtxinwit.size() <= i || !IsValidPeginWitness(tx.witness.vtxinwit[i].m_pegin_witness, tx.vin[i].prevout, err, true)) { + // Make sure witness exists and is properly formatted + if (tx.witness.vtxinwit.size() != tx.vin.size() || !IsValidPeginWitness(tx.witness.vtxinwit[i].m_pegin_witness, tx.vin[i].prevout, err, false)) { continue; } prevout = GetPeginOutputFromWitness(tx.witness.vtxinwit[i].m_pegin_witness); diff --git a/src/validation.cpp b/src/validation.cpp index b0fd88fce9..52bedeead2 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -700,12 +700,11 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool // This only checks the UTXO set for already claimed pegins. For mempool conflicts, // we rely on the GetConflictTx check done above. if (txin.m_is_pegin) { - // Quick sanity check on witness first. - if (tx.witness.vtxinwit.size() <= i || - tx.witness.vtxinwit[i].m_pegin_witness.stack.size() < 6 || - uint256(tx.witness.vtxinwit[i].m_pegin_witness.stack[2]).IsNull() || - tx.vin[i].prevout.hash.IsNull()) { - return state.Invalid(false, REJECT_INVALID, "pegin-no-witness"); + // Peg-in witness is required, check here without validating existence in parent chain + std::string err_msg = "no peg-in witness attached"; + if (tx.witness.vtxinwit.size() != tx.vin.size() || + !IsValidPeginWitness(tx.witness.vtxinwit[i].m_pegin_witness, tx.vin[i].prevout, err_msg, false)) { + return state.Invalid(false, REJECT_INVALID, "pegin-no-witness", err_msg); } std::pair pegin = std::make_pair(uint256(tx.witness.vtxinwit[i].m_pegin_witness.stack[2]), tx.vin[i].prevout);