diff --git a/src/blockfilter.cpp b/src/blockfilter.cpp index 1a65e910c84f..496ec24fd2a5 100644 --- a/src/blockfilter.cpp +++ b/src/blockfilter.cpp @@ -28,7 +28,7 @@ static const std::map g_filter_types = { uint64_t GCSFilter::HashToRange(const Element& element) const { uint64_t hash = CSipHasher(m_params.m_siphash_k0, m_params.m_siphash_k1) - .Write(element.data(), element.size()) + .Write(element) .Finalize(); return FastRange64(hash, m_F); } diff --git a/src/core_io.h b/src/core_io.h index bb05111da5da..1bf88ae23b79 100644 --- a/src/core_io.h +++ b/src/core_io.h @@ -16,6 +16,7 @@ class CBlock; class CBlockHeader; class CScript; class CTransaction; +class SigningProvider; class CTxUndo; class uint256; struct CMutableTransaction; @@ -55,7 +56,7 @@ UniValue ValueFromAmount(const CAmount amount); std::string FormatScript(const CScript& script); std::string EncodeHexTx(const CTransaction& tx); std::string SighashToStr(unsigned char sighash_type); -void ScriptToUniv(const CScript& script, UniValue& out, bool include_hex = true, bool include_address = false); +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, const CSpentIndexTxInfo* ptxSpentInfo = nullptr); // evo/core_write.cpp diff --git a/src/core_write.cpp b/src/core_write.cpp index a3ec9b5643cb..8303cad671c3 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -156,13 +156,13 @@ std::string EncodeHexTx(const CTransaction& tx) return HexStr(ssTx); } -void ScriptToUniv(const CScript& script, UniValue& out, bool include_hex, bool include_address) +void ScriptToUniv(const CScript& script, UniValue& out, bool include_hex, bool include_address, const SigningProvider* provider) { CTxDestination address; out.pushKV("asm", ScriptToAsmStr(script)); if (include_address) { - out.pushKV("desc", InferDescriptor(script, DUMMY_SIGNING_PROVIDER)->ToString()); + out.pushKV("desc", InferDescriptor(script, provider ? *provider : DUMMY_SIGNING_PROVIDER)->ToString()); } if (include_hex) { out.pushKV("hex", HexStr(script)); diff --git a/src/crypto/siphash.cpp b/src/crypto/siphash.cpp index 679ae566696d..8004a0548ecb 100644 --- a/src/crypto/siphash.cpp +++ b/src/crypto/siphash.cpp @@ -45,14 +45,14 @@ CSipHasher& CSipHasher::Write(uint64_t data) return *this; } -CSipHasher& CSipHasher::Write(const unsigned char* data, size_t size) +CSipHasher& CSipHasher::Write(Span data) { uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3]; uint64_t t = tmp; uint8_t c = count; - while (size--) { - t |= ((uint64_t)(*(data++))) << (8 * (c % 8)); + while (data.size() > 0) { + t |= uint64_t{data.front()} << (8 * (c % 8)); c++; if ((c & 7) == 0) { v3 ^= t; @@ -61,6 +61,7 @@ CSipHasher& CSipHasher::Write(const unsigned char* data, size_t size) v0 ^= t; t = 0; } + data = data.subspan(1); } v[0] = v0; diff --git a/src/crypto/siphash.h b/src/crypto/siphash.h index b573526932d5..4fb3dc2f2584 100644 --- a/src/crypto/siphash.h +++ b/src/crypto/siphash.h @@ -7,6 +7,7 @@ #include +#include #include /** SipHash-2-4 */ @@ -26,7 +27,7 @@ class CSipHasher */ CSipHasher& Write(uint64_t data); /** Hash arbitrary bytes. */ - CSipHasher& Write(const unsigned char* data, size_t size); + CSipHasher& Write(Span data); /** Compute the 64-bit SipHash-2-4 of the data written so far. The object remains untouched. */ uint64_t Finalize() const; }; diff --git a/src/llmq/quorums.h b/src/llmq/quorums.h index 2b28f80835ec..80cf0e839d5d 100644 --- a/src/llmq/quorums.h +++ b/src/llmq/quorums.h @@ -235,10 +235,10 @@ struct SaltedHasherImpl static std::size_t CalcHash(const llmq::CQuorumDataRequestKey& v, uint64_t k0, uint64_t k1) { CSipHasher c(k0, k1); - c.Write(reinterpret_cast(&v.proRegTx), sizeof(v.proRegTx)); - c.Write(reinterpret_cast(&v.m_we_requested), sizeof(v.m_we_requested)); - c.Write(reinterpret_cast(&v.quorumHash), sizeof(v.quorumHash)); - c.Write(reinterpret_cast(&v.llmqType), sizeof(v.llmqType)); + c.Write(Span{reinterpret_cast(&v.proRegTx), sizeof(v.proRegTx)}); + c.Write(Span{reinterpret_cast(&v.m_we_requested), sizeof(v.m_we_requested)}); + c.Write(Span{reinterpret_cast(&v.quorumHash), sizeof(v.quorumHash)}); + c.Write(Span{reinterpret_cast(&v.llmqType), sizeof(v.llmqType)}); return c.Finalize(); } }; diff --git a/src/net.cpp b/src/net.cpp index 4e9d3457cb7f..a2828e314b97 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -4267,7 +4267,7 @@ std::vector CConnman::GetAddresses(CNode& requestor, size_t max_addres auto local_socket_bytes = requestor.addrBind.GetAddrBytes(); uint64_t cache_id = GetDeterministicRandomizer(RANDOMIZER_ID_ADDRCACHE) .Write(requestor.ConnectedThroughNetwork()) - .Write(local_socket_bytes.data(), local_socket_bytes.size()) + .Write(local_socket_bytes) // For outbound connections, the port of the bound address is randomly // assigned by the OS and would therefore not be useful for seeding. .Write(requestor.IsInboundConn() ? requestor.addrBind.GetPort() : 0) @@ -4974,7 +4974,7 @@ uint64_t CConnman::CalculateKeyedNetGroup(const CAddress& address) const { std::vector vchNetGroup(m_netgroupman.GetGroup(address)); - return GetDeterministicRandomizer(RANDOMIZER_ID_NETGROUP).Write(vchNetGroup.data(), vchNetGroup.size()).Finalize(); + return GetDeterministicRandomizer(RANDOMIZER_ID_NETGROUP).Write(vchNetGroup).Finalize(); } void CConnman::PerformReconnections() diff --git a/src/netaddress.h b/src/netaddress.h index 173179309add..f7ab7bfce9e0 100644 --- a/src/netaddress.h +++ b/src/netaddress.h @@ -586,7 +586,7 @@ class CServiceHash CSipHasher hasher(m_salt_k0, m_salt_k1); hasher.Write(a.m_net); hasher.Write(a.port); - hasher.Write(a.m_addr.data(), a.m_addr.size()); + hasher.Write(a.m_addr); return static_cast(hasher.Finalize()); } diff --git a/src/test/fuzz/addrman.cpp b/src/test/fuzz/addrman.cpp index eddd958094bb..33206cdfffcf 100644 --- a/src/test/fuzz/addrman.cpp +++ b/src/test/fuzz/addrman.cpp @@ -170,8 +170,8 @@ class AddrManDeterministic : public AddrMan hasher.Write(a.source.GetNetwork()); hasher.Write(addr_key.size()); hasher.Write(source_key.size()); - hasher.Write(addr_key.data(), addr_key.size()); - hasher.Write(source_key.data(), source_key.size()); + hasher.Write(addr_key); + hasher.Write(source_key); return (size_t)hasher.Finalize(); }; diff --git a/src/test/fuzz/crypto.cpp b/src/test/fuzz/crypto.cpp index 2fd8327b36f0..5c7d9d94433a 100644 --- a/src/test/fuzz/crypto.cpp +++ b/src/test/fuzz/crypto.cpp @@ -57,7 +57,7 @@ FUZZ_TARGET(crypto) (void)sha256.Write(data.data(), data.size()); (void)sha3.Write(data); (void)sha512.Write(data.data(), data.size()); - (void)sip_hasher.Write(data.data(), data.size()); + (void)sip_hasher.Write(data); (void)Hash(data); (void)Hash160(data); diff --git a/src/test/fuzz/golomb_rice.cpp b/src/test/fuzz/golomb_rice.cpp index 1a1225b635d3..e006653ca94c 100644 --- a/src/test/fuzz/golomb_rice.cpp +++ b/src/test/fuzz/golomb_rice.cpp @@ -23,7 +23,7 @@ namespace { uint64_t HashToRange(const std::vector& element, const uint64_t f) { const uint64_t hash = CSipHasher(0x0706050403020100ULL, 0x0F0E0D0C0B0A0908ULL) - .Write(element.data(), element.size()) + .Write(element) .Finalize(); return FastRange64(hash, f); } diff --git a/src/test/hash_tests.cpp b/src/test/hash_tests.cpp index fd18212185ab..157451cc611e 100644 --- a/src/test/hash_tests.cpp +++ b/src/test/hash_tests.cpp @@ -83,21 +83,21 @@ BOOST_AUTO_TEST_CASE(siphash) CSipHasher hasher(0x0706050403020100ULL, 0x0F0E0D0C0B0A0908ULL); BOOST_CHECK_EQUAL(hasher.Finalize(), 0x726fdb47dd0e0e31ull); static const unsigned char t0[1] = {0}; - hasher.Write(t0, 1); + hasher.Write(t0); BOOST_CHECK_EQUAL(hasher.Finalize(), 0x74f839c593dc67fdull); static const unsigned char t1[7] = {1,2,3,4,5,6,7}; - hasher.Write(t1, 7); + hasher.Write(t1); BOOST_CHECK_EQUAL(hasher.Finalize(), 0x93f5f5799a932462ull); hasher.Write(0x0F0E0D0C0B0A0908ULL); BOOST_CHECK_EQUAL(hasher.Finalize(), 0x3f2acc7f57c29bdbull); static const unsigned char t2[2] = {16,17}; - hasher.Write(t2, 2); + hasher.Write(t2); BOOST_CHECK_EQUAL(hasher.Finalize(), 0x4bc1b3f0968dd39cull); static const unsigned char t3[9] = {18,19,20,21,22,23,24,25,26}; - hasher.Write(t3, 9); + hasher.Write(t3); BOOST_CHECK_EQUAL(hasher.Finalize(), 0x2f2e6163076bcfadull); static const unsigned char t4[5] = {27,28,29,30,31}; - hasher.Write(t4, 5); + hasher.Write(t4); BOOST_CHECK_EQUAL(hasher.Finalize(), 0x7127512f72f27cceull); hasher.Write(0x2726252423222120ULL); BOOST_CHECK_EQUAL(hasher.Finalize(), 0x0e3ea96b5304a7d0ull); @@ -111,7 +111,7 @@ BOOST_AUTO_TEST_CASE(siphash) for (uint8_t x=0; x> 1; + uint64_t low_bits = CSipHasher(m_k0, m_k1).Write(inv.hash).Write(inv.type).Write(peer).Finalize() >> 1; return low_bits | uint64_t{preferred} << 63; } diff --git a/src/util/bytevectorhash.cpp b/src/util/bytevectorhash.cpp index 29be138eeb1f..92f1dbd5d80e 100644 --- a/src/util/bytevectorhash.cpp +++ b/src/util/bytevectorhash.cpp @@ -16,5 +16,5 @@ ByteVectorHash::ByteVectorHash() : size_t ByteVectorHash::operator()(const std::vector& input) const { - return CSipHasher(m_k0, m_k1).Write(input.data(), input.size()).Finalize(); + return CSipHasher(m_k0, m_k1).Write(input).Finalize(); } diff --git a/src/util/hasher.cpp b/src/util/hasher.cpp index bc1f84479bc7..4ce0df4fcb62 100644 --- a/src/util/hasher.cpp +++ b/src/util/hasher.cpp @@ -20,5 +20,5 @@ SaltedSipHasher::SaltedSipHasher() : m_k0(GetRand()), m_k1(GetRand& script) const { - return CSipHasher(m_k0, m_k1).Write(script.data(), script.size()).Finalize(); + return CSipHasher(m_k0, m_k1).Write(script).Finalize(); } diff --git a/test/functional/mempool_packages.py b/test/functional/mempool_packages.py index cb2207999f8e..029be2cdeff6 100755 --- a/test/functional/mempool_packages.py +++ b/test/functional/mempool_packages.py @@ -7,7 +7,6 @@ from decimal import Decimal from test_framework.messages import ( - COIN, DEFAULT_ANCESTOR_LIMIT, DEFAULT_DESCENDANT_LIMIT, ) @@ -26,9 +25,6 @@ class MempoolPackagesTest(BitcoinTestFramework): - def add_options(self, parser): - self.add_wallet_options(parser) - def set_test_params(self): self.num_nodes = 2 self.extra_args = [ @@ -47,10 +43,6 @@ def run_test(self): self.wallet = MiniWallet(self.nodes[0]) self.wallet.rescan_utxos() - if self.is_specified_wallet_compiled(): - self.nodes[0].createwallet("watch_wallet", disable_private_keys=True) - self.nodes[0].importaddress(self.wallet.get_address()) - peer_inv_store = self.nodes[0].add_p2p_connection(P2PTxInvStore()) # keep track of invs # DEFAULT_ANCESTOR_LIMIT transactions off a confirmed tx should be fine @@ -63,13 +55,6 @@ def run_test(self): ancestor_vsize += t["tx"].get_vsize() ancestor_fees += t["fee"] self.wallet.sendrawtransaction(from_node=self.nodes[0], tx_hex=t["hex"]) - # Check that listunspent ancestor{count, size, fees} yield the correct results - if self.is_specified_wallet_compiled(): - wallet_unspent = self.nodes[0].listunspent(minconf=0) - this_unspent = next(utxo_info for utxo_info in wallet_unspent if utxo_info["txid"] == t["txid"]) - assert_equal(this_unspent['ancestorcount'], i + 1) - assert_equal(this_unspent['ancestorsize'], ancestor_vsize) - assert_equal(this_unspent['ancestorfees'], ancestor_fees * COIN) # Wait until mempool transactions have passed initial broadcast (sent inv and received getdata) # Otherwise, getrawmempool may be inconsistent with getmempoolentry if unbroadcast changes in between diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py index 62e9c26f6de0..9f3147bcf2e6 100755 --- a/test/functional/wallet_basic.py +++ b/test/functional/wallet_basic.py @@ -8,6 +8,10 @@ from test_framework.blocktools import COINBASE_MATURITY from test_framework.descriptors import descsum_create +from test_framework.messages import ( + COIN, + DEFAULT_ANCESTOR_LIMIT, +) from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_array_result, @@ -19,6 +23,7 @@ find_vout_for_address, ) from test_framework.wallet_util import test_address +from test_framework.wallet import MiniWallet NOT_A_NUMBER_OR_STRING = "Amount is not a number or string" OUT_OF_RANGE = "Amount out of range" @@ -828,6 +833,34 @@ def run_test(self): zeroconf_wallet.sendtoaddress(zeroconf_wallet.getnewaddress(), Decimal('0.5')) + self.test_chain_listunspent() + + def test_chain_listunspent(self): + if not self.options.descriptors: + return + self.wallet = MiniWallet(self.nodes[0]) + self.nodes[0].get_wallet_rpc(self.default_wallet_name).sendtoaddress(self.wallet.get_address(), "5") + self.generate(self.wallet, 1, sync_fun=self.no_op) + self.nodes[0].createwallet("watch_wallet", disable_private_keys=True) + watch_wallet = self.nodes[0].get_wallet_rpc("watch_wallet") + watch_wallet.importaddress(self.wallet.get_address()) + + # DEFAULT_ANCESTOR_LIMIT transactions off a confirmed tx should be fine + chain = self.wallet.create_self_transfer_chain(chain_length=DEFAULT_ANCESTOR_LIMIT) + ancestor_vsize = 0 + ancestor_fees = Decimal(0) + + for i, t in enumerate(chain): + ancestor_vsize += t["tx"].get_vsize() + ancestor_fees += t["fee"] + self.wallet.sendrawtransaction(from_node=self.nodes[0], tx_hex=t["hex"]) + # Check that listunspent ancestor{count, size, fees} yield the correct results + wallet_unspent = watch_wallet.listunspent(minconf=0) + this_unspent = next(utxo_info for utxo_info in wallet_unspent if utxo_info["txid"] == t["txid"]) + assert_equal(this_unspent['ancestorcount'], i + 1) + assert_equal(this_unspent['ancestorsize'], ancestor_vsize) + assert_equal(this_unspent['ancestorfees'], ancestor_fees * COIN) + if __name__ == '__main__': WalletTest().main()