diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp index 947f605d8e6..3f61a122e67 100644 --- a/src/blockencodings.cpp +++ b/src/blockencodings.cpp @@ -42,7 +42,7 @@ void CBlockHeaderAndShortTxIDs::FillShortTxIDSelector() const { uint64_t CBlockHeaderAndShortTxIDs::GetShortID(const Wtxid& wtxid) const { static_assert(SHORTTXIDS_LENGTH == 6, "shorttxids calculation assumes 6-byte shorttxids"); - return SipHashUint256(shorttxidk0, shorttxidk1, wtxid) & 0xffffffffffffL; + return SipHashUint256(shorttxidk0, shorttxidk1, wtxid.ToUint256()) & 0xffffffffffffL; } ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& cmpctblock, const std::vector& extra_txn) { diff --git a/src/consensus/merkle.cpp b/src/consensus/merkle.cpp index 7dd24e1868f..e274ed821a5 100644 --- a/src/consensus/merkle.cpp +++ b/src/consensus/merkle.cpp @@ -68,7 +68,7 @@ uint256 BlockMerkleRoot(const CBlock& block, bool* mutated) std::vector leaves; leaves.resize(block.vtx.size()); for (size_t s = 0; s < block.vtx.size(); s++) { - leaves[s] = block.vtx[s]->GetHash(); + leaves[s] = block.vtx[s]->GetHash().ToUint256(); } return ComputeMerkleRoot(std::move(leaves), mutated); } @@ -79,7 +79,7 @@ uint256 BlockWitnessMerkleRoot(const CBlock& block, bool* mutated) leaves.resize(block.vtx.size()); leaves[0].SetNull(); // The witness hash of the coinbase is 0. for (size_t s = 1; s < block.vtx.size(); s++) { - leaves[s] = block.vtx[s]->GetWitnessHash(); + leaves[s] = block.vtx[s]->GetWitnessHash().ToUint256(); } return ComputeMerkleRoot(std::move(leaves), mutated); } @@ -185,7 +185,7 @@ std::vector TransactionMerklePath(const CBlock& block, uint32_t positio std::vector leaves; leaves.resize(block.vtx.size()); for (size_t s = 0; s < block.vtx.size(); s++) { - leaves[s] = block.vtx[s]->GetHash(); + leaves[s] = block.vtx[s]->GetHash().ToUint256(); } return ComputeMerklePath(leaves, position); } diff --git a/src/headerssync.cpp b/src/headerssync.cpp index 9e8b1905168..fbe2026ecae 100644 --- a/src/headerssync.cpp +++ b/src/headerssync.cpp @@ -48,7 +48,7 @@ HeadersSyncState::HeadersSyncState(NodeId id, const Consensus::Params& consensus /** Free any memory in use, and mark this object as no longer usable. This is * required to guarantee that we won't reuse this object with the same - * SaltedTxidHasher for another sync. */ + * SaltedUint256Hasher for another sync. */ void HeadersSyncState::Finalize() { Assume(m_download_state != State::FINAL); diff --git a/src/headerssync.h b/src/headerssync.h index 2e7017f115d..56380c66fe2 100644 --- a/src/headerssync.h +++ b/src/headerssync.h @@ -224,7 +224,7 @@ private: arith_uint256 m_current_chain_work; /** m_hasher is a salted hasher for making our 1-bit commitments to headers we've seen. */ - const SaltedTxidHasher m_hasher; + const SaltedUint256Hasher m_hasher; /** A queue of commitment bits, created during the 1st phase, and verified during the 2nd. */ bitdeque<> m_header_commitments; diff --git a/src/index/txindex.cpp b/src/index/txindex.cpp index 4bb6dc74447..2a7c0066b08 100644 --- a/src/index/txindex.cpp +++ b/src/index/txindex.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include constexpr uint8_t DB_TXINDEX{'t'}; @@ -24,26 +25,26 @@ public: /// Read the disk location of the transaction data with the given hash. Returns false if the /// transaction hash is not indexed. - bool ReadTxPos(const uint256& txid, CDiskTxPos& pos) const; + bool ReadTxPos(const Txid& txid, CDiskTxPos& pos) const; /// Write a batch of transaction positions to the DB. - [[nodiscard]] bool WriteTxs(const std::vector>& v_pos); + [[nodiscard]] bool WriteTxs(const std::vector>& v_pos); }; TxIndex::DB::DB(size_t n_cache_size, bool f_memory, bool f_wipe) : BaseIndex::DB(gArgs.GetDataDirNet() / "indexes" / "txindex", n_cache_size, f_memory, f_wipe) {} -bool TxIndex::DB::ReadTxPos(const uint256 &txid, CDiskTxPos& pos) const +bool TxIndex::DB::ReadTxPos(const Txid& txid, CDiskTxPos& pos) const { - return Read(std::make_pair(DB_TXINDEX, txid), pos); + return Read(std::make_pair(DB_TXINDEX, txid.ToUint256()), pos); } -bool TxIndex::DB::WriteTxs(const std::vector>& v_pos) +bool TxIndex::DB::WriteTxs(const std::vector>& v_pos) { CDBBatch batch(*this); - for (const auto& tuple : v_pos) { - batch.Write(std::make_pair(DB_TXINDEX, tuple.first), tuple.second); + for (const auto& [txid, pos] : v_pos) { + batch.Write(std::make_pair(DB_TXINDEX, txid.ToUint256()), pos); } return WriteBatch(batch); } @@ -61,7 +62,7 @@ bool TxIndex::CustomAppend(const interfaces::BlockInfo& block) assert(block.data); CDiskTxPos pos({block.file_number, block.data_pos}, GetSizeOfCompactSize(block.data->vtx.size())); - std::vector> vPos; + std::vector> vPos; vPos.reserve(block.data->vtx.size()); for (const auto& tx : block.data->vtx) { vPos.emplace_back(tx->GetHash(), pos); @@ -72,7 +73,7 @@ bool TxIndex::CustomAppend(const interfaces::BlockInfo& block) BaseIndex::DB& TxIndex::GetDB() const { return *m_db; } -bool TxIndex::FindTx(const uint256& tx_hash, uint256& block_hash, CTransactionRef& tx) const +bool TxIndex::FindTx(const Txid& tx_hash, uint256& block_hash, CTransactionRef& tx) const { CDiskTxPos postx; if (!m_db->ReadTxPos(tx_hash, postx)) { diff --git a/src/index/txindex.h b/src/index/txindex.h index ef835fe5d7d..f8236c92844 100644 --- a/src/index/txindex.h +++ b/src/index/txindex.h @@ -42,7 +42,7 @@ public: /// @param[out] block_hash The hash of the block the transaction is found in. /// @param[out] tx The transaction itself. /// @return true if transaction is found, false otherwise - bool FindTx(const uint256& tx_hash, uint256& block_hash, CTransactionRef& tx) const; + bool FindTx(const Txid& tx_hash, uint256& block_hash, CTransactionRef& tx) const; }; /// The global transaction index, used in GetTransaction. May be null. diff --git a/src/kernel/coinstats.cpp b/src/kernel/coinstats.cpp index 81c496ab342..6270f365f4e 100644 --- a/src/kernel/coinstats.cpp +++ b/src/kernel/coinstats.cpp @@ -98,7 +98,7 @@ static void ApplyHash(T& hash_obj, const Txid& hash, const std::map& outputs) +static void ApplyStats(CCoinsStats& stats, const std::map& outputs) { assert(!outputs.empty()); stats.nTransactions++; @@ -126,7 +126,7 @@ static bool ComputeUTXOStats(CCoinsView* view, CCoinsStats& stats, T hash_obj, c Coin coin; if (pcursor->GetKey(key) && pcursor->GetValue(coin)) { if (!outputs.empty() && key.hash != prevkey) { - ApplyStats(stats, prevkey, outputs); + ApplyStats(stats, outputs); ApplyHash(hash_obj, prevkey, outputs); outputs.clear(); } @@ -140,7 +140,7 @@ static bool ComputeUTXOStats(CCoinsView* view, CCoinsStats& stats, T hash_obj, c pcursor->Next(); } if (!outputs.empty()) { - ApplyStats(stats, prevkey, outputs); + ApplyStats(stats, outputs); ApplyHash(hash_obj, prevkey, outputs); } diff --git a/src/kernel/disconnected_transactions.h b/src/kernel/disconnected_transactions.h index 401ec435e6b..bc098f71aaf 100644 --- a/src/kernel/disconnected_transactions.h +++ b/src/kernel/disconnected_transactions.h @@ -41,7 +41,7 @@ private: const size_t m_max_mem_usage; std::list queuedTx; using TxList = decltype(queuedTx); - std::unordered_map iters_by_txid; + std::unordered_map iters_by_txid; /** Trim the earliest-added entries until we are within memory bounds. */ std::vector LimitMemoryUsage(); diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 546e14b8bce..810627a14e7 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -3030,7 +3030,7 @@ std::optional PeerManagerImpl::ProcessInvalidTx(NodeId AddToCompactExtraTransactions(ptx); } for (const Txid& parent_txid : unique_parents) { - if (peer) AddKnownTx(*peer, parent_txid); + if (peer) AddKnownTx(*peer, parent_txid.ToUint256()); } MaybePunishNodeForTx(nodeid, state); @@ -4280,12 +4280,11 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type, CTransactionRef ptx; vRecv >> TX_WITH_WITNESS(ptx); - const CTransaction& tx = *ptx; - const uint256& txid = ptx->GetHash(); - const uint256& wtxid = ptx->GetWitnessHash(); + const Txid& txid = ptx->GetHash(); + const Wtxid& wtxid = ptx->GetWitnessHash(); - const uint256& hash = peer->m_wtxid_relay ? wtxid : txid; + const uint256& hash = peer->m_wtxid_relay ? wtxid.ToUint256() : txid.ToUint256(); AddKnownTx(*peer, hash); LOCK2(cs_main, m_tx_download_mutex); @@ -4296,13 +4295,13 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type, // Always relay transactions received from peers with forcerelay // permission, even if they were already in the mempool, allowing // the node to function as a gateway for nodes hidden behind it. - if (!m_mempool.exists(tx.GetHash())) { + if (!m_mempool.exists(txid)) { LogPrintf("Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n", - tx.GetHash().ToString(), tx.GetWitnessHash().ToString(), pfrom.GetId()); + txid.ToString(), wtxid.ToString(), pfrom.GetId()); } else { LogPrintf("Force relaying tx %s (wtxid=%s) from peer=%d\n", - tx.GetHash().ToString(), tx.GetWitnessHash().ToString(), pfrom.GetId()); - RelayTransaction(tx.GetHash(), tx.GetWitnessHash()); + txid.ToString(), wtxid.ToString(), pfrom.GetId()); + RelayTransaction(txid, wtxid); } } diff --git a/src/node/txdownloadman_impl.cpp b/src/node/txdownloadman_impl.cpp index 0105fe3d609..91bc7f3bcbd 100644 --- a/src/node/txdownloadman_impl.cpp +++ b/src/node/txdownloadman_impl.cpp @@ -104,8 +104,8 @@ void TxDownloadManagerImpl::BlockConnected(const std::shared_ptr& if (ptx->HasWitness()) { RecentConfirmedTransactionsFilter().insert(ptx->GetWitnessHash().ToUint256()); } - m_txrequest.ForgetTxHash(ptx->GetHash()); - m_txrequest.ForgetTxHash(ptx->GetWitnessHash()); + m_txrequest.ForgetTxHash(ptx->GetHash().ToUint256()); + m_txrequest.ForgetTxHash(ptx->GetWitnessHash().ToUint256()); } } @@ -324,8 +324,8 @@ void TxDownloadManagerImpl::MempoolAcceptedTx(const CTransactionRef& tx) { // As this version of the transaction was acceptable, we can forget about any requests for it. // No-op if the tx is not in txrequest. - m_txrequest.ForgetTxHash(tx->GetHash()); - m_txrequest.ForgetTxHash(tx->GetWitnessHash()); + m_txrequest.ForgetTxHash(tx->GetHash().ToUint256()); + m_txrequest.ForgetTxHash(tx->GetWitnessHash().ToUint256()); m_orphanage->AddChildrenToWorkSet(*tx, m_opts.m_rng); // If it came from the orphanage, remove it. No-op if the tx is not in txorphanage. @@ -406,8 +406,8 @@ node::RejectedTxTodo TxDownloadManagerImpl::MempoolRejectedTx(const CTransaction // // Search by txid and, if the tx has a witness, wtxid std::vector orphan_resolution_candidates{nodeid}; - m_txrequest.GetCandidatePeers(ptx->GetHash(), orphan_resolution_candidates); - if (ptx->HasWitness()) m_txrequest.GetCandidatePeers(ptx->GetWitnessHash(), orphan_resolution_candidates); + m_txrequest.GetCandidatePeers(ptx->GetHash().ToUint256(), orphan_resolution_candidates); + if (ptx->HasWitness()) m_txrequest.GetCandidatePeers(ptx->GetWitnessHash().ToUint256(), orphan_resolution_candidates); for (const auto& nodeid : orphan_resolution_candidates) { if (MaybeAddOrphanResolutionCandidate(unique_parents, ptx->GetWitnessHash(), nodeid, now)) { @@ -416,8 +416,8 @@ node::RejectedTxTodo TxDownloadManagerImpl::MempoolRejectedTx(const CTransaction } // Once added to the orphan pool, a tx is considered AlreadyHave, and we shouldn't request it anymore. - m_txrequest.ForgetTxHash(tx.GetHash()); - m_txrequest.ForgetTxHash(tx.GetWitnessHash()); + m_txrequest.ForgetTxHash(tx.GetHash().ToUint256()); + m_txrequest.ForgetTxHash(tx.GetWitnessHash().ToUint256()); } else { unique_parents.clear(); LogDebug(BCLog::MEMPOOL, "not keeping orphan with rejected parents %s (wtxid=%s)\n", @@ -431,8 +431,8 @@ node::RejectedTxTodo TxDownloadManagerImpl::MempoolRejectedTx(const CTransaction // from any of our non-wtxidrelay peers. RecentRejectsFilter().insert(tx.GetHash().ToUint256()); RecentRejectsFilter().insert(tx.GetWitnessHash().ToUint256()); - m_txrequest.ForgetTxHash(tx.GetHash()); - m_txrequest.ForgetTxHash(tx.GetWitnessHash()); + m_txrequest.ForgetTxHash(tx.GetHash().ToUint256()); + m_txrequest.ForgetTxHash(tx.GetWitnessHash().ToUint256()); } } } else if (state.GetResult() == TxValidationResult::TX_WITNESS_STRIPPED) { @@ -467,7 +467,7 @@ node::RejectedTxTodo TxDownloadManagerImpl::MempoolRejectedTx(const CTransaction } else { RecentRejectsFilter().insert(ptx->GetWitnessHash().ToUint256()); } - m_txrequest.ForgetTxHash(ptx->GetWitnessHash()); + m_txrequest.ForgetTxHash(ptx->GetWitnessHash().ToUint256()); // If the transaction failed for TX_INPUTS_NOT_STANDARD, // then we know that the witness was irrelevant to the policy // failure, since this check depends only on the txid @@ -480,7 +480,7 @@ node::RejectedTxTodo TxDownloadManagerImpl::MempoolRejectedTx(const CTransaction // rolling bloom filter. if (state.GetResult() == TxValidationResult::TX_INPUTS_NOT_STANDARD && ptx->HasWitness()) { RecentRejectsFilter().insert(ptx->GetHash().ToUint256()); - m_txrequest.ForgetTxHash(ptx->GetHash()); + m_txrequest.ForgetTxHash(ptx->GetHash().ToUint256()); } } @@ -508,8 +508,8 @@ std::pair> TxDownloadManagerImpl::Receive const Wtxid& wtxid = ptx->GetWitnessHash(); // Mark that we have received a response - m_txrequest.ReceivedResponse(nodeid, txid); - if (ptx->HasWitness()) m_txrequest.ReceivedResponse(nodeid, wtxid); + m_txrequest.ReceivedResponse(nodeid, txid.ToUint256()); + if (ptx->HasWitness()) m_txrequest.ReceivedResponse(nodeid, wtxid.ToUint256()); // First check if we should drop this tx. // We do the AlreadyHaveTx() check using wtxid, rather than txid - in the diff --git a/src/signet.cpp b/src/signet.cpp index 45d279d2bf0..742d03d9178 100644 --- a/src/signet.cpp +++ b/src/signet.cpp @@ -59,9 +59,9 @@ static uint256 ComputeModifiedMerkleRoot(const CMutableTransaction& cb, const CB { std::vector leaves; leaves.resize(block.vtx.size()); - leaves[0] = cb.GetHash(); + leaves[0] = cb.GetHash().ToUint256(); for (size_t s = 1; s < block.vtx.size(); ++s) { - leaves[s] = block.vtx[s]->GetHash(); + leaves[s] = block.vtx[s]->GetHash().ToUint256(); } return ComputeMerkleRoot(std::move(leaves)); } diff --git a/src/test/disconnected_transactions.cpp b/src/test/disconnected_transactions.cpp index d4dc124b7b1..7897e5f15c0 100644 --- a/src/test/disconnected_transactions.cpp +++ b/src/test/disconnected_transactions.cpp @@ -22,7 +22,7 @@ BOOST_AUTO_TEST_CASE(disconnectpool_memory_limits) // is within an expected range. // Overhead for the hashmap depends on number of buckets - std::unordered_map temp_map; + std::unordered_map temp_map; temp_map.reserve(1); const size_t MAP_1{memusage::DynamicUsage(temp_map)}; temp_map.reserve(100); diff --git a/src/test/fuzz/merkle.cpp b/src/test/fuzz/merkle.cpp index 84055ac861c..4bb91faf0b8 100644 --- a/src/test/fuzz/merkle.cpp +++ b/src/test/fuzz/merkle.cpp @@ -19,7 +19,7 @@ uint256 ComputeMerkleRootFromPath(const CBlock& block, uint32_t position, const throw std::out_of_range("Position out of range"); } - uint256 current_hash = block.vtx[position]->GetHash(); + uint256 current_hash = block.vtx[position]->GetHash().ToUint256(); for (const uint256& sibling : merkle_path) { if (position % 2 == 0) { @@ -47,7 +47,7 @@ FUZZ_TARGET(merkle) tx_hashes.reserve(num_txs); for (size_t i = 0; i < num_txs; ++i) { - tx_hashes.push_back(block->vtx[i]->GetHash()); + tx_hashes.push_back(block->vtx[i]->GetHash().ToUint256()); } // Test ComputeMerkleRoot diff --git a/src/test/fuzz/p2p_headers_presync.cpp b/src/test/fuzz/p2p_headers_presync.cpp index a2c3a0f3e62..9aebac30557 100644 --- a/src/test/fuzz/p2p_headers_presync.cpp +++ b/src/test/fuzz/p2p_headers_presync.cpp @@ -139,7 +139,7 @@ CBlock ConsumeBlock(FuzzedDataProvider& fuzzed_data_provider, const uint256& pre tx.vout[0].nValue = 0; tx.vin[0].scriptSig.resize(2); block.vtx.push_back(MakeTransactionRef(tx)); - block.hashMerkleRoot = block.vtx[0]->GetHash(); + block.hashMerkleRoot = block.vtx[0]->GetHash().ToUint256(); return block; } diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp index f8cb0094fc7..cad23321ce9 100644 --- a/src/test/merkle_tests.cpp +++ b/src/test/merkle_tests.cpp @@ -29,7 +29,7 @@ static uint256 BlockBuildMerkleTree(const CBlock& block, bool* fMutated, std::ve vMerkleTree.clear(); vMerkleTree.reserve(block.vtx.size() * 2 + 16); // Safe upper bound for the number of total nodes. for (std::vector::const_iterator it(block.vtx.begin()); it != block.vtx.end(); ++it) - vMerkleTree.push_back((*it)->GetHash()); + vMerkleTree.push_back((*it)->GetHash().ToUint256()); int j = 0; bool mutated = false; for (int nSize = block.vtx.size(); nSize > 1; nSize = (nSize + 1) / 2) @@ -138,7 +138,7 @@ BOOST_AUTO_TEST_CASE(merkle_test) std::vector newBranch = TransactionMerklePath(block, mtx); std::vector oldBranch = BlockGetMerkleBranch(block, merkleTree, mtx); BOOST_CHECK(oldBranch == newBranch); - BOOST_CHECK(ComputeMerkleRootFromBranch(block.vtx[mtx]->GetHash(), newBranch, mtx) == oldRoot); + BOOST_CHECK(ComputeMerkleRootFromBranch(block.vtx[mtx]->GetHash().ToUint256(), newBranch, mtx) == oldRoot); } } } @@ -166,7 +166,7 @@ BOOST_AUTO_TEST_CASE(merkle_test_oneTx_block) mtx.nLockTime = 0; block.vtx[0] = MakeTransactionRef(std::move(mtx)); uint256 root = BlockMerkleRoot(block, &mutated); - BOOST_CHECK_EQUAL(root, block.vtx[0]->GetHash()); + BOOST_CHECK_EQUAL(root, block.vtx[0]->GetHash().ToUint256()); BOOST_CHECK_EQUAL(mutated, false); } @@ -239,7 +239,7 @@ BOOST_AUTO_TEST_CASE(merkle_test_BlockWitness) std::vector hashes; hashes.resize(block.vtx.size()); hashes[0].SetNull(); - hashes[1] = block.vtx[1]->GetHash(); + hashes[1] = block.vtx[1]->GetHash().ToUint256(); uint256 merkleRootofHashes = ComputeMerkleRoot(hashes); diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 76a42d19ea2..0fc7991e570 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -629,3 +629,11 @@ std::ostream& operator<<(std::ostream& os, const uint256& num) { return os << num.ToString(); } + +std::ostream& operator<<(std::ostream& os, const Txid& txid) { + return os << txid.ToString(); +} + +std::ostream& operator<<(std::ostream& os, const Wtxid& wtxid) { + return os << wtxid.ToString(); +} diff --git a/src/test/util/setup_common.h b/src/test/util/setup_common.h index 57bea9086b9..150f50650ba 100644 --- a/src/test/util/setup_common.h +++ b/src/test/util/setup_common.h @@ -291,6 +291,8 @@ inline std::ostream& operator<<(std::ostream& os, const std::optional& v) std::ostream& operator<<(std::ostream& os, const arith_uint256& num); std::ostream& operator<<(std::ostream& os, const uint160& num); std::ostream& operator<<(std::ostream& os, const uint256& num); +std::ostream& operator<<(std::ostream& os, const Txid& txid); +std::ostream& operator<<(std::ostream& os, const Wtxid& wtxid); // @} /** diff --git a/src/test/validation_tests.cpp b/src/test/validation_tests.cpp index 7e86b3a35c1..5d4c3ee1f1d 100644 --- a/src/test/validation_tests.cpp +++ b/src/test/validation_tests.cpp @@ -214,9 +214,9 @@ BOOST_AUTO_TEST_CASE(block_malleation) // Block with a single coinbase tx is mutated if the merkle root is not // equal to the coinbase tx's hash. block.vtx.push_back(create_coinbase_tx()); - BOOST_CHECK(block.vtx[0]->GetHash() != block.hashMerkleRoot); + BOOST_CHECK(block.vtx[0]->GetHash().ToUint256() != block.hashMerkleRoot); BOOST_CHECK(is_mutated(block, /*check_witness_root=*/false)); - block.hashMerkleRoot = block.vtx[0]->GetHash(); + block.hashMerkleRoot = block.vtx[0]->GetHash().ToUint256(); BOOST_CHECK(is_not_mutated(block, /*check_witness_root=*/false)); // Block with two transactions is mutated if the merkle root does not @@ -248,7 +248,7 @@ BOOST_AUTO_TEST_CASE(block_malleation) mtx.vout.resize(1); mtx.vout[0].scriptPubKey.resize(4); block.vtx.push_back(MakeTransactionRef(mtx)); - block.hashMerkleRoot = block.vtx.back()->GetHash(); + block.hashMerkleRoot = block.vtx.back()->GetHash().ToUint256(); assert(block.vtx.back()->IsCoinBase()); assert(GetSerializeSize(TX_NO_WITNESS(block.vtx.back())) == 64); } @@ -285,7 +285,7 @@ BOOST_AUTO_TEST_CASE(block_malleation) HashWriter hasher; hasher.write(tx1.GetHash()); hasher.write(tx2.GetHash()); - assert(hasher.GetHash() == tx3.GetHash()); + assert(hasher.GetHash() == tx3.GetHash().ToUint256()); // Verify that tx3 is 64 bytes in size (without witness). assert(GetSerializeSize(TX_NO_WITNESS(tx3)) == 64); } diff --git a/src/txmempool.h b/src/txmempool.h index 8b55d9cd521..5c81876a361 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -313,7 +313,7 @@ public: boost::multi_index::hashed_unique< boost::multi_index::tag, mempoolentry_wtxid, - SaltedTxidHasher + SaltedWtxidHasher >, // sorted by fee rate boost::multi_index::ordered_non_unique< diff --git a/src/util/hasher.cpp b/src/util/hasher.cpp index 117cfe8dcd1..c4051ae0013 100644 --- a/src/util/hasher.cpp +++ b/src/util/hasher.cpp @@ -7,10 +7,18 @@ #include #include +SaltedUint256Hasher::SaltedUint256Hasher() : + k0{FastRandomContext().rand64()}, + k1{FastRandomContext().rand64()} {} + SaltedTxidHasher::SaltedTxidHasher() : k0{FastRandomContext().rand64()}, k1{FastRandomContext().rand64()} {} +SaltedWtxidHasher::SaltedWtxidHasher() : + k0{FastRandomContext().rand64()}, + k1{FastRandomContext().rand64()} {} + SaltedOutpointHasher::SaltedOutpointHasher(bool deterministic) : k0{deterministic ? 0x8e819f2607a18de6 : FastRandomContext().rand64()}, k1{deterministic ? 0xf4020d2e3983b0eb : FastRandomContext().rand64()} diff --git a/src/util/hasher.h b/src/util/hasher.h index 3a75c91a3ef..be5d9eb13df 100644 --- a/src/util/hasher.h +++ b/src/util/hasher.h @@ -11,9 +11,24 @@ #include #include +#include #include #include +class SaltedUint256Hasher +{ +private: + /** Salt */ + const uint64_t k0, k1; + +public: + SaltedUint256Hasher(); + + size_t operator()(const uint256& hash) const { + return SipHashUint256(k0, k1, hash); + } +}; + class SaltedTxidHasher { private: @@ -23,11 +38,26 @@ private: public: SaltedTxidHasher(); - size_t operator()(const uint256& txid) const { - return SipHashUint256(k0, k1, txid); + size_t operator()(const Txid& txid) const { + return SipHashUint256(k0, k1, txid.ToUint256()); } }; +class SaltedWtxidHasher +{ +private: + /** Salt */ + const uint64_t k0, k1; + +public: + SaltedWtxidHasher(); + + size_t operator()(const Wtxid& wtxid) const { + return SipHashUint256(k0, k1, wtxid.ToUint256()); + } +}; + + class SaltedOutpointHasher { private: @@ -47,7 +77,7 @@ public: * @see https://gcc.gnu.org/onlinedocs/gcc-13.2.0/libstdc++/manual/manual/unordered_associative.html */ size_t operator()(const COutPoint& id) const noexcept { - return SipHashUint256Extra(k0, k1, id.hash, id.n); + return SipHashUint256Extra(k0, k1, id.hash.ToUint256(), id.n); } }; diff --git a/src/validation.cpp b/src/validation.cpp index 0d68475aa6c..91adbdff11f 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1275,7 +1275,7 @@ bool MemPoolAccept::ConsensusScriptChecks(const ATMPArgs& args, Workspace& ws) AssertLockHeld(cs_main); AssertLockHeld(m_pool.cs); const CTransaction& tx = *ws.m_ptx; - const uint256& hash = ws.m_hash; + const Txid& hash = ws.m_hash; TxValidationState& state = ws.m_state; // Check again against the current block tip's script verification @@ -1322,7 +1322,7 @@ void MemPoolAccept::FinalizeSubpackage(const ATMPArgs& args) const bool replaced_with_tx{m_subpackage.m_changeset->GetTxCount() == 1}; if (replaced_with_tx) { const CTransaction& tx = m_subpackage.m_changeset->GetAddedTxn(0); - tx_or_package_hash = tx.GetHash(); + tx_or_package_hash = tx.GetHash().ToUint256(); log_string += strprintf("New tx %s (wtxid=%s, fees=%s, vsize=%s)", tx.GetHash().ToString(), tx.GetWitnessHash().ToString(), diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp index 250377afcfa..4ae34d0bb4c 100644 --- a/src/wallet/spend.cpp +++ b/src/wallet/spend.cpp @@ -327,7 +327,7 @@ CoinsResult AvailableCoins(const CWallet& wallet, std::set trusted_parents; // Cache for whether each tx passes the tx level checks (first bool), and whether the transaction is "safe" (second bool) - std::unordered_map, SaltedTxidHasher> tx_safe_cache; + std::unordered_map, SaltedTxidHasher> tx_safe_cache; for (const auto& [outpoint, txo] : wallet.GetTXOs()) { const CWalletTx& wtx = txo.GetWalletTx(); const CTxOut& output = txo.GetTxOut(); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 91a494c379f..5e7bec48c0b 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2319,7 +2319,7 @@ util::Result CWallet::RemoveTxs(WalletBatch& batch, std::vector& txs for (const auto& txin : it->second.tx->vin) mapTxSpends.erase(txin.prevout); for (unsigned int i = 0; i < it->second.tx->vout.size(); ++i) { - m_txos.erase(COutPoint(Txid::FromUint256(hash), i)); + m_txos.erase(COutPoint(hash, i)); } mapWallet.erase(it); NotifyTransactionChanged(hash, CT_DELETED); diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp index 1e7aa11ce9b..693d70c8437 100644 --- a/src/zmq/zmqpublishnotifier.cpp +++ b/src/zmq/zmqpublishnotifier.cpp @@ -230,7 +230,7 @@ bool CZMQPublishHashBlockNotifier::NotifyBlock(const CBlockIndex *pindex) bool CZMQPublishHashTransactionNotifier::NotifyTransaction(const CTransaction &transaction) { - uint256 hash = transaction.GetHash(); + uint256 hash = transaction.GetHash().ToUint256(); LogDebug(BCLog::ZMQ, "Publish hashtx %s to %s\n", hash.GetHex(), this->address); uint8_t data[32]; for (unsigned int i = 0; i < 32; i++) { @@ -254,7 +254,7 @@ bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex) bool CZMQPublishRawTransactionNotifier::NotifyTransaction(const CTransaction &transaction) { - uint256 hash = transaction.GetHash(); + uint256 hash = transaction.GetHash().ToUint256(); LogDebug(BCLog::ZMQ, "Publish rawtx %s to %s\n", hash.GetHex(), this->address); DataStream ss; ss << TX_WITH_WITNESS(transaction); @@ -290,14 +290,14 @@ bool CZMQPublishSequenceNotifier::NotifyBlockDisconnect(const CBlockIndex *pinde bool CZMQPublishSequenceNotifier::NotifyTransactionAcceptance(const CTransaction &transaction, uint64_t mempool_sequence) { - uint256 hash = transaction.GetHash(); + uint256 hash = transaction.GetHash().ToUint256(); LogDebug(BCLog::ZMQ, "Publish hashtx mempool acceptance %s to %s\n", hash.GetHex(), this->address); return SendSequenceMsg(*this, hash, /* Mempool (A)cceptance */ 'A', mempool_sequence); } bool CZMQPublishSequenceNotifier::NotifyTransactionRemoval(const CTransaction &transaction, uint64_t mempool_sequence) { - uint256 hash = transaction.GetHash(); + uint256 hash = transaction.GetHash().ToUint256(); LogDebug(BCLog::ZMQ, "Publish hashtx mempool removal %s to %s\n", hash.GetHex(), this->address); return SendSequenceMsg(*this, hash, /* Mempool (R)emoval */ 'R', mempool_sequence); }