Move CTxInWitness inside CTxIn
This commit is contained in:
parent
d04aebaec7
commit
f6fb7acda4
18 changed files with 96 additions and 176 deletions
|
@ -36,7 +36,6 @@ static CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, co
|
|||
txSpend.nLockTime = 0;
|
||||
txSpend.vin.resize(1);
|
||||
txSpend.vout.resize(1);
|
||||
txSpend.wit.vtxinwit.resize(1);
|
||||
txSpend.vin[0].prevout.hash = txCredit.GetHash();
|
||||
txSpend.vin[0].prevout.n = 0;
|
||||
txSpend.vin[0].scriptSig = scriptSig;
|
||||
|
@ -68,7 +67,7 @@ static void VerifyScriptBench(benchmark::State& state)
|
|||
CScript witScriptPubkey = CScript() << OP_DUP << OP_HASH160 << ToByteVector(pubkeyHash) << OP_EQUALVERIFY << OP_CHECKSIG;
|
||||
CTransaction txCredit = BuildCreditingTransaction(scriptPubKey);
|
||||
CMutableTransaction txSpend = BuildSpendingTransaction(scriptSig, txCredit);
|
||||
CScriptWitness& witness = txSpend.wit.vtxinwit[0].scriptWitness;
|
||||
CScriptWitness& witness = txSpend.vin[0].scriptWitness;
|
||||
witness.stack.emplace_back();
|
||||
key.Sign(SignatureHash(witScriptPubkey, txSpend, 0, SIGHASH_ALL, txCredit.vout[0].nValue, SIGVERSION_WITNESS_V0), witness.stack.back(), 0);
|
||||
witness.stack.back().push_back(static_cast<unsigned char>(SIGHASH_ALL));
|
||||
|
@ -80,7 +79,7 @@ static void VerifyScriptBench(benchmark::State& state)
|
|||
bool success = VerifyScript(
|
||||
txSpend.vin[0].scriptSig,
|
||||
txCredit.vout[0].scriptPubKey,
|
||||
&txSpend.wit.vtxinwit[0].scriptWitness,
|
||||
&txSpend.vin[0].scriptWitness,
|
||||
flags,
|
||||
MutableTransactionSignatureChecker(&txSpend, 0, txCredit.vout[0].nValue),
|
||||
&err);
|
||||
|
|
|
@ -494,7 +494,7 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr)
|
|||
sigdata = CombineSignatures(prevPubKey, MutableTransactionSignatureChecker(&mergedTx, i, amount), sigdata, DataFromTransaction(txv, i));
|
||||
UpdateTransaction(mergedTx, i, sigdata);
|
||||
|
||||
if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i, amount)))
|
||||
if (!VerifyScript(txin.scriptSig, prevPubKey, &txin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i, amount)))
|
||||
fComplete = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,35 +18,19 @@ static inline size_t RecursiveDynamicUsage(const COutPoint& out) {
|
|||
}
|
||||
|
||||
static inline size_t RecursiveDynamicUsage(const CTxIn& in) {
|
||||
return RecursiveDynamicUsage(in.scriptSig) + RecursiveDynamicUsage(in.prevout);
|
||||
size_t mem = RecursiveDynamicUsage(in.scriptSig) + RecursiveDynamicUsage(in.prevout) + memusage::DynamicUsage(in.scriptWitness.stack);
|
||||
for (std::vector<std::vector<unsigned char> >::const_iterator it = in.scriptWitness.stack.begin(); it != in.scriptWitness.stack.end(); it++) {
|
||||
mem += memusage::DynamicUsage(*it);
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
|
||||
static inline size_t RecursiveDynamicUsage(const CTxOut& out) {
|
||||
return RecursiveDynamicUsage(out.scriptPubKey);
|
||||
}
|
||||
|
||||
static inline size_t RecursiveDynamicUsage(const CScriptWitness& scriptWit) {
|
||||
size_t mem = memusage::DynamicUsage(scriptWit.stack);
|
||||
for (std::vector<std::vector<unsigned char> >::const_iterator it = scriptWit.stack.begin(); it != scriptWit.stack.end(); it++) {
|
||||
mem += memusage::DynamicUsage(*it);
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
|
||||
static inline size_t RecursiveDynamicUsage(const CTxInWitness& txinwit) {
|
||||
return RecursiveDynamicUsage(txinwit.scriptWitness);
|
||||
}
|
||||
|
||||
static inline size_t RecursiveDynamicUsage(const CTxWitness& txwit) {
|
||||
size_t mem = memusage::DynamicUsage(txwit.vtxinwit);
|
||||
for (std::vector<CTxInWitness>::const_iterator it = txwit.vtxinwit.begin(); it != txwit.vtxinwit.end(); it++) {
|
||||
mem += RecursiveDynamicUsage(*it);
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
|
||||
static inline size_t RecursiveDynamicUsage(const CTransaction& tx) {
|
||||
size_t mem = memusage::DynamicUsage(tx.vin) + memusage::DynamicUsage(tx.vout) + RecursiveDynamicUsage(tx.wit);
|
||||
size_t mem = memusage::DynamicUsage(tx.vin) + memusage::DynamicUsage(tx.vout);
|
||||
for (std::vector<CTxIn>::const_iterator it = tx.vin.begin(); it != tx.vin.end(); it++) {
|
||||
mem += RecursiveDynamicUsage(*it);
|
||||
}
|
||||
|
@ -57,7 +41,7 @@ static inline size_t RecursiveDynamicUsage(const CTransaction& tx) {
|
|||
}
|
||||
|
||||
static inline size_t RecursiveDynamicUsage(const CMutableTransaction& tx) {
|
||||
size_t mem = memusage::DynamicUsage(tx.vin) + memusage::DynamicUsage(tx.vout) + RecursiveDynamicUsage(tx.wit);
|
||||
size_t mem = memusage::DynamicUsage(tx.vin) + memusage::DynamicUsage(tx.vout);
|
||||
for (std::vector<CTxIn>::const_iterator it = tx.vin.begin(); it != tx.vin.end(); it++) {
|
||||
mem += RecursiveDynamicUsage(*it);
|
||||
}
|
||||
|
|
|
@ -168,9 +168,9 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry)
|
|||
o.pushKV("asm", ScriptToAsmStr(txin.scriptSig, true));
|
||||
o.pushKV("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()));
|
||||
in.pushKV("scriptSig", o);
|
||||
if (!tx.wit.IsNull() && i < tx.wit.vtxinwit.size() && !tx.wit.vtxinwit[i].IsNull()) {
|
||||
if (!tx.vin[i].scriptWitness.IsNull()) {
|
||||
UniValue txinwitness(UniValue::VARR);
|
||||
for (const auto& item : tx.wit.vtxinwit[i].scriptWitness.stack) {
|
||||
for (const auto& item : tx.vin[i].scriptWitness.stack) {
|
||||
txinwitness.push_back(HexStr(item.begin(), item.end()));
|
||||
}
|
||||
in.pushKV("txinwitness", txinwitness);
|
||||
|
|
|
@ -245,7 +245,7 @@ bool BlockAssembler::TestPackageTransactions(const CTxMemPool::setEntries& packa
|
|||
BOOST_FOREACH (const CTxMemPool::txiter it, package) {
|
||||
if (!IsFinalTx(it->GetTx(), nHeight, nLockTimeCutoff))
|
||||
return false;
|
||||
if (!fIncludeWitness && !it->GetTx().wit.IsNull())
|
||||
if (!fIncludeWitness && it->GetTx().HasWitness())
|
||||
return false;
|
||||
if (fNeedSizeAccounting) {
|
||||
uint64_t nTxSize = ::GetSerializeSize(it->GetTx(), SER_NETWORK, PROTOCOL_VERSION);
|
||||
|
@ -554,7 +554,7 @@ void BlockAssembler::addPriorityTxs()
|
|||
}
|
||||
|
||||
// cannot accept witness transactions into a non-witness block
|
||||
if (!fIncludeWitness && !iter->GetTx().wit.IsNull())
|
||||
if (!fIncludeWitness && iter->GetTx().HasWitness())
|
||||
continue;
|
||||
|
||||
// If tx is dependent on other mempool txs which haven't yet been included
|
||||
|
|
|
@ -1666,7 +1666,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||
// Probably non-standard or insufficient fee/priority
|
||||
LogPrint("mempool", " removed orphan tx %s\n", orphanHash.ToString());
|
||||
vEraseQueue.push_back(orphanHash);
|
||||
if (orphanTx.wit.IsNull() && !stateDummy.CorruptionPossible()) {
|
||||
if (!orphanTx.HasWitness() && !stateDummy.CorruptionPossible()) {
|
||||
// Do not use rejection cache for witness transactions or
|
||||
// witness-stripped transactions, as they can have been malleated.
|
||||
// See https://github.com/bitcoin/bitcoin/issues/8279 for details.
|
||||
|
@ -1708,7 +1708,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||
LogPrint("mempool", "not keeping orphan with rejected parents %s\n",tx.GetHash().ToString());
|
||||
}
|
||||
} else {
|
||||
if (tx.wit.IsNull() && !state.CorruptionPossible()) {
|
||||
if (!tx.HasWitness() && !state.CorruptionPossible()) {
|
||||
// Do not use rejection cache for witness transactions or
|
||||
// witness-stripped transactions, as they can have been malleated.
|
||||
// See https://github.com/bitcoin/bitcoin/issues/8279 for details.
|
||||
|
|
|
@ -163,7 +163,7 @@ bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
|
|||
{
|
||||
// We don't care if witness for this input is empty, since it must not be bloated.
|
||||
// If the script is invalid without witness, it would be caught sooner or later during validation.
|
||||
if (tx.wit.vtxinwit[i].IsNull())
|
||||
if (tx.vin[i].scriptWitness.IsNull())
|
||||
continue;
|
||||
|
||||
const CTxOut &prev = mapInputs.GetOutputFor(tx.vin[i]);
|
||||
|
@ -192,13 +192,13 @@ bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
|
|||
|
||||
// Check P2WSH standard limits
|
||||
if (witnessversion == 0 && witnessprogram.size() == 32) {
|
||||
if (tx.wit.vtxinwit[i].scriptWitness.stack.back().size() > MAX_STANDARD_P2WSH_SCRIPT_SIZE)
|
||||
if (tx.vin[i].scriptWitness.stack.back().size() > MAX_STANDARD_P2WSH_SCRIPT_SIZE)
|
||||
return false;
|
||||
size_t sizeWitnessStack = tx.wit.vtxinwit[i].scriptWitness.stack.size() - 1;
|
||||
size_t sizeWitnessStack = tx.vin[i].scriptWitness.stack.size() - 1;
|
||||
if (sizeWitnessStack > MAX_STANDARD_P2WSH_STACK_ITEMS)
|
||||
return false;
|
||||
for (unsigned int j = 0; j < sizeWitnessStack; j++) {
|
||||
if (tx.wit.vtxinwit[i].scriptWitness.stack[j].size() > MAX_STANDARD_P2WSH_STACK_ITEM_SIZE)
|
||||
if (tx.vin[i].scriptWitness.stack[j].size() > MAX_STANDARD_P2WSH_STACK_ITEM_SIZE)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ std::string CTxOut::ToString() const
|
|||
}
|
||||
|
||||
CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nLockTime(0) {}
|
||||
CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), wit(tx.wit), nLockTime(tx.nLockTime) {}
|
||||
CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {}
|
||||
|
||||
uint256 CMutableTransaction::GetHash() const
|
||||
{
|
||||
|
@ -74,8 +74,8 @@ uint256 CTransaction::GetWitnessHash() const
|
|||
|
||||
/* For backward compatibility, the hash is initialized to 0. TODO: remove the need for this default constructor entirely. */
|
||||
CTransaction::CTransaction() : nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0), hash() {}
|
||||
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), wit(tx.wit), nLockTime(tx.nLockTime), hash(ComputeHash()) {}
|
||||
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()) {}
|
||||
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime), hash(ComputeHash()) {}
|
||||
CTransaction::CTransaction(CMutableTransaction &&tx) : nVersion(tx.nVersion), vin(std::move(tx.vin)), vout(std::move(tx.vout)), nLockTime(tx.nLockTime), hash(ComputeHash()) {}
|
||||
|
||||
CAmount CTransaction::GetValueOut() const
|
||||
{
|
||||
|
@ -131,8 +131,8 @@ std::string CTransaction::ToString() const
|
|||
nLockTime);
|
||||
for (unsigned int i = 0; i < vin.size(); i++)
|
||||
str += " " + vin[i].ToString() + "\n";
|
||||
for (unsigned int i = 0; i < wit.vtxinwit.size(); i++)
|
||||
str += " " + wit.vtxinwit[i].scriptWitness.ToString() + "\n";
|
||||
for (unsigned int i = 0; i < vin.size(); i++)
|
||||
str += " " + vin[i].scriptWitness.ToString() + "\n";
|
||||
for (unsigned int i = 0; i < vout.size(); i++)
|
||||
str += " " + vout[i].ToString() + "\n";
|
||||
return str;
|
||||
|
|
|
@ -65,6 +65,7 @@ public:
|
|||
COutPoint prevout;
|
||||
CScript scriptSig;
|
||||
uint32_t nSequence;
|
||||
CScriptWitness scriptWitness; //! Only serialized through CTransaction
|
||||
|
||||
/* Setting nSequence to this value for every input in a transaction
|
||||
* disables nLockTime. */
|
||||
|
@ -211,62 +212,6 @@ public:
|
|||
std::string ToString() const;
|
||||
};
|
||||
|
||||
class CTxInWitness
|
||||
{
|
||||
public:
|
||||
CScriptWitness scriptWitness;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action)
|
||||
{
|
||||
READWRITE(scriptWitness.stack);
|
||||
}
|
||||
|
||||
bool IsNull() const { return scriptWitness.IsNull(); }
|
||||
|
||||
CTxInWitness() { }
|
||||
};
|
||||
|
||||
class CTxWitness
|
||||
{
|
||||
public:
|
||||
/** In case vtxinwit is missing, all entries are treated as if they were empty CTxInWitnesses */
|
||||
std::vector<CTxInWitness> vtxinwit;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
bool IsEmpty() const { return vtxinwit.empty(); }
|
||||
|
||||
bool IsNull() const
|
||||
{
|
||||
for (size_t n = 0; n < vtxinwit.size(); n++) {
|
||||
if (!vtxinwit[n].IsNull()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetNull()
|
||||
{
|
||||
vtxinwit.clear();
|
||||
}
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action)
|
||||
{
|
||||
for (size_t n = 0; n < vtxinwit.size(); n++) {
|
||||
READWRITE(vtxinwit[n]);
|
||||
}
|
||||
if (IsNull()) {
|
||||
/* It's illegal to encode a witness when all vtxinwit entries are empty. */
|
||||
throw std::ios_base::failure("Superfluous witness record");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct CMutableTransaction;
|
||||
|
||||
/**
|
||||
|
@ -294,7 +239,6 @@ inline void UnserializeTransaction(TxType& tx, Stream& s) {
|
|||
unsigned char flags = 0;
|
||||
tx.vin.clear();
|
||||
tx.vout.clear();
|
||||
tx.wit.SetNull();
|
||||
/* Try to read the vin. In case the dummy is there, this will be read as an empty vector. */
|
||||
s >> tx.vin;
|
||||
if (tx.vin.size() == 0 && fAllowWitness) {
|
||||
|
@ -311,8 +255,9 @@ inline void UnserializeTransaction(TxType& tx, Stream& s) {
|
|||
if ((flags & 1) && fAllowWitness) {
|
||||
/* The witness flag is present, and we support witnesses. */
|
||||
flags ^= 1;
|
||||
tx.wit.vtxinwit.resize(tx.vin.size());
|
||||
s >> tx.wit;
|
||||
for (size_t i = 0; i < tx.vin.size(); i++) {
|
||||
s >> tx.vin[i].scriptWitness.stack;
|
||||
}
|
||||
}
|
||||
if (flags) {
|
||||
/* Unknown flag in the serialization */
|
||||
|
@ -328,10 +273,9 @@ inline void SerializeTransaction(const TxType& tx, Stream& s) {
|
|||
s << tx.nVersion;
|
||||
unsigned char flags = 0;
|
||||
// Consistency check
|
||||
assert(tx.wit.vtxinwit.size() <= tx.vin.size());
|
||||
if (fAllowWitness) {
|
||||
/* Check whether witnesses need to be serialized. */
|
||||
if (!tx.wit.IsNull()) {
|
||||
if (tx.HasWitness()) {
|
||||
flags |= 1;
|
||||
}
|
||||
}
|
||||
|
@ -345,11 +289,7 @@ inline void SerializeTransaction(const TxType& tx, Stream& s) {
|
|||
s << tx.vout;
|
||||
if (flags & 1) {
|
||||
for (size_t i = 0; i < tx.vin.size(); i++) {
|
||||
if (i < tx.wit.vtxinwit.size()) {
|
||||
s << tx.wit.vtxinwit[i];
|
||||
} else {
|
||||
s << CTxInWitness();
|
||||
}
|
||||
s << tx.vin[i].scriptWitness.stack;
|
||||
}
|
||||
}
|
||||
s << tx.nLockTime;
|
||||
|
@ -379,7 +319,6 @@ public:
|
|||
const int32_t nVersion;
|
||||
const std::vector<CTxIn> vin;
|
||||
const std::vector<CTxOut> vout;
|
||||
CTxWitness wit; // Not const: can change without invalidating the txid cache
|
||||
const uint32_t nLockTime;
|
||||
|
||||
private:
|
||||
|
@ -451,6 +390,16 @@ public:
|
|||
}
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
bool HasWitness() const
|
||||
{
|
||||
for (size_t i = 0; i < vin.size(); i++) {
|
||||
if (!vin[i].scriptWitness.IsNull()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/** A mutable version of CTransaction. */
|
||||
|
@ -459,7 +408,6 @@ struct CMutableTransaction
|
|||
int32_t nVersion;
|
||||
std::vector<CTxIn> vin;
|
||||
std::vector<CTxOut> vout;
|
||||
CTxWitness wit;
|
||||
uint32_t nLockTime;
|
||||
|
||||
CMutableTransaction();
|
||||
|
@ -485,6 +433,21 @@ struct CMutableTransaction
|
|||
* fly, as opposed to GetHash() in CTransaction, which uses a cached result.
|
||||
*/
|
||||
uint256 GetHash() const;
|
||||
|
||||
friend bool operator==(const CMutableTransaction& a, const CMutableTransaction& b)
|
||||
{
|
||||
return a.GetHash() == b.GetHash();
|
||||
}
|
||||
|
||||
bool HasWitness() const
|
||||
{
|
||||
for (size_t i = 0; i < vin.size(); i++) {
|
||||
if (!vin[i].scriptWitness.IsNull()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<const CTransaction> CTransactionRef;
|
||||
|
|
|
@ -82,17 +82,14 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
|
|||
o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
|
||||
in.push_back(Pair("scriptSig", o));
|
||||
}
|
||||
if (!tx.wit.IsNull()) {
|
||||
if (!tx.wit.vtxinwit[i].IsNull()) {
|
||||
if (tx.HasWitness()) {
|
||||
UniValue txinwitness(UniValue::VARR);
|
||||
for (unsigned int j = 0; j < tx.wit.vtxinwit[i].scriptWitness.stack.size(); j++) {
|
||||
std::vector<unsigned char> item = tx.wit.vtxinwit[i].scriptWitness.stack[j];
|
||||
for (unsigned int j = 0; j < tx.vin[i].scriptWitness.stack.size(); j++) {
|
||||
std::vector<unsigned char> item = tx.vin[i].scriptWitness.stack[j];
|
||||
txinwitness.push_back(HexStr(item.begin(), item.end()));
|
||||
}
|
||||
in.push_back(Pair("txinwitness", txinwitness));
|
||||
}
|
||||
|
||||
}
|
||||
in.push_back(Pair("sequence", (int64_t)txin.nSequence));
|
||||
vin.push_back(in);
|
||||
}
|
||||
|
@ -840,7 +837,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request)
|
|||
UpdateTransaction(mergedTx, i, sigdata);
|
||||
|
||||
ScriptError serror = SCRIPT_ERR_OK;
|
||||
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)) {
|
||||
if (!VerifyScript(txin.scriptSig, prevPubKey, &txin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) {
|
||||
TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,8 +93,9 @@ static int verify_script(const unsigned char *scriptPubKey, unsigned int scriptP
|
|||
|
||||
// Regardless of the verification result, the tx did not error.
|
||||
set_error(err, bitcoinconsensus_ERR_OK);
|
||||
|
||||
PrecomputedTransactionData txdata(tx);
|
||||
return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), nIn < tx.wit.vtxinwit.size() ? &tx.wit.vtxinwit[nIn].scriptWitness : NULL, flags, TransactionSignatureChecker(&tx, nIn, amount, txdata), NULL);
|
||||
return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), &tx.vin[nIn].scriptWitness, flags, TransactionSignatureChecker(&tx, nIn, amount, txdata), NULL);
|
||||
} catch (const std::exception&) {
|
||||
return set_error(err, bitcoinconsensus_ERR_TX_DESERIALIZE); // Error deserializing
|
||||
}
|
||||
|
|
|
@ -656,6 +656,8 @@ struct CScriptWitness
|
|||
|
||||
bool IsNull() const { return stack.empty(); }
|
||||
|
||||
void SetNull() { stack.clear(); stack.shrink_to_fit(); }
|
||||
|
||||
std::string ToString() const;
|
||||
};
|
||||
|
||||
|
|
|
@ -194,9 +194,7 @@ SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nI
|
|||
SignatureData data;
|
||||
assert(tx.vin.size() > nIn);
|
||||
data.scriptSig = tx.vin[nIn].scriptSig;
|
||||
if (tx.wit.vtxinwit.size() > nIn) {
|
||||
data.scriptWitness = tx.wit.vtxinwit[nIn].scriptWitness;
|
||||
}
|
||||
data.scriptWitness = tx.vin[nIn].scriptWitness;
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -204,10 +202,7 @@ void UpdateTransaction(CMutableTransaction& tx, unsigned int nIn, const Signatur
|
|||
{
|
||||
assert(tx.vin.size() > nIn);
|
||||
tx.vin[nIn].scriptSig = data.scriptSig;
|
||||
if (!data.scriptWitness.IsNull() || tx.wit.vtxinwit.size() > nIn) {
|
||||
tx.wit.vtxinwit.resize(tx.vin.size());
|
||||
tx.wit.vtxinwit[nIn].scriptWitness = data.scriptWitness;
|
||||
}
|
||||
tx.vin[nIn].scriptWitness = data.scriptWitness;
|
||||
}
|
||||
|
||||
bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType)
|
||||
|
|
|
@ -145,8 +145,7 @@ CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CSc
|
|||
txSpend.nLockTime = 0;
|
||||
txSpend.vin.resize(1);
|
||||
txSpend.vout.resize(1);
|
||||
txSpend.wit.vtxinwit.resize(1);
|
||||
txSpend.wit.vtxinwit[0].scriptWitness = scriptWitness;
|
||||
txSpend.vin[0].scriptWitness = scriptWitness;
|
||||
txSpend.vin[0].prevout.hash = txCredit.GetHash();
|
||||
txSpend.vin[0].prevout.n = 0;
|
||||
txSpend.vin[0].scriptSig = scriptSig;
|
||||
|
|
|
@ -73,7 +73,7 @@ ScriptError VerifyWithFlag(const CTransaction& output, const CMutableTransaction
|
|||
{
|
||||
ScriptError error;
|
||||
CTransaction inputi(input);
|
||||
bool ret = VerifyScript(inputi.vin[0].scriptSig, output.vout[0].scriptPubKey, inputi.wit.vtxinwit.size() > 0 ? &inputi.wit.vtxinwit[0].scriptWitness : NULL, flags, TransactionSignatureChecker(&inputi, 0, output.vout[0].nValue), &error);
|
||||
bool ret = VerifyScript(inputi.vin[0].scriptSig, output.vout[0].scriptPubKey, &inputi.vin[0].scriptWitness, flags, TransactionSignatureChecker(&inputi, 0, output.vout[0].nValue), &error);
|
||||
BOOST_CHECK((ret == true) == (error == SCRIPT_ERR_OK));
|
||||
|
||||
return error;
|
||||
|
@ -84,13 +84,12 @@ ScriptError VerifyWithFlag(const CTransaction& output, const CMutableTransaction
|
|||
* and witness such that spendingTx spends output zero of creationTx.
|
||||
* Also inserts creationTx's output into the coins view.
|
||||
*/
|
||||
void BuildTxs(CMutableTransaction& spendingTx, CCoinsViewCache& coins, CMutableTransaction& creationTx, const CScript& scriptPubKey, const CScript& scriptSig, const CTxInWitness& witness)
|
||||
void BuildTxs(CMutableTransaction& spendingTx, CCoinsViewCache& coins, CMutableTransaction& creationTx, const CScript& scriptPubKey, const CScript& scriptSig, const CScriptWitness& witness)
|
||||
{
|
||||
creationTx.nVersion = 1;
|
||||
creationTx.vin.resize(1);
|
||||
creationTx.vin[0].prevout.SetNull();
|
||||
creationTx.vin[0].scriptSig = CScript();
|
||||
creationTx.wit.vtxinwit.resize(1);
|
||||
creationTx.vout.resize(1);
|
||||
creationTx.vout[0].nValue = 1;
|
||||
creationTx.vout[0].scriptPubKey = scriptPubKey;
|
||||
|
@ -100,8 +99,7 @@ void BuildTxs(CMutableTransaction& spendingTx, CCoinsViewCache& coins, CMutableT
|
|||
spendingTx.vin[0].prevout.hash = creationTx.GetHash();
|
||||
spendingTx.vin[0].prevout.n = 0;
|
||||
spendingTx.vin[0].scriptSig = scriptSig;
|
||||
spendingTx.wit.vtxinwit.resize(1);
|
||||
spendingTx.wit.vtxinwit[0] = witness;
|
||||
spendingTx.vin[0].scriptWitness = witness;
|
||||
spendingTx.vout.resize(1);
|
||||
spendingTx.vout[0].nValue = 1;
|
||||
spendingTx.vout[0].scriptPubKey = CScript();
|
||||
|
@ -133,7 +131,7 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
|
|||
// Do not use a valid signature to avoid using wallet operations.
|
||||
CScript scriptSig = CScript() << OP_0 << OP_0;
|
||||
|
||||
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, CTxInWitness());
|
||||
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, CScriptWitness());
|
||||
// Legacy counting only includes signature operations in scriptSigs and scriptPubKeys
|
||||
// of a transaction and does not take the actual executed sig operations into account.
|
||||
// spendingTx in itself does not contain a signature operation.
|
||||
|
@ -151,7 +149,7 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
|
|||
CScript scriptPubKey = GetScriptForDestination(CScriptID(redeemScript));
|
||||
CScript scriptSig = CScript() << OP_0 << OP_0 << ToByteVector(redeemScript);
|
||||
|
||||
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, CTxInWitness());
|
||||
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, CScriptWitness());
|
||||
assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 2 * WITNESS_SCALE_FACTOR);
|
||||
assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY);
|
||||
}
|
||||
|
@ -161,14 +159,12 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
|
|||
CScript p2pk = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
|
||||
CScript scriptPubKey = GetScriptForWitness(p2pk);
|
||||
CScript scriptSig = CScript();
|
||||
CTxInWitness witness;
|
||||
CScriptWitness scriptWitness;
|
||||
scriptWitness.stack.push_back(vector<unsigned char>(0));
|
||||
scriptWitness.stack.push_back(vector<unsigned char>(0));
|
||||
witness.scriptWitness = scriptWitness;
|
||||
|
||||
|
||||
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, witness);
|
||||
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness);
|
||||
assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 1);
|
||||
// No signature operations if we don't verify the witness.
|
||||
assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags & ~SCRIPT_VERIFY_WITNESS) == 0);
|
||||
|
@ -177,10 +173,10 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
|
|||
// The sig op cost for witness version != 0 is zero.
|
||||
assert(scriptPubKey[0] == 0x00);
|
||||
scriptPubKey[0] = 0x51;
|
||||
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, witness);
|
||||
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness);
|
||||
assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 0);
|
||||
scriptPubKey[0] = 0x00;
|
||||
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, witness);
|
||||
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness);
|
||||
|
||||
// The witness of a coinbase transaction is not taken into account.
|
||||
spendingTx.vin[0].prevout.SetNull();
|
||||
|
@ -193,13 +189,11 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
|
|||
CScript scriptSig = GetScriptForWitness(p2pk);
|
||||
CScript scriptPubKey = GetScriptForDestination(CScriptID(scriptSig));
|
||||
scriptSig = CScript() << ToByteVector(scriptSig);
|
||||
CTxInWitness witness;
|
||||
CScriptWitness scriptWitness;
|
||||
scriptWitness.stack.push_back(vector<unsigned char>(0));
|
||||
scriptWitness.stack.push_back(vector<unsigned char>(0));
|
||||
witness.scriptWitness = scriptWitness;
|
||||
|
||||
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, witness);
|
||||
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness);
|
||||
assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 1);
|
||||
assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_EQUALVERIFY);
|
||||
}
|
||||
|
@ -209,14 +203,12 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
|
|||
CScript witnessScript = CScript() << 1 << ToByteVector(pubkey) << ToByteVector(pubkey) << 2 << OP_CHECKMULTISIGVERIFY;
|
||||
CScript scriptPubKey = GetScriptForWitness(witnessScript);
|
||||
CScript scriptSig = CScript();
|
||||
CTxInWitness witness;
|
||||
CScriptWitness scriptWitness;
|
||||
scriptWitness.stack.push_back(vector<unsigned char>(0));
|
||||
scriptWitness.stack.push_back(vector<unsigned char>(0));
|
||||
scriptWitness.stack.push_back(vector<unsigned char>(witnessScript.begin(), witnessScript.end()));
|
||||
witness.scriptWitness = scriptWitness;
|
||||
|
||||
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, witness);
|
||||
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness);
|
||||
assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 2);
|
||||
assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags & ~SCRIPT_VERIFY_WITNESS) == 0);
|
||||
assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY);
|
||||
|
@ -228,14 +220,12 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
|
|||
CScript redeemScript = GetScriptForWitness(witnessScript);
|
||||
CScript scriptPubKey = GetScriptForDestination(CScriptID(redeemScript));
|
||||
CScript scriptSig = CScript() << ToByteVector(redeemScript);
|
||||
CTxInWitness witness;
|
||||
CScriptWitness scriptWitness;
|
||||
scriptWitness.stack.push_back(vector<unsigned char>(0));
|
||||
scriptWitness.stack.push_back(vector<unsigned char>(0));
|
||||
scriptWitness.stack.push_back(vector<unsigned char>(witnessScript.begin(), witnessScript.end()));
|
||||
witness.scriptWitness = scriptWitness;
|
||||
|
||||
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, witness);
|
||||
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness);
|
||||
assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 2);
|
||||
assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY);
|
||||
}
|
||||
|
|
|
@ -170,7 +170,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
|
|||
amount = mapprevOutValues[tx.vin[i].prevout];
|
||||
}
|
||||
unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
|
||||
const CScriptWitness *witness = (i < tx.wit.vtxinwit.size()) ? &tx.wit.vtxinwit[i].scriptWitness : NULL;
|
||||
const CScriptWitness *witness = &tx.vin[i].scriptWitness;
|
||||
BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout],
|
||||
witness, verify_flags, TransactionSignatureChecker(&tx, i, amount, txdata), &err),
|
||||
strTest);
|
||||
|
@ -254,7 +254,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
|
|||
if (mapprevOutValues.count(tx.vin[i].prevout)) {
|
||||
amount = mapprevOutValues[tx.vin[i].prevout];
|
||||
}
|
||||
const CScriptWitness *witness = (i < tx.wit.vtxinwit.size()) ? &tx.wit.vtxinwit[i].scriptWitness : NULL;
|
||||
const CScriptWitness *witness = &tx.vin[i].scriptWitness;
|
||||
fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout],
|
||||
witness, verify_flags, TransactionSignatureChecker(&tx, i, amount, txdata), &err);
|
||||
}
|
||||
|
@ -351,7 +351,6 @@ void CreateCreditAndSpend(const CKeyStore& keystore, const CScript& outscript, C
|
|||
outputm.vin.resize(1);
|
||||
outputm.vin[0].prevout.SetNull();
|
||||
outputm.vin[0].scriptSig = CScript();
|
||||
outputm.wit.vtxinwit.resize(1);
|
||||
outputm.vout.resize(1);
|
||||
outputm.vout[0].nValue = 1;
|
||||
outputm.vout[0].scriptPubKey = outscript;
|
||||
|
@ -362,14 +361,12 @@ void CreateCreditAndSpend(const CKeyStore& keystore, const CScript& outscript, C
|
|||
assert(output->vin[0] == outputm.vin[0]);
|
||||
assert(output->vout.size() == 1);
|
||||
assert(output->vout[0] == outputm.vout[0]);
|
||||
assert(output->wit.vtxinwit.size() == 0);
|
||||
|
||||
CMutableTransaction inputm;
|
||||
inputm.nVersion = 1;
|
||||
inputm.vin.resize(1);
|
||||
inputm.vin[0].prevout.hash = output->GetHash();
|
||||
inputm.vin[0].prevout.n = 0;
|
||||
inputm.wit.vtxinwit.resize(1);
|
||||
inputm.vout.resize(1);
|
||||
inputm.vout[0].nValue = 1;
|
||||
inputm.vout[0].scriptPubKey = CScript();
|
||||
|
@ -382,20 +379,14 @@ void CreateCreditAndSpend(const CKeyStore& keystore, const CScript& outscript, C
|
|||
assert(input.vin[0] == inputm.vin[0]);
|
||||
assert(input.vout.size() == 1);
|
||||
assert(input.vout[0] == inputm.vout[0]);
|
||||
if (inputm.wit.IsNull()) {
|
||||
assert(input.wit.IsNull());
|
||||
} else {
|
||||
assert(!input.wit.IsNull());
|
||||
assert(input.wit.vtxinwit.size() == 1);
|
||||
assert(input.wit.vtxinwit[0].scriptWitness.stack == inputm.wit.vtxinwit[0].scriptWitness.stack);
|
||||
}
|
||||
assert(input.vin[0].scriptWitness.stack == inputm.vin[0].scriptWitness.stack);
|
||||
}
|
||||
|
||||
void CheckWithFlag(const CTransactionRef& output, const CMutableTransaction& input, int flags, bool success)
|
||||
{
|
||||
ScriptError error;
|
||||
CTransaction inputi(input);
|
||||
bool ret = VerifyScript(inputi.vin[0].scriptSig, output->vout[0].scriptPubKey, inputi.wit.vtxinwit.size() > 0 ? &inputi.wit.vtxinwit[0].scriptWitness : NULL, flags, TransactionSignatureChecker(&inputi, 0, output->vout[0].nValue), &error);
|
||||
bool ret = VerifyScript(inputi.vin[0].scriptSig, output->vout[0].scriptPubKey, &inputi.vin[0].scriptWitness, flags, TransactionSignatureChecker(&inputi, 0, output->vout[0].nValue), &error);
|
||||
assert(ret == success);
|
||||
}
|
||||
|
||||
|
|
|
@ -446,7 +446,7 @@ int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& i
|
|||
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
||||
{
|
||||
const CTxOut &prevout = inputs.GetOutputFor(tx.vin[i]);
|
||||
nSigOps += CountWitnessSigOps(tx.vin[i].scriptSig, prevout.scriptPubKey, i < tx.wit.vtxinwit.size() ? &tx.wit.vtxinwit[i].scriptWitness : NULL, flags);
|
||||
nSigOps += CountWitnessSigOps(tx.vin[i].scriptSig, prevout.scriptPubKey, &tx.vin[i].scriptWitness, flags);
|
||||
}
|
||||
return nSigOps;
|
||||
}
|
||||
|
@ -550,7 +550,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
|
|||
|
||||
// Reject transactions with witness before segregated witness activates (override with -prematurewitness)
|
||||
bool witnessEnabled = IsWitnessEnabled(chainActive.Tip(), Params().GetConsensus());
|
||||
if (!GetBoolArg("-prematurewitness",false) && !tx.wit.IsNull() && !witnessEnabled) {
|
||||
if (!GetBoolArg("-prematurewitness",false) && tx.HasWitness() && !witnessEnabled) {
|
||||
return state.DoS(0, false, REJECT_NONSTANDARD, "no-witness-yet", true);
|
||||
}
|
||||
|
||||
|
@ -672,7 +672,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
|
|||
return state.Invalid(false, REJECT_NONSTANDARD, "bad-txns-nonstandard-inputs");
|
||||
|
||||
// Check for non-standard witness in P2WSH
|
||||
if (!tx.wit.IsNull() && fRequireStandard && !IsWitnessStandard(tx, view))
|
||||
if (tx.HasWitness() && fRequireStandard && !IsWitnessStandard(tx, view))
|
||||
return state.DoS(0, false, REJECT_NONSTANDARD, "bad-witness-nonstandard", true);
|
||||
|
||||
int64_t nSigOpsCost = GetTransactionSigOpCost(tx, view, STANDARD_SCRIPT_VERIFY_FLAGS);
|
||||
|
@ -912,7 +912,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
|
|||
// SCRIPT_VERIFY_CLEANSTACK requires SCRIPT_VERIFY_WITNESS, so we
|
||||
// need to turn both off, and compare against just turning off CLEANSTACK
|
||||
// to see if the failure is specifically due to witness validation.
|
||||
if (tx.wit.IsNull() && CheckInputs(tx, state, view, true, scriptVerifyFlags & ~(SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK), true, txdata) &&
|
||||
if (!tx.HasWitness() && CheckInputs(tx, state, view, true, scriptVerifyFlags & ~(SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK), true, txdata) &&
|
||||
!CheckInputs(tx, state, view, true, scriptVerifyFlags & ~SCRIPT_VERIFY_CLEANSTACK, true, txdata)) {
|
||||
// Only the witness is missing, so the transaction itself may be fine.
|
||||
state.SetCorruptionPossible();
|
||||
|
@ -1304,7 +1304,7 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight)
|
|||
|
||||
bool CScriptCheck::operator()() {
|
||||
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
|
||||
const CScriptWitness *witness = (nIn < ptxTo->wit.vtxinwit.size()) ? &ptxTo->wit.vtxinwit[nIn].scriptWitness : NULL;
|
||||
const CScriptWitness *witness = &ptxTo->vin[nIn].scriptWitness;
|
||||
if (!VerifyScript(scriptSig, scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore, *txdata), &error)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2846,11 +2846,10 @@ void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPr
|
|||
{
|
||||
int commitpos = GetWitnessCommitmentIndex(block);
|
||||
static const std::vector<unsigned char> nonce(32, 0x00);
|
||||
if (commitpos != -1 && IsWitnessEnabled(pindexPrev, consensusParams) && block.vtx[0]->wit.IsEmpty()) {
|
||||
if (commitpos != -1 && IsWitnessEnabled(pindexPrev, consensusParams) && !block.vtx[0]->HasWitness()) {
|
||||
CMutableTransaction tx(*block.vtx[0]);
|
||||
tx.wit.vtxinwit.resize(1);
|
||||
tx.wit.vtxinwit[0].scriptWitness.stack.resize(1);
|
||||
tx.wit.vtxinwit[0].scriptWitness.stack[0] = nonce;
|
||||
tx.vin[0].scriptWitness.stack.resize(1);
|
||||
tx.vin[0].scriptWitness.stack[0] = nonce;
|
||||
block.vtx[0] = MakeTransactionRef(std::move(tx));
|
||||
}
|
||||
}
|
||||
|
@ -2958,10 +2957,10 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Co
|
|||
// The malleation check is ignored; as the transaction tree itself
|
||||
// already does not permit it, it is impossible to trigger in the
|
||||
// witness tree.
|
||||
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) {
|
||||
if (block.vtx[0]->vin[0].scriptWitness.stack.size() != 1 || block.vtx[0]->vin[0].scriptWitness.stack[0].size() != 32) {
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-witness-nonce-size", true, strprintf("%s : invalid witness nonce size", __func__));
|
||||
}
|
||||
CHash256().Write(hashWitness.begin(), 32).Write(&block.vtx[0]->wit.vtxinwit[0].scriptWitness.stack[0][0], 32).Finalize(hashWitness.begin());
|
||||
CHash256().Write(hashWitness.begin(), 32).Write(&block.vtx[0]->vin[0].scriptWitness.stack[0][0], 32).Finalize(hashWitness.begin());
|
||||
if (memcmp(hashWitness.begin(), &block.vtx[0]->vout[commitpos].scriptPubKey[6], 32)) {
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-witness-merkle-match", true, strprintf("%s : witness merkle commitment mismatch", __func__));
|
||||
}
|
||||
|
@ -2972,7 +2971,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Co
|
|||
// No witness data is allowed in blocks that don't commit to witness data, as this would otherwise leave room for spam
|
||||
if (!fHaveWitness) {
|
||||
for (size_t i = 0; i < block.vtx.size(); i++) {
|
||||
if (!block.vtx[i]->wit.IsNull()) {
|
||||
if (block.vtx[i]->HasWitness()) {
|
||||
return state.DoS(100, false, REJECT_INVALID, "unexpected-witness", true, strprintf("%s : unexpected witness data found", __func__));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2301,7 +2301,6 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
|
|||
nChangePosInOut = nChangePosRequest;
|
||||
txNew.vin.clear();
|
||||
txNew.vout.clear();
|
||||
txNew.wit.SetNull();
|
||||
wtxNew.fFromMe = true;
|
||||
bool fFirst = true;
|
||||
|
||||
|
@ -2488,9 +2487,10 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
|
|||
|
||||
// Remove scriptSigs if we used dummy signatures for fee calculation
|
||||
if (!sign) {
|
||||
BOOST_FOREACH (CTxIn& vin, txNew.vin)
|
||||
BOOST_FOREACH (CTxIn& vin, txNew.vin) {
|
||||
vin.scriptSig = CScript();
|
||||
txNew.wit.SetNull();
|
||||
vin.scriptWitness.SetNull();
|
||||
}
|
||||
}
|
||||
|
||||
// Embed the constructed transaction data in wtxNew.
|
||||
|
|
Loading…
Reference in a new issue