mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-16 13:01:19 +02:00
FULLFEATURE: Separate serialization tx witness and the rest
This commit is contained in:
parent
a04ea8a812
commit
663e9bd329
10 changed files with 164 additions and 51 deletions
|
|
@ -585,19 +585,19 @@ static void MutateTxWithdrawSign(CMutableTransaction& tx, const string& flagStr)
|
|||
merkleBlock.header.SetBitcoinBlock();
|
||||
ssProof >> merkleBlock;
|
||||
|
||||
CDataStream ssTx(txData, SER_NETWORK, PROTOCOL_VERSION);
|
||||
CDataStream ssTx(txData, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_VERSION_MASK_BITCOIN_TX);
|
||||
CTransaction txBTC;
|
||||
ssTx >> txBTC;
|
||||
|
||||
CDataStream ssCoinbaseTx(coinbaseTxData, SER_NETWORK, PROTOCOL_VERSION);
|
||||
CDataStream ssCoinbaseTx(coinbaseTxData, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_VERSION_MASK_BITCOIN_TX);
|
||||
CTransaction coinbaseTxBTC;
|
||||
ssCoinbaseTx >> coinbaseTxBTC;
|
||||
|
||||
vector<uint256> transactionHashes;
|
||||
if (merkleBlock.txn.ExtractMatches(transactionHashes) != merkleBlock.header.hashMerkleRoot ||
|
||||
transactionHashes.size() != 2 ||
|
||||
transactionHashes[0] != coinbaseTxBTC.GetHash() ||
|
||||
transactionHashes[1] != txBTC.GetHash())
|
||||
transactionHashes[0] != coinbaseTxBTC.GetBitcoinHash() ||
|
||||
transactionHashes[1] != txBTC.GetBitcoinHash())
|
||||
throw runtime_error("txoutproof is invalid or did not match tx");
|
||||
|
||||
if (nOut < 0 || (unsigned int) nOut >= txBTC.vout.size())
|
||||
|
|
|
|||
|
|
@ -1971,6 +1971,9 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
|||
dsMerkleBlockDS << (CMerkleBlock(block, txSet));
|
||||
scriptSig.PushWithdraw(std::vector<unsigned char>(dsMerkleBlockDS.begin(), dsMerkleBlockDS.end()));
|
||||
|
||||
uint256 witnessHash(dsTx.GetWitnessHash());
|
||||
scriptSig << std::vector<unsigned char>(witnessHash.begin(), witnessHash.end());
|
||||
|
||||
scriptSig << OP_1 << OP_1;
|
||||
|
||||
proofTx.vout.push_back(CTxOut(0, CScript()));
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter& filter)
|
|||
|
||||
for (unsigned int i = 0; i < block.vtx.size(); i++)
|
||||
{
|
||||
const uint256& hash = block.vtx[i].GetHash();
|
||||
const uint256& hash = block.vtx[i].GetFullHash();
|
||||
if (filter.IsRelevantAndUpdate(block.vtx[i]))
|
||||
{
|
||||
vMatch.push_back(true);
|
||||
|
|
@ -54,7 +54,7 @@ CMerkleBlock::CMerkleBlock(const CBlock& block, const std::set<uint256>& txids)
|
|||
vMatch.push_back(true);
|
||||
else
|
||||
vMatch.push_back(false);
|
||||
vHashes.push_back(hash);
|
||||
vHashes.push_back(block.vtx[i].GetFullHash());
|
||||
}
|
||||
|
||||
txn = CPartialMerkleTree(vHashes, vMatch);
|
||||
|
|
|
|||
|
|
@ -65,8 +65,12 @@ uint256 CBlock::BuildMerkleTree(bool* fMutated) const
|
|||
*/
|
||||
vMerkleTree.clear();
|
||||
vMerkleTree.reserve(vtx.size() * 2 + 16); // Safe upper bound for the number of total nodes.
|
||||
for (std::vector<CTransaction>::const_iterator it(vtx.begin()); it != vtx.end(); ++it)
|
||||
vMerkleTree.push_back(it->GetHash());
|
||||
for (std::vector<CTransaction>::const_iterator it(vtx.begin()); it != vtx.end(); ++it) {
|
||||
if (IsBitcoinBlock())
|
||||
vMerkleTree.push_back(it->GetBitcoinHash());
|
||||
else
|
||||
vMerkleTree.push_back(it->GetFullHash());
|
||||
}
|
||||
int j = 0;
|
||||
bool mutated = false;
|
||||
for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
|
||||
|
|
|
|||
|
|
@ -185,6 +185,8 @@ public:
|
|||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(*(CBlockHeader*)this);
|
||||
if (IsBitcoinBlock())
|
||||
nVersion |= SERIALIZE_VERSION_MASK_BITCOIN_TX;
|
||||
READWRITE(vtx);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,10 +18,7 @@ CTxOutValue::CTxOutValue()
|
|||
CTxOutValue::CTxOutValue(CAmount nAmountIn)
|
||||
{
|
||||
vchCommitment.resize(nCommitmentSize);
|
||||
assert(vchCommitment.size() > sizeof(nAmountIn) + 1);
|
||||
memset(&vchCommitment[0], 0, vchCommitment.size() - sizeof(nAmountIn));
|
||||
for (size_t i = 0; i < sizeof(nAmountIn); ++i)
|
||||
vchCommitment[vchCommitment.size() - (i + 1)] = ((nAmountIn >> (i * 8)) & 0xff);
|
||||
SetToAmount(nAmountIn);
|
||||
}
|
||||
|
||||
CTxOutValue::CTxOutValue(const std::vector<unsigned char>& vchValueCommitmentIn, const std::vector<unsigned char>& vchRangeproofIn)
|
||||
|
|
@ -62,6 +59,14 @@ bool CTxOutValue::IsAmount() const
|
|||
return !vchCommitment[0];
|
||||
}
|
||||
|
||||
void CTxOutValue::SetToAmount(CAmount nAmount)
|
||||
{
|
||||
assert(vchCommitment.size() > sizeof(nAmount) + 1);
|
||||
memset(&vchCommitment[0], 0, vchCommitment.size() - sizeof(nAmount));
|
||||
for (size_t i = 0; i < sizeof(nAmount); ++i)
|
||||
vchCommitment[vchCommitment.size() - (i + 1)] = ((nAmount >> (i * 8)) & 0xff);
|
||||
}
|
||||
|
||||
CAmount CTxOutValue::GetAmount() const
|
||||
{
|
||||
assert(IsAmount());
|
||||
|
|
@ -132,15 +137,36 @@ CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.n
|
|||
|
||||
uint256 CMutableTransaction::GetHash() const
|
||||
{
|
||||
return SerializeHash(*this);
|
||||
if (IsCoinBase()) {
|
||||
return SerializeHash(*this, SER_GETHASH, PROTOCOL_VERSION);
|
||||
} else {
|
||||
return SerializeHash(*this, SER_GETHASH, PROTOCOL_VERSION | SERIALIZE_VERSION_MASK_NO_WITNESS);
|
||||
}
|
||||
}
|
||||
|
||||
void CTransaction::UpdateHash() const
|
||||
{
|
||||
*const_cast<uint256*>(&hash) = SerializeHash(*this);
|
||||
bool maybeBitcoinTx = true;
|
||||
for (unsigned int i = 0; i < vout.size(); i++)
|
||||
if (!vout[i].nValue.IsAmount())
|
||||
maybeBitcoinTx = false;
|
||||
if (maybeBitcoinTx)
|
||||
*const_cast<uint256*>(&hashBitcoin) = SerializeHash(*this, SER_GETHASH, PROTOCOL_VERSION | SERIALIZE_VERSION_MASK_BITCOIN_TX);
|
||||
|
||||
if (IsCoinBase()) {
|
||||
*const_cast<uint256*>(&hash) = SerializeHash(*this, SER_GETHASH, PROTOCOL_VERSION);
|
||||
} else {
|
||||
*const_cast<uint256*>(&hash) = SerializeHash(*this, SER_GETHASH, PROTOCOL_VERSION | SERIALIZE_VERSION_MASK_NO_WITNESS);
|
||||
}
|
||||
*const_cast<uint256*>(&hashWitness) = SerializeHash(*this, SER_GETHASH, PROTOCOL_VERSION | SERIALIZE_VERSION_MASK_ONLY_WITNESS);
|
||||
// Update full hash combining the normalized txid with the hash of the witness
|
||||
CHash256 hasher;
|
||||
hasher.Write((unsigned char*)&hash, hash.size());
|
||||
hasher.Write((unsigned char*)&hashWitness, hashWitness.size());
|
||||
hasher.Finalize((unsigned char*)&hashFull);
|
||||
}
|
||||
|
||||
CTransaction::CTransaction() : hash(0), nVersion(CTransaction::CURRENT_VERSION), vin(), nTxFee(0), vout(), nLockTime(0) { }
|
||||
CTransaction::CTransaction() : hash(0), hashFull(0), nVersion(CTransaction::CURRENT_VERSION), vin(), nTxFee(0), vout(), nLockTime(0) { }
|
||||
|
||||
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), nTxFee(tx.nTxFee), vout(tx.vout), nLockTime(tx.nLockTime) {
|
||||
UpdateHash();
|
||||
|
|
@ -153,6 +179,7 @@ CTransaction& CTransaction::operator=(const CTransaction &tx) {
|
|||
*const_cast<std::vector<CTxOut>*>(&vout) = tx.vout;
|
||||
*const_cast<unsigned int*>(&nLockTime) = tx.nLockTime;
|
||||
*const_cast<uint256*>(&hash) = tx.hash;
|
||||
*const_cast<uint256*>(&hashFull) = tx.hashFull;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,10 +7,16 @@
|
|||
#define BITCOIN_PRIMITIVES_TRANSACTION_H
|
||||
|
||||
#include "amount.h"
|
||||
#include "hash.h"
|
||||
#include "script/script.h"
|
||||
#include "serialize.h"
|
||||
#include "uint256.h"
|
||||
|
||||
#define SERIALIZE_VERSION_MASK_NO_WITNESS 0x40000000
|
||||
#define SERIALIZE_VERSION_MASK_ONLY_WITNESS 0x80000000
|
||||
#define SERIALIZE_VERSION_MASK_BITCOIN_TX 0x20000000
|
||||
#define SERIALIZE_VERSION_MASK_PREHASH 0x10000000
|
||||
|
||||
class CTxOutValue
|
||||
{
|
||||
public:
|
||||
|
|
@ -29,9 +35,29 @@ public:
|
|||
template<typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion)
|
||||
{
|
||||
READWRITE(REF(CFlatData(&vchCommitment[0], &vchCommitment[nCommitmentSize])));
|
||||
READWRITE(vchRangeproof);
|
||||
READWRITE(vchNonceCommitment);
|
||||
bool fBitcoinTx = nVersion & SERIALIZE_VERSION_MASK_BITCOIN_TX;
|
||||
bool fWitness = (nVersion & SERIALIZE_VERSION_MASK_NO_WITNESS) == 0;
|
||||
bool fOnlyWitness = nVersion & SERIALIZE_VERSION_MASK_ONLY_WITNESS;
|
||||
assert(!fBitcoinTx || IsAmount() || (IsNull() && ser_action.ForRead()));
|
||||
if (fBitcoinTx) {
|
||||
CAmount amount = 0;
|
||||
if (!ser_action.ForRead())
|
||||
amount = GetAmount();
|
||||
READWRITE(amount);
|
||||
if (ser_action.ForRead())
|
||||
SetToAmount(amount);
|
||||
} else {
|
||||
if (!fOnlyWitness) READWRITE(REF(CFlatData(&vchCommitment[0], &vchCommitment[nCommitmentSize])));
|
||||
if (fWitness) {
|
||||
if (nVersion & SERIALIZE_VERSION_MASK_PREHASH) {
|
||||
uint256 prehash = (CHashWriter(nType, nVersion) << vchRangeproof << vchNonceCommitment).GetHash();
|
||||
READWRITE(prehash);
|
||||
} else {
|
||||
READWRITE(vchRangeproof);
|
||||
READWRITE(vchNonceCommitment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IsValid() const;
|
||||
|
|
@ -39,6 +65,7 @@ public:
|
|||
bool IsAmount() const;
|
||||
|
||||
CAmount GetAmount() const;
|
||||
void SetToAmount(CAmount nAmount);
|
||||
|
||||
friend bool operator==(const CTxOutValue& a, const CTxOutValue& b);
|
||||
friend bool operator!=(const CTxOutValue& a, const CTxOutValue& b);
|
||||
|
|
@ -105,9 +132,12 @@ public:
|
|||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(prevout);
|
||||
READWRITE(scriptSig);
|
||||
READWRITE(nSequence);
|
||||
bool fWitness = (nVersion & SERIALIZE_VERSION_MASK_NO_WITNESS) == 0;
|
||||
bool fOnlyWitness = nVersion & SERIALIZE_VERSION_MASK_ONLY_WITNESS;
|
||||
assert((nType != SER_GETHASH && !fOnlyWitness && fWitness) || nType == SER_GETHASH);
|
||||
if (!fOnlyWitness) READWRITE(prevout);
|
||||
if (fWitness) READWRITE(scriptSig);
|
||||
if (!fOnlyWitness) READWRITE(nSequence);
|
||||
}
|
||||
|
||||
friend bool operator==(const CTxIn& a, const CTxIn& b)
|
||||
|
|
@ -201,6 +231,9 @@ class CTransaction
|
|||
private:
|
||||
/** Memory only. */
|
||||
const uint256 hash;
|
||||
const uint256 hashWitness; // Just witness
|
||||
const uint256 hashFull; // Including witness
|
||||
const uint256 hashBitcoin; // For Bitcoin Transactions
|
||||
void UpdateHash() const;
|
||||
|
||||
public:
|
||||
|
|
@ -229,12 +262,16 @@ public:
|
|||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(*const_cast<int32_t*>(&this->nVersion));
|
||||
nVersion = this->nVersion;
|
||||
READWRITE(*const_cast<std::vector<CTxIn>*>(&vin));
|
||||
READWRITE(*const_cast<CAmount*>(&nTxFee));
|
||||
READWRITE(*const_cast<std::vector<CTxOut>*>(&vout));
|
||||
READWRITE(*const_cast<uint32_t*>(&nLockTime));
|
||||
bool fWitness = (nVersion & SERIALIZE_VERSION_MASK_NO_WITNESS) == 0;
|
||||
bool fOnlyWitness = nVersion & SERIALIZE_VERSION_MASK_ONLY_WITNESS;
|
||||
bool fBitcoinTx = nVersion & SERIALIZE_VERSION_MASK_BITCOIN_TX;
|
||||
assert(!fBitcoinTx || (fBitcoinTx && fWitness && !fOnlyWitness));
|
||||
assert((nType != SER_GETHASH && !fOnlyWitness && fWitness) || nType == SER_GETHASH);
|
||||
if (!fOnlyWitness) READWRITE(*const_cast<int32_t*>(&this->nVersion));
|
||||
READWRITE(*const_cast<std::vector<CTxIn>*>(&vin));
|
||||
if (!fBitcoinTx && !fOnlyWitness) READWRITE(*const_cast<CAmount*>(&nTxFee));
|
||||
if (!fOnlyWitness) READWRITE(*const_cast<std::vector<CTxOut>*>(&vout));
|
||||
if (!fOnlyWitness) READWRITE(*const_cast<uint32_t*>(&nLockTime));
|
||||
if (ser_action.ForRead())
|
||||
UpdateHash();
|
||||
}
|
||||
|
|
@ -243,10 +280,27 @@ public:
|
|||
return vin.empty() && vout.empty();
|
||||
}
|
||||
|
||||
/* Transaction hash without witness information */
|
||||
const uint256& GetHash() const {
|
||||
return hash;
|
||||
}
|
||||
|
||||
/* Transaction hash including witness information */
|
||||
const uint256& GetFullHash() const {
|
||||
return hashFull;
|
||||
}
|
||||
|
||||
/* Hash of just witness information */
|
||||
const uint256& GetWitnessHash() const {
|
||||
return hashWitness;
|
||||
}
|
||||
|
||||
/* Transaction hash including witness information */
|
||||
const uint256& GetBitcoinHash() const {
|
||||
assert(hashBitcoin != 0);
|
||||
return hashBitcoin;
|
||||
}
|
||||
|
||||
// Compute priority, given priority of inputs and (optionally) tx size
|
||||
double ComputePriority(double dPriorityInputs, unsigned int nTxSize=0) const;
|
||||
|
||||
|
|
@ -287,12 +341,21 @@ struct CMutableTransaction
|
|||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(this->nVersion);
|
||||
nVersion = this->nVersion;
|
||||
READWRITE(vin);
|
||||
READWRITE(nTxFee);
|
||||
READWRITE(vout);
|
||||
READWRITE(nLockTime);
|
||||
bool fWitness = (nVersion & SERIALIZE_VERSION_MASK_NO_WITNESS) == 0;
|
||||
bool fOnlyWitness = nVersion & SERIALIZE_VERSION_MASK_ONLY_WITNESS;
|
||||
bool fBitcoinTx = nVersion & SERIALIZE_VERSION_MASK_BITCOIN_TX;
|
||||
assert(!fBitcoinTx);
|
||||
assert((nType != SER_GETHASH && !fOnlyWitness && fWitness) || nType == SER_GETHASH);
|
||||
if (!fOnlyWitness) READWRITE(this->nVersion);
|
||||
READWRITE(vin);
|
||||
if (!fOnlyWitness) READWRITE(nTxFee);
|
||||
if (!fOnlyWitness) READWRITE(vout);
|
||||
if (!fOnlyWitness) READWRITE(nLockTime);
|
||||
}
|
||||
|
||||
bool IsCoinBase() const
|
||||
{
|
||||
return (vin.size() == 1 && vin[0].prevout.IsNull());
|
||||
}
|
||||
|
||||
/** Compute the hash of this CMutableTransaction. This is computed on the
|
||||
|
|
|
|||
|
|
@ -1416,7 +1416,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
|
|||
#endif
|
||||
|
||||
CTransaction locktx;
|
||||
CDataStream locktxStream(vlockTx, SER_NETWORK, PROTOCOL_VERSION);
|
||||
CDataStream locktxStream(vlockTx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_VERSION_MASK_BITCOIN_TX);
|
||||
locktxStream >> locktx;
|
||||
if (!locktxStream.empty())
|
||||
return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_LOCKTX);
|
||||
|
|
@ -1425,16 +1425,16 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
|
|||
if (nlocktxOut < 0 || (unsigned int)nlocktxOut >= locktx.vout.size())
|
||||
return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_LOCKTX);
|
||||
|
||||
if (locktx.GetHash() != txHashes[1])
|
||||
if (locktx.GetBitcoinHash() != txHashes[1])
|
||||
return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_LOCKTX);
|
||||
|
||||
CTransaction coinbasetx;
|
||||
CDataStream coinbasetxStream(vlockCoinbaseTx, SER_NETWORK, PROTOCOL_VERSION);
|
||||
CDataStream coinbasetxStream(vlockCoinbaseTx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_VERSION_MASK_BITCOIN_TX);
|
||||
coinbasetxStream >> coinbasetx;
|
||||
if (!coinbasetxStream.empty())
|
||||
return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_BLOCK);
|
||||
|
||||
if (coinbasetx.GetHash() != txHashes[0] || !coinbasetx.IsCoinBase())
|
||||
if (coinbasetx.GetBitcoinHash() != txHashes[0] || !coinbasetx.IsCoinBase())
|
||||
return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_BLOCK);
|
||||
valtype vcoinbaseHeight;
|
||||
CScript::const_iterator coinbasepc = coinbasetx.vin[0].scriptSig.begin();
|
||||
|
|
@ -1501,7 +1501,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
|
|||
if (withdrawOutput.nValue.GetAmount() < withdrawVal)
|
||||
return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_OUTPUT);
|
||||
|
||||
uint256 locktxHash = locktx.GetHash();
|
||||
uint256 locktxHash = locktx.GetBitcoinHash();
|
||||
std::vector<unsigned char> vlocktxHash(locktxHash.begin(), locktxHash.end());
|
||||
CScript expectedWithdrawScriptPubKeyStart = CScript() << OP_IF << nLockHeight
|
||||
<< std::vector<unsigned char>(vlocktxHash.rbegin(), vlocktxHash.rend()) << nlocktxOut
|
||||
|
|
@ -1621,11 +1621,18 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
|
|||
if (proofType == 1) { // Double-spent withdraw
|
||||
// We need to have complete proof that two transactions double-spent each other:
|
||||
// So we read the following from the stack:
|
||||
// 9. merkle block with tx we are proving against (ie our input tx)
|
||||
// 10. the full transaction of the original withdraw
|
||||
// 11. the input index in the transaction above which shows the double-spend
|
||||
// 12. the transaction which is spent in the above input
|
||||
// 13. merkle block containing the original withdraw tx, required only if they are not in the same block
|
||||
// 9. witness hash of the tx we are proving against (ie our input tx)
|
||||
// 10. merkle block with tx we are proving against (ie our input tx)
|
||||
// 11. the full transaction of the original withdraw
|
||||
// 12. the input index in the transaction above which shows the double-spend
|
||||
// 13. the transaction which is spent in the above input
|
||||
// 14. merkle block containing the original withdraw tx, required only if they are not in the same block
|
||||
if (stack.size() < size_t(-(stackReadPos)))
|
||||
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
|
||||
valtype vInputTxWitnessHash = stacktop(stackReadPos--);
|
||||
if (vInputTxWitnessHash.size() != 32)
|
||||
return set_error(serror, SCRIPT_ERR_REORG_VERIFY_FORMAT);
|
||||
|
||||
valtype vmerkleBlockInputTx;
|
||||
if (!WithdrawProofReadStackItem(stack, fRequireMinimal, &stackReadPos, vmerkleBlockInputTx))
|
||||
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
|
||||
|
|
@ -1655,7 +1662,14 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
|
|||
if (inputTxHashes.size() != 1 && inputTxHashes.size() != 2)
|
||||
return set_error(serror, SCRIPT_ERR_REORG_VERIFY_FRAUD_BLOCK);
|
||||
|
||||
if (inputTxHashes[0] != checker.GetPrevOut().hash)
|
||||
uint256 inputTxWitnessHash(vInputTxWitnessHash);
|
||||
uint256 inputTxFullHash(checker.GetPrevOut().hash);
|
||||
CHash256 hasher;
|
||||
hasher.Write(inputTxFullHash.begin(), inputTxFullHash.size());
|
||||
hasher.Write(inputTxWitnessHash.begin(), inputTxWitnessHash.size());
|
||||
hasher.Finalize(inputTxFullHash.begin());
|
||||
|
||||
if (inputTxHashes[0] != inputTxFullHash)
|
||||
return set_error(serror, SCRIPT_ERR_REORG_VERIFY_FRAUD_BLOCK);
|
||||
|
||||
CTransaction originalWithdrawTx;
|
||||
|
|
@ -1681,9 +1695,9 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
|
|||
if (originalWithdrawHashes.size() != 1 || merkleBlockOriginalWithdrawTx.header.GetHash() == merkleBlockInputTx.header.GetHash())
|
||||
return set_error(serror, SCRIPT_ERR_REORG_VERIFY_FRAUD_ORIG_BLOCK);
|
||||
|
||||
if (originalWithdrawHashes[0] != originalWithdrawTx.GetHash())
|
||||
if (originalWithdrawHashes[0] != originalWithdrawTx.GetFullHash())
|
||||
return set_error(serror, SCRIPT_ERR_REORG_VERIFY_FRAUD_ORIG_BLOCK);
|
||||
} else if (inputTxHashes[1] != originalWithdrawTx.GetHash())
|
||||
} else if (inputTxHashes[1] != originalWithdrawTx.GetFullHash())
|
||||
return set_error(serror, SCRIPT_ERR_REORG_VERIFY_FRAUD_BLOCK);
|
||||
|
||||
int noriginalWithdrawTxIn = CScriptNum(voriginalWithdrawTxInIndex, fRequireMinimal).getint();
|
||||
|
|
@ -1830,9 +1844,9 @@ public:
|
|||
void SerializeOutput(S &s, unsigned int nOutput, int nType, int nVersion) const {
|
||||
if (fHashSingle && nOutput != nIn)
|
||||
// Do not lock-in the txout payee at other indices as txin
|
||||
::Serialize(s, CTxOut(), nType, nVersion);
|
||||
::Serialize(s, CTxOut(), nType, nVersion | SERIALIZE_VERSION_MASK_PREHASH);
|
||||
else
|
||||
::Serialize(s, txTo.vout[nOutput], nType, nVersion);
|
||||
::Serialize(s, txTo.vout[nOutput], nType, nVersion | SERIALIZE_VERSION_MASK_PREHASH);
|
||||
}
|
||||
|
||||
/** Serialize txTo */
|
||||
|
|
|
|||
|
|
@ -473,12 +473,12 @@ COutPoint CScript::GetWithdrawSpent() const
|
|||
if (!PopWithdrawPush(pushes, &vTx))
|
||||
return COutPoint();
|
||||
CTransaction tx;
|
||||
CDataStream(vTx, SER_NETWORK, PROTOCOL_VERSION) >> tx;
|
||||
CDataStream(vTx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_VERSION_MASK_BITCOIN_TX) >> tx;
|
||||
|
||||
if (ntxOut < 0 || (unsigned int)ntxOut >= tx.vout.size())
|
||||
return COutPoint();
|
||||
|
||||
return COutPoint(tx.GetHash(), ntxOut);
|
||||
return COutPoint(tx.GetBitcoinHash(), ntxOut);
|
||||
} catch (std::exception& e) {
|
||||
return COutPoint();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2488,7 +2488,7 @@ int CMerkleTx::GetDepthInMainChainINTERNAL(const CBlockIndex* &pindexRet) const
|
|||
// Make sure the merkle branch connects to this block
|
||||
if (!fMerkleVerified)
|
||||
{
|
||||
if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot)
|
||||
if (CBlock::CheckMerkleBranch(GetFullHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot)
|
||||
return 0;
|
||||
fMerkleVerified = true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue