diff --git a/src/bench/checkblock.cpp b/src/bench/checkblock.cpp index 269ac847a5..9f52a22672 100644 --- a/src/bench/checkblock.cpp +++ b/src/bench/checkblock.cpp @@ -24,7 +24,7 @@ static void DeserializeBlockTest(benchmark::Bench& bench) bench.unit("block").run([&] { CBlock block; - stream >> block; + stream >> TX_WITH_WITNESS(block); bool rewound = stream.Rewind(benchmark::data::block413567.size()); assert(rewound); }); @@ -41,7 +41,7 @@ static void DeserializeAndCheckBlockTest(benchmark::Bench& bench) bench.unit("block").run([&] { CBlock block; // Note that CBlock caches its checked state, so we need to recreate it here - stream >> block; + stream >> TX_WITH_WITNESS(block); bool rewound = stream.Rewind(benchmark::data::block413567.size()); assert(rewound); diff --git a/src/bench/rpc_blockchain.cpp b/src/bench/rpc_blockchain.cpp index 724c7987de..ad6573c52c 100644 --- a/src/bench/rpc_blockchain.cpp +++ b/src/bench/rpc_blockchain.cpp @@ -27,7 +27,7 @@ struct TestBlockAndIndex { std::byte a{0}; stream.write({&a, 1}); // Prevent compaction - stream >> block; + stream >> TX_WITH_WITNESS(block); CBlockIndex::SetNodeContext(&(testing_setup->m_node)); blockHash = block.GetHash(); diff --git a/src/bench/verify_script.cpp b/src/bench/verify_script.cpp index 6b1a124dd0..5ab439180f 100644 --- a/src/bench/verify_script.cpp +++ b/src/bench/verify_script.cpp @@ -63,7 +63,7 @@ static void VerifyScriptBench(benchmark::Bench& bench) #if defined(HAVE_CONSENSUS_LIB) CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); - stream << txSpend; + stream << TX_WITH_WITNESS(txSpend); CDataStream streamVal(SER_NETWORK, PROTOCOL_VERSION); streamVal << txCredit.vout[0].nValue; int csuccess = bitcoinconsensus_verify_script_with_amount( diff --git a/src/bitcoin-util.cpp b/src/bitcoin-util.cpp index afe43284f7..3a32943af4 100644 --- a/src/bitcoin-util.cpp +++ b/src/bitcoin-util.cpp @@ -143,8 +143,8 @@ static int Grind(const std::vector& args, std::string& strPrint) return EXIT_FAILURE; } - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << header; + DataStream ss{}; + ss << TX_WITH_WITNESS(header); strPrint = HexStr(ss); return EXIT_SUCCESS; } diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp index e492aed362..cba7881a1d 100644 --- a/src/blockencodings.cpp +++ b/src/blockencodings.cpp @@ -30,8 +30,8 @@ CBlockHeaderAndShortTxIDs::CBlockHeaderAndShortTxIDs(const CBlock& block) : } void CBlockHeaderAndShortTxIDs::FillShortTxIDSelector() const { - CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); - stream << header << nonce; + DataStream stream{}; + stream << TX_WITH_WITNESS(header) << nonce; CSHA256 hasher; hasher.Write((unsigned char*)&(*stream.begin()), stream.end() - stream.begin()); uint256 shorttxidhash; @@ -170,7 +170,7 @@ ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& c break; } - LogPrint(BCLog::CMPCTBLOCK, "Initialized PartiallyDownloadedBlock for block %s using a cmpctblock of size %lu\n", cmpctblock.header.GetHash().ToString(), GetSerializeSize(cmpctblock, PROTOCOL_VERSION)); + LogPrint(BCLog::CMPCTBLOCK, "Initialized PartiallyDownloadedBlock for block %s using a cmpctblock of size %lu\n", cmpctblock.header.GetHash().ToString(), GetSerializeSize(TX_WITH_WITNESS(cmpctblock))); return READ_STATUS_OK; } diff --git a/src/blockencodings.h b/src/blockencodings.h index 148155fa5a..98757c1f45 100644 --- a/src/blockencodings.h +++ b/src/blockencodings.h @@ -65,7 +65,7 @@ public: SERIALIZE_METHODS(BlockTransactions, obj) { - READWRITE(obj.blockhash, Using>(obj.txn)); + READWRITE(obj.blockhash, TX_WITH_WITNESS(Using>(obj.txn))); } }; @@ -76,7 +76,7 @@ struct PrefilledTransaction { uint16_t index; CTransactionRef tx; - SERIALIZE_METHODS(PrefilledTransaction, obj) { READWRITE(COMPACTSIZE(obj.index), Using(obj.tx)); } + SERIALIZE_METHODS(PrefilledTransaction, obj) { READWRITE(COMPACTSIZE(obj.index), TX_WITH_WITNESS(Using(obj.tx))); } }; typedef enum ReadStatus_t diff --git a/src/consensus/tx_check.cpp b/src/consensus/tx_check.cpp index 501829096e..729fdefd72 100644 --- a/src/consensus/tx_check.cpp +++ b/src/consensus/tx_check.cpp @@ -16,8 +16,9 @@ bool CheckTransaction(const CTransaction& tx, TxValidationState& state) if (tx.vout.empty()) return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-vout-empty"); // Size limits (this doesn't take the witness into account, as that hasn't been checked for malleability) - if (::GetSerializeSize(tx, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT) + if (::GetSerializeSize(TX_NO_WITNESS(tx)) * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT) { return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-oversize"); + } // Check for negative or overflow output values (see CVE-2010-5139) CAmount nValueOutExplicit = 0; diff --git a/src/consensus/validation.h b/src/consensus/validation.h index c8fafa830a..6f0cebde01 100644 --- a/src/consensus/validation.h +++ b/src/consensus/validation.h @@ -149,11 +149,11 @@ class BlockValidationState : public ValidationState {}; // weight = (stripped_size * 3) + total_size. static inline int32_t GetTransactionWeight(const CTransaction& tx) { - return ::GetSerializeSize(tx, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(tx, PROTOCOL_VERSION); + return ::GetSerializeSize(TX_NO_WITNESS(tx)) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(TX_WITH_WITNESS(tx)); } static inline int64_t GetBlockWeight(const CBlock& block) { - return ::GetSerializeSize(block, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(block, PROTOCOL_VERSION); + return ::GetSerializeSize(TX_NO_WITNESS(block)) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(TX_WITH_WITNESS(block)); } static inline int64_t GetTransactionInputWeight(const CTransaction& tx, const size_t nIn) @@ -165,9 +165,7 @@ static inline int64_t GetTransactionInputWeight(const CTransaction& tx, const si assert(tx.witness.vtxinwit[nIn].vchIssuanceAmountRangeproof.empty()); assert(tx.witness.vtxinwit[nIn].vchInflationKeysRangeproof.empty()); - return ::GetSerializeSize(tx.vin[nIn], PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) - + ::GetSerializeSize(tx.vin[nIn], PROTOCOL_VERSION) - + ::GetSerializeSize(tx.witness.vtxinwit[nIn].scriptWitness.stack, PROTOCOL_VERSION); + return ::GetSerializeSize(TX_NO_WITNESS(tx.vin[nIn])) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(TX_WITH_WITNESS(tx.vin[nIn])) + ::GetSerializeSize(tx.witness.vtxinwit[nIn].scriptWitness.stack); } /** Compute at which vout of the block's coinbase transaction the witness commitment occurs, or -1 if not found */ diff --git a/src/core_io.h b/src/core_io.h index 34fe394d07..44a19bf8e3 100644 --- a/src/core_io.h +++ b/src/core_io.h @@ -53,10 +53,10 @@ bool ParseHashStr(const std::string& strHex, uint256& result); // core_write.cpp UniValue ValueFromAmount(const CAmount amount); std::string FormatScript(const CScript& script); -std::string EncodeHexTx(const CTransaction& tx, const int serializeFlags = 0); +std::string EncodeHexTx(const CTransaction& tx, const bool without_witness = false); UniValue EncodeHexScriptWitness(const CScriptWitness& witness); std::string SighashToStr(unsigned char sighash_type); void ScriptToUniv(const CScript& script, UniValue& out, bool include_hex = true, bool include_address = false, const SigningProvider* provider = nullptr); -void TxToUniv(const CTransaction& tx, const uint256& block_hash, UniValue& entry, bool include_hex = true, int serialize_flags = 0, const CTxUndo* txundo = nullptr, TxVerbosity verbosity = TxVerbosity::SHOW_DETAILS); +void TxToUniv(const CTransaction& tx, const uint256& block_hash, UniValue& entry, bool include_hex = true, bool without_witness = false, const CTxUndo* txundo = nullptr, TxVerbosity verbosity = TxVerbosity::SHOW_DETAILS); #endif // BITCOIN_CORE_IO_H diff --git a/src/core_read.cpp b/src/core_read.cpp index ad988d5898..65bf5b0b8e 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -142,9 +142,9 @@ static bool DecodeTx(CMutableTransaction& tx, const std::vector& // Try decoding with extended serialization support, and remember if the result successfully // consumes the entire input. if (try_witness) { - CDataStream ssData(tx_data, SER_NETWORK, PROTOCOL_VERSION); + DataStream ssData(tx_data); try { - ssData >> tx_extended; + ssData >> TX_WITH_WITNESS(tx_extended); if (ssData.empty()) ok_extended = true; } catch (const std::exception&) { // Fall through. @@ -160,9 +160,9 @@ static bool DecodeTx(CMutableTransaction& tx, const std::vector& // Try decoding with legacy serialization, and remember if the result successfully consumes the entire input. if (try_no_witness) { - CDataStream ssData(tx_data, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS); + DataStream ssData(tx_data); try { - ssData >> tx_legacy; + ssData >> TX_NO_WITNESS(tx_legacy); if (ssData.empty()) ok_legacy = true; } catch (const std::exception&) { // Fall through. @@ -207,9 +207,9 @@ bool DecodeHexBlockHeader(CBlockHeader& header, const std::string& hex_header) if (!IsHex(hex_header)) return false; const std::vector header_data{ParseHex(hex_header)}; - CDataStream ser_header(header_data, SER_NETWORK, PROTOCOL_VERSION); + DataStream ser_header(header_data); try { - ser_header >> header; + ser_header >> TX_WITH_WITNESS(header); } catch (const std::exception&) { return false; } @@ -222,9 +222,9 @@ bool DecodeHexBlk(CBlock& block, const std::string& strHexBlk) return false; std::vector blockData(ParseHex(strHexBlk)); - CDataStream ssBlock(blockData, SER_NETWORK, PROTOCOL_VERSION); + DataStream ssBlock(blockData); try { - ssBlock >> block; + ssBlock >> TX_WITH_WITNESS(block); } catch (const std::exception&) { return false; diff --git a/src/core_write.cpp b/src/core_write.cpp index 4aef2c04f2..8c2ec106c3 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -169,10 +169,14 @@ std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDeco return str; } -std::string EncodeHexTx(const CTransaction& tx, const int serializeFlags) +std::string EncodeHexTx(const CTransaction& tx, const bool without_witness) { - CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION | serializeFlags); - ssTx << tx; + DataStream ssTx; + if (without_witness) { + ssTx << TX_NO_WITNESS(tx); + } else { + ssTx << TX_WITH_WITNESS(tx); + } return HexStr(ssTx); } @@ -224,7 +228,7 @@ void ScriptToUniv(const CScript& script, UniValue& out, bool include_hex, bool i } } -void TxToUniv(const CTransaction& tx, const uint256& block_hash, UniValue& entry, bool include_hex, int serialize_flags, const CTxUndo* txundo, TxVerbosity verbosity) +void TxToUniv(const CTransaction& tx, const uint256& block_hash, UniValue& entry, bool include_hex, bool without_witness, const CTxUndo* txundo, TxVerbosity verbosity) { CHECK_NONFATAL(verbosity >= TxVerbosity::SHOW_DETAILS); @@ -237,7 +241,7 @@ void TxToUniv(const CTransaction& tx, const uint256& block_hash, UniValue& entry // Transaction version is actually unsigned in consensus checks, just signed in memory, // so cast to unsigned before giving it to the user. entry.pushKV("version", static_cast(static_cast(tx.nVersion))); - entry.pushKV("size", (int)::GetSerializeSize(tx, PROTOCOL_VERSION)); + entry.pushKV("size", tx.GetTotalSize()); entry.pushKV("vsize", (GetTransactionWeight(tx) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR); entry.pushKV("weight", GetTransactionWeight(tx)); // ELEMENTS: add discountvsize @@ -422,6 +426,6 @@ void TxToUniv(const CTransaction& tx, const uint256& block_hash, UniValue& entry } if (include_hex) { - entry.pushKV("hex", EncodeHexTx(tx, serialize_flags)); // The hex-encoded transaction. Used the name "hex" to be consistent with the verbose output of "getrawtransaction". + entry.pushKV("hex", EncodeHexTx(tx, without_witness)); // The hex-encoded transaction. Used the name "hex" to be consistent with the verbose output of "getrawtransaction". } } diff --git a/src/external_signer.cpp b/src/external_signer.cpp index 102c58b56a..d5b646d77a 100644 --- a/src/external_signer.cpp +++ b/src/external_signer.cpp @@ -72,8 +72,8 @@ UniValue ExternalSigner::GetDescriptors(const int account) bool ExternalSigner::SignTransaction(PartiallySignedTransaction& psbtx, std::string& error) { // Serialize the PSBT - CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); - ssTx << psbtx; + DataStream ssTx{}; + ssTx << TX_WITH_WITNESS(psbtx); // parse ExternalSigner master fingerprint std::vector parsed_m_fingerprint = ParseHex(m_fingerprint); // Check if signer fingerprint matches any input master key fingerprint diff --git a/src/hash.h b/src/hash.h index d355b703ff..132e1a9fb3 100644 --- a/src/hash.h +++ b/src/hash.h @@ -146,23 +146,6 @@ public: } }; -class CHashWriter : public HashWriter -{ -private: - const int nVersion; - -public: - CHashWriter(int nVersionIn) : nVersion{nVersionIn} {} - - int GetVersion() const { return nVersion; } - - template - CHashWriter& operator<<(const T& obj) { - ::Serialize(*this, obj); - return (*this); - } -}; - /** Reads data from an underlying stream, while hashing the read data. */ template class HashVerifier : public HashWriter diff --git a/src/index/txindex.cpp b/src/index/txindex.cpp index 67688e6372..92d1b6e443 100644 --- a/src/index/txindex.cpp +++ b/src/index/txindex.cpp @@ -66,7 +66,7 @@ bool TxIndex::CustomAppend(const interfaces::BlockInfo& block) vPos.reserve(block.data->vtx.size()); for (const auto& tx : block.data->vtx) { vPos.emplace_back(tx->GetHash(), pos); - pos.nTxOffset += ::GetSerializeSize(*tx, CLIENT_VERSION); + pos.nTxOffset += ::GetSerializeSize(TX_WITH_WITNESS(*tx)); } return m_db->WriteTxs(vPos); } @@ -86,11 +86,11 @@ bool TxIndex::FindTx(const uint256& tx_hash, uint256& block_hash, CTransactionRe } CBlockHeader header; try { - file >> header; + file >> TX_WITH_WITNESS(header); if (fseek(file.Get(), postx.nTxOffset, SEEK_CUR)) { return error("%s: fseek(...) failed", __func__); } - file >> tx; + file >> TX_WITH_WITNESS(tx); } catch (const std::exception& e) { return error("%s: Deserialize or I/O error - %s", __func__, e.what()); } diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index ffd4d992b3..90a897eabb 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -337,7 +337,7 @@ public: virtual void rpcRunLater(const std::string& name, std::function fn, int64_t seconds) = 0; //! Current RPC serialization flags. - virtual int rpcSerializationFlags() = 0; + virtual bool rpcSerializationWithoutWitness() = 0; //! Get settings value. virtual common::SettingsValue getSetting(const std::string& arg) = 0; diff --git a/src/issuance.cpp b/src/issuance.cpp index b18d5d21ef..2f2163c3dd 100644 --- a/src/issuance.cpp +++ b/src/issuance.cpp @@ -28,7 +28,7 @@ void GenerateAssetEntropy(uint256& entropy, const COutPoint& prevout, const uint // E = H( H(I) || H(C) ) std::vector leaves; leaves.reserve(2); - leaves.push_back((CHashWriter{0} << prevout).GetHash()); + leaves.push_back((HashWriter{} << prevout).GetHash()); leaves.push_back(contracthash); entropy = ComputeFastMerkleRoot(leaves); } diff --git a/src/kernel/mempool_persist.cpp b/src/kernel/mempool_persist.cpp index 4087308d1a..0808d42452 100644 --- a/src/kernel/mempool_persist.cpp +++ b/src/kernel/mempool_persist.cpp @@ -42,7 +42,7 @@ bool LoadMempool(CTxMemPool& pool, const fs::path& load_path, Chainstate& active { if (load_path.empty()) return false; - CAutoFile file{opts.mockable_fopen_function(load_path, "rb"), CLIENT_VERSION}; + AutoFile file{opts.mockable_fopen_function(load_path, "rb")}; if (file.IsNull()) { LogPrintf("Failed to open mempool file from disk. Continuing anyway.\n"); return false; @@ -74,7 +74,7 @@ bool LoadMempool(CTxMemPool& pool, const fs::path& load_path, Chainstate& active CTransactionRef tx; int64_t nTime; int64_t nFeeDelta; - file >> tx; + file >> TX_WITH_WITNESS(tx); file >> nTime; file >> nFeeDelta; @@ -158,7 +158,7 @@ bool DumpMempool(const CTxMemPool& pool, const fs::path& dump_path, FopenFn mock auto mid = SteadyClock::now(); - CAutoFile file{mockable_fopen_function(dump_path + ".new", "wb"), CLIENT_VERSION}; + AutoFile file{mockable_fopen_function(dump_path + ".new", "wb")}; if (file.IsNull()) { return false; } @@ -176,7 +176,7 @@ bool DumpMempool(const CTxMemPool& pool, const fs::path& dump_path, FopenFn mock file << (uint64_t)vinfo.size(); for (const auto& i : vinfo) { - file << *(i.tx); + file << TX_WITH_WITNESS(*(i.tx)); file << int64_t{count_seconds(i.m_time)}; file << int64_t{i.nFeeDelta}; mapDeltas.erase(i.tx->GetHash()); diff --git a/src/net_processing.cpp b/src/net_processing.cpp index b97df603a3..cf3e5b8100 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -2312,9 +2312,9 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv& } if (pblock) { if (inv.IsMsgBlk()) { - m_connman.PushMessage(&pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, *pblock)); + m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::BLOCK, TX_NO_WITNESS(*pblock))); } else if (inv.IsMsgWitnessBlk()) { - m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::BLOCK, *pblock)); + m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::BLOCK, TX_WITH_WITNESS(*pblock))); } else if (inv.IsMsgFilteredBlk()) { bool sendMerkleBlock = false; CMerkleBlock merkleBlock; @@ -2335,7 +2335,7 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv& // however we MUST always provide at least what the remote peer needs typedef std::pair PairType; for (PairType& pair : merkleBlock.vMatchedTxn) - m_connman.PushMessage(&pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::TX, *pblock->vtx[pair.first])); + m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::TX, TX_NO_WITNESS(*pblock->vtx[pair.first]))); } // else // no response @@ -2352,7 +2352,7 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv& m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::CMPCTBLOCK, cmpctblock)); } } else { - m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::BLOCK, *pblock)); + m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::BLOCK, TX_WITH_WITNESS(*pblock))); } } } @@ -2422,8 +2422,8 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic CTransactionRef tx = FindTxForGetData(*tx_relay, ToGenTxid(inv)); if (tx) { // WTX and WITNESS_TX imply we serialize with witness - int nSendFlags = (inv.IsMsgTx() ? SERIALIZE_TRANSACTION_NO_WITNESS : 0); - m_connman.PushMessage(&pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *tx)); + const auto maybe_with_witness = (inv.IsMsgTx() ? TX_NO_WITNESS : TX_WITH_WITNESS); + m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::TX, maybe_with_witness(*tx))); m_mempool.RemoveUnbroadcastTx(tx->GetHash()); } else { vNotFound.push_back(inv); @@ -4170,7 +4170,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type, LogPrint(BCLog::NET, "Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.GetId()); // Just respond with an empty headers message, to tell the peer to // go away but not treat us as unresponsive. - m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::HEADERS, std::vector())); + m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::HEADERS, std::vector())); return; } @@ -4228,7 +4228,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type, // will re-announce the new block via headers (or compact blocks again) // in the SendMessages logic. nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.ActiveChain().Tip(); - m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::HEADERS, vHeaders)); + m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::HEADERS, TX_WITH_WITNESS(vHeaders))); return; } @@ -4245,7 +4245,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type, if (m_chainman.IsInitialBlockDownload()) return; CTransactionRef ptx; - vRecv >> ptx; + vRecv >> TX_WITH_WITNESS(ptx); const CTransaction& tx = *ptx; const uint256& txid = ptx->GetHash(); @@ -4440,7 +4440,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type, } CBlockHeaderAndShortTxIDs cmpctblock; - vRecv >> cmpctblock; + vRecv >> TX_WITH_WITNESS(cmpctblock); bool received_new_header = false; const auto blockhash = cmpctblock.header.GetHash(); @@ -4721,7 +4721,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type, } headers.resize(nCount); for (unsigned int n = 0; n < nCount; n++) { - vRecv >> headers[n]; + vRecv >> TX_WITH_WITNESS(headers[n]); ReadCompactSize(vRecv); // ignore tx count; assume it is 0. } @@ -4753,7 +4753,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type, } std::shared_ptr pblock = std::make_shared(); - vRecv >> *pblock; + vRecv >> TX_WITH_WITNESS(*pblock); LogPrint(BCLog::NET, "received block %s peer=%d\n", pblock->GetHash().ToString(), pfrom.GetId()); @@ -5777,7 +5777,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto) LogPrint(BCLog::NET, "%s: sending header %s to peer=%d\n", __func__, vHeaders.front().GetHash().ToString(), pto->GetId()); } - m_connman.PushMessage(pto, msgMaker.Make(NetMsgType::HEADERS, vHeaders)); + m_connman.PushMessage(pto, msgMaker.Make(NetMsgType::HEADERS, TX_WITH_WITNESS(vHeaders))); state.pindexBestHeaderSent = pBestIndex; } else fRevertToInv = true; diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index 3a499e2e39..e4f10e8826 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -1049,7 +1049,7 @@ bool BlockManager::WriteBlockToDisk(const CBlock& block, FlatFilePos& pos) const } // Write index header - unsigned int nSize = GetSerializeSize(block, fileout.GetVersion()); + unsigned int nSize = GetSerializeSize(TX_WITH_WITNESS(block)); fileout << GetParams().MessageStart() << nSize; // Write block @@ -1057,7 +1057,7 @@ bool BlockManager::WriteBlockToDisk(const CBlock& block, FlatFilePos& pos) const if (fileOutPos < 0) return error("WriteBlockToDisk: ftell failed"); pos.nPos = (unsigned int)fileOutPos; - fileout << block; + fileout << TX_WITH_WITNESS(block); return true; } @@ -1115,9 +1115,8 @@ bool BlockManager::ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos) cons // Read block try { - filein >> block; - } - catch (const std::exception& e) { + filein >> TX_WITH_WITNESS(block); + } catch (const std::exception& e) { return error("%s: Deserialize or I/O error - %s at %s", __func__, e.what(), pos.ToString()); } @@ -1187,7 +1186,7 @@ bool BlockManager::ReadRawBlockFromDisk(std::vector& block, const FlatF FlatFilePos BlockManager::SaveBlockToDisk(const CBlock& block, int nHeight, const FlatFilePos* dbp) { - unsigned int nBlockSize = ::GetSerializeSize(block, CLIENT_VERSION); + unsigned int nBlockSize = ::GetSerializeSize(TX_WITH_WITNESS(block)); FlatFilePos blockPos; const auto position_known {dbp != nullptr}; if (position_known) { diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index 153cee6205..c43d5221ec 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -777,7 +777,7 @@ public: { RPCRunLater(name, std::move(fn), seconds); } - int rpcSerializationFlags() override { return RPCSerializationFlags(); } + bool rpcSerializationWithoutWitness() override { return RPCSerializationWithoutWitness(); } common::SettingsValue getSetting(const std::string& name) override { return args().GetSetting(name); diff --git a/src/pegins.cpp b/src/pegins.cpp index 8a4a3e3fc9..768f8a1d17 100644 --- a/src/pegins.cpp +++ b/src/pegins.cpp @@ -145,8 +145,8 @@ template static bool CheckPeginTx(const std::vector& tx_data, T& pegtx, const COutPoint& prevout, const CAmount claim_amount, const CScript& claim_script, const std::vector>& fedpegscripts) { try { - CDataStream pegtx_stream(tx_data, SER_NETWORK, PROTOCOL_VERSION); - pegtx_stream >> pegtx; + DataStream pegtx_stream(tx_data); + pegtx_stream >> TX_WITH_WITNESS(pegtx); if (!pegtx_stream.empty()) { return false; } @@ -202,8 +202,8 @@ static bool GetBlockAndTxFromMerkleBlock(uint256& block_hash, uint256& tx_hash, try { std::vector tx_hashes; std::vector tx_indices; - CDataStream merkle_block_stream(merkle_block_raw, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS); - merkle_block_stream >> merkle_block; + CDataStream merkle_block_stream(merkle_block_raw, SER_NETWORK, PROTOCOL_VERSION); + merkle_block_stream >> TX_NO_WITNESS(merkle_block); block_hash = merkle_block.header.GetHash(); if (!merkle_block_stream.empty()) { @@ -514,14 +514,14 @@ CScriptWitness CreatePeginWitnessInner(const CAmount& value, const CAsset& asset } // Strip witness data for proof inclusion since only TXID-covered fields matters - CDataStream ss_tx(SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS); - ss_tx << tx_ref; + CDataStream ss_tx(SER_NETWORK, PROTOCOL_VERSION); + ss_tx << TX_NO_WITNESS(tx_ref); const auto* ss_tx_ptr = UCharCast(ss_tx.data()); std::vector tx_data_stripped(ss_tx_ptr, ss_tx_ptr + ss_tx.size()); // Serialize merkle block - CDataStream ss_txout_proof(SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS); - ss_txout_proof << merkle_block; + CDataStream ss_txout_proof(SER_NETWORK, PROTOCOL_VERSION); + ss_txout_proof << TX_NO_WITNESS(merkle_block); const auto* ss_txout_ptr = UCharCast(ss_txout_proof.data()); std::vector txout_proof_bytes(ss_txout_ptr, ss_txout_ptr + ss_txout_proof.size()); @@ -564,25 +564,25 @@ bool DecomposePeginWitness(const CScriptWitness& witness, CAmount& value, CAsset CScript s(stack[3].begin(), stack[3].end()); claim_script = s; - CDataStream ss_tx(stack[4], SER_NETWORK, PROTOCOL_VERSION); + DataStream ss_tx(stack[4]); if (Params().GetConsensus().ParentChainHasPow()) { Sidechain::Bitcoin::CTransactionRef btc_tx; - ss_tx >> btc_tx; + ss_tx >> TX_WITH_WITNESS(btc_tx); tx = btc_tx; } else { CTransactionRef elem_tx; - ss_tx >> elem_tx; + ss_tx >> TX_WITH_WITNESS(elem_tx); tx = elem_tx; } - CDataStream ss_proof(stack[5], SER_NETWORK, PROTOCOL_VERSION); + DataStream ss_proof(stack[5]); if (Params().GetConsensus().ParentChainHasPow()) { Sidechain::Bitcoin::CMerkleBlock tx_proof; - ss_proof >> tx_proof; + ss_proof >> TX_WITH_WITNESS(tx_proof); merkle_block = tx_proof; } else { CMerkleBlock tx_proof; - ss_proof >> tx_proof; + ss_proof >> TX_WITH_WITNESS(tx_proof); merkle_block = tx_proof; } diff --git a/src/policy/discount.h b/src/policy/discount.h index 9f087f62c9..a1a2d117f5 100644 --- a/src/policy/discount.h +++ b/src/policy/discount.h @@ -16,7 +16,7 @@ */ static inline int64_t GetDiscountTransactionWeight(const CTransaction& tx, int64_t nSigOpCost = 0, unsigned int bytes_per_sig_op = 0) { - int64_t size_bytes = ::GetSerializeSize(tx, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(tx, PROTOCOL_VERSION); + int64_t size_bytes = ::GetSerializeSize(TX_NO_WITNESS(tx)) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(TX_WITH_WITNESS(tx)); int64_t sigop_bytes = nSigOpCost * bytes_per_sig_op; int64_t weight = std::max(size_bytes, sigop_bytes); @@ -25,7 +25,7 @@ static inline int64_t GetDiscountTransactionWeight(const CTransaction& tx, int64 const CTxOut& output = tx.vout[i]; if (i < tx.witness.vtxoutwit.size()) { // subtract the weight of the output witness, except the 2 bytes used to serialize the empty proofs - size_t witness_size = ::GetSerializeSize(tx.witness.vtxoutwit[i], PROTOCOL_VERSION); + size_t witness_size = ::GetSerializeSize(tx.witness.vtxoutwit[i]); assert(witness_size >= 2); weight -= (witness_size - 2); } diff --git a/src/primitives/bitcoin/block.cpp b/src/primitives/bitcoin/block.cpp index 0175dccecc..0092a4a006 100644 --- a/src/primitives/bitcoin/block.cpp +++ b/src/primitives/bitcoin/block.cpp @@ -15,7 +15,7 @@ namespace Bitcoin { uint256 CBlockHeader::GetHash() const { - return (CHashWriter{PROTOCOL_VERSION} << *this).GetHash(); + return (HashWriter{} << *this).GetHash(); } std::string CBlock::ToString() const diff --git a/src/primitives/bitcoin/transaction.cpp b/src/primitives/bitcoin/transaction.cpp index 4f6a37b520..2a98d1dfdb 100644 --- a/src/primitives/bitcoin/transaction.cpp +++ b/src/primitives/bitcoin/transaction.cpp @@ -64,20 +64,21 @@ CMutableTransaction::CMutableTransaction(const CTransaction& tx) : vin(tx.vin), uint256 CMutableTransaction::GetHash() const { - return (CHashWriter{SERIALIZE_TRANSACTION_NO_WITNESS} << *this).GetHash(); + return Txid::FromUint256((HashWriter{} << TX_NO_WITNESS(*this)).GetHash()); } uint256 CTransaction::ComputeHash() const { - return (CHashWriter{SERIALIZE_TRANSACTION_NO_WITNESS} << *this).GetHash(); + return Txid::FromUint256((HashWriter{} << TX_NO_WITNESS(*this)).GetHash()); } uint256 CTransaction::ComputeWitnessHash() const { if (!HasWitness()) { - return hash; + return Wtxid::FromUint256(hash); } - return (CHashWriter{0} << *this).GetHash(); + + return Wtxid::FromUint256((HashWriter{} << TX_WITH_WITNESS(*this)).GetHash()); } /* For backward compatibility, the hash is initialized to 0. TODO: remove the need for this default constructor entirely. */ @@ -99,7 +100,7 @@ CAmount CTransaction::GetValueOut() const unsigned int CTransaction::GetTotalSize() const { - return ::GetSerializeSize(*this, PROTOCOL_VERSION); + return ::GetSerializeSize(TX_WITH_WITNESS(*this)); } std::string CTransaction::ToString() const diff --git a/src/primitives/bitcoin/transaction.h b/src/primitives/bitcoin/transaction.h index b29f7d971f..f9dbed7727 100644 --- a/src/primitives/bitcoin/transaction.h +++ b/src/primitives/bitcoin/transaction.h @@ -11,6 +11,7 @@ #include