0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-08 10:31:50 -05:00

Merge bitcoin/bitcoin#23413: Replace MakeSpan helper with Span deduction guide

11daf6ceb1 More Span simplifications (Pieter Wuille)
568dd2f839 Replace MakeSpan helper with Span deduction guide (Pieter Wuille)

Pull request description:

  C++17 supports [user-defined deduction guides](https://en.cppreference.com/w/cpp/language/class_template_argument_deduction), allowing class constructors to be invoked without specifying class template arguments. Instead, the code can contain rules to infer the template arguments from the constructor argument types.

  This alleviates the need for the `MakeSpan` helper. Convert the existing MakeSpan rules into deduction rules for `Span` itself, and replace all invocations of `MakeSpan` with just `Span` ones.

ACKs for top commit:
  MarcoFalke:
    re-ACK 11daf6ceb1 Only change is removing a hunk in the tests 🌕

Tree-SHA512: 10f3e82e4338f39d9b7b407cd11aac7ebe1e9191b58e3d7f4e5e338a4636c0e126b4a1d912127c7446f57ba356c8d6544482e47f97901efea6a54fffbfd7895f
This commit is contained in:
MarcoFalke 2021-12-03 10:44:26 +01:00
commit 8b1de78577
No known key found for this signature in database
GPG key ID: CE2B75697E69A548
25 changed files with 125 additions and 124 deletions

View file

@ -149,7 +149,7 @@ std::string EncodeBase58Check(Span<const unsigned char> input)
return false;
}
// re-calculate the checksum, ensure it matches the included 4-byte checksum
uint256 hash = Hash(MakeSpan(vchRet).first(vchRet.size() - 4));
uint256 hash = Hash(Span{vchRet}.first(vchRet.size() - 4));
if (memcmp(&hash, &vchRet[vchRet.size() - 4], 4) != 0) {
vchRet.clear();
return false;

View file

@ -65,12 +65,12 @@ struct ScriptCompression
void Ser(Stream &s, const CScript& script) {
CompressedScript compr;
if (CompressScript(script, compr)) {
s << MakeSpan(compr);
s << Span{compr};
return;
}
unsigned int nSize = script.size() + nSpecialScripts;
s << VARINT(nSize);
s << MakeSpan(script);
s << Span{script};
}
template<typename Stream>
@ -79,7 +79,7 @@ struct ScriptCompression
s >> VARINT(nSize);
if (nSize < nSpecialScripts) {
CompressedScript vch(GetSpecialScriptSize(nSize), 0x00);
s >> MakeSpan(vch);
s >> Span{vch};
DecompressScript(script, nSize, vch);
return;
}
@ -90,7 +90,7 @@ struct ScriptCompression
s.ignore(nSize);
} else {
script.resize(nSize);
s >> MakeSpan(script);
s >> Span{script};
}
}
};

View file

@ -761,7 +761,7 @@ CNetMessage V1TransportDeserializer::GetMessage(const std::chrono::microseconds
if (memcmp(hash.begin(), hdr.pchChecksum, CMessageHeader::CHECKSUM_SIZE) != 0) {
LogPrint(BCLog::NET, "Header error: Wrong checksum (%s, %u bytes), expected %s was %s, peer=%d\n",
SanitizeString(msg.m_command), msg.m_message_size,
HexStr(Span<uint8_t>(hash.begin(), hash.begin() + CMessageHeader::CHECKSUM_SIZE)),
HexStr(Span{hash}.first(CMessageHeader::CHECKSUM_SIZE)),
HexStr(hdr.pchChecksum),
m_node_id);
reject_message = true;
@ -1583,8 +1583,9 @@ void CConnman::SocketHandlerConnected(const std::vector<CNode*>& nodes,
if (nBytes > 0)
{
bool notify = false;
if (!pnode->ReceiveMsgBytes(Span<const uint8_t>(pchBuf, nBytes), notify))
if (!pnode->ReceiveMsgBytes({pchBuf, (size_t)nBytes}, notify)) {
pnode->CloseSocketDisconnect();
}
RecordBytesRecv(nBytes);
if (notify) {
size_t nSizeAdded = 0;

View file

@ -1815,7 +1815,7 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv&
if (!ReadRawBlockFromDisk(block_data, pindex, m_chainparams.MessageStart())) {
assert(!"cannot load block from disk");
}
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::BLOCK, MakeSpan(block_data)));
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::BLOCK, Span{block_data}));
// Don't set pblock as we've sent the block
} else {
// Send block from disk

View file

@ -196,7 +196,7 @@ static void Checksum(Span<const uint8_t> addr_pubkey, uint8_t (&checksum)[CHECKS
SHA3_256 hasher;
hasher.Write(MakeSpan(prefix).first(prefix_len));
hasher.Write(Span{prefix}.first(prefix_len));
hasher.Write(addr_pubkey);
hasher.Write(VERSION);
@ -303,7 +303,7 @@ CNetAddr::CNetAddr(const struct in_addr& ipv4Addr)
CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr, const uint32_t scope)
{
SetLegacyIPv6(Span<const uint8_t>(reinterpret_cast<const uint8_t*>(&ipv6Addr), sizeof(ipv6Addr)));
SetLegacyIPv6({reinterpret_cast<const uint8_t*>(&ipv6Addr), sizeof(ipv6Addr)});
m_scope_id = scope;
}
@ -693,13 +693,13 @@ uint32_t CNetAddr::GetLinkedIPv4() const
return ReadBE32(m_addr.data());
} else if (IsRFC6052() || IsRFC6145()) {
// mapped IPv4, SIIT translated IPv4: the IPv4 address is the last 4 bytes of the address
return ReadBE32(MakeSpan(m_addr).last(ADDR_IPV4_SIZE).data());
return ReadBE32(Span{m_addr}.last(ADDR_IPV4_SIZE).data());
} else if (IsRFC3964()) {
// 6to4 tunneled IPv4: the IPv4 address is in bytes 2-6
return ReadBE32(MakeSpan(m_addr).subspan(2, ADDR_IPV4_SIZE).data());
return ReadBE32(Span{m_addr}.subspan(2, ADDR_IPV4_SIZE).data());
} else if (IsRFC4380()) {
// Teredo tunneled IPv4: the IPv4 address is in the last 4 bytes of the address, but bitflipped
return ~ReadBE32(MakeSpan(m_addr).last(ADDR_IPV4_SIZE).data());
return ~ReadBE32(Span{m_addr}.last(ADDR_IPV4_SIZE).data());
}
assert(false);
}

View file

@ -433,7 +433,7 @@ private:
if (SetNetFromBIP155Network(bip155_net, address_size)) {
m_addr.resize(address_size);
s >> MakeSpan(m_addr);
s >> Span{m_addr};
if (m_net != NET_IPV6) {
return;

View file

@ -251,7 +251,7 @@ bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
// - No annexes
if (witnessversion == 1 && witnessprogram.size() == WITNESS_V1_TAPROOT_SIZE && !p2sh) {
// Taproot spend (non-P2SH-wrapped, version 1, witness program size 32; see BIP 341)
auto stack = MakeSpan(tx.vin[i].scriptWitness.stack);
Span stack{tx.vin[i].scriptWitness.stack};
if (stack.size() >= 2 && !stack.back().empty() && stack.back()[0] == ANNEX_TAG) {
// Annexes are nonstandard as long as no semantics are defined for them.
return false;

View file

@ -81,7 +81,7 @@ struct PSBTInput
if (final_script_sig.empty() && final_script_witness.IsNull()) {
// Write any partial signatures
for (auto sig_pair : partial_sigs) {
SerializeToVector(s, PSBT_IN_PARTIAL_SIG, MakeSpan(sig_pair.second.first));
SerializeToVector(s, PSBT_IN_PARTIAL_SIG, Span{sig_pair.second.first});
s << sig_pair.second.second;
}

View file

@ -157,13 +157,13 @@ public:
//! Get the KeyID of this public key (hash of its serialization)
CKeyID GetID() const
{
return CKeyID(Hash160(MakeSpan(vch).first(size())));
return CKeyID(Hash160(Span{vch}.first(size())));
}
//! Get the 256-bit hash of this public key.
uint256 GetHash() const
{
return Hash(MakeSpan(vch).first(size()));
return Hash(Span{vch}.first(size()));
}
/*
@ -240,7 +240,7 @@ public:
explicit XOnlyPubKey(Span<const unsigned char> bytes);
/** Construct an x-only pubkey from a normal pubkey. */
explicit XOnlyPubKey(const CPubKey& pubkey) : XOnlyPubKey(Span<const unsigned char>(pubkey.begin() + 1, pubkey.begin() + 33)) {}
explicit XOnlyPubKey(const CPubKey& pubkey) : XOnlyPubKey(Span{pubkey}.subspan(1, 32)) {}
/** Verify a Schnorr signature against this public key.
*

View file

@ -317,7 +317,7 @@ public:
UniValue obj(UniValue::VOBJ);
obj.pushKV("iswitness", true);
obj.pushKV("witness_version", (int)id.version);
obj.pushKV("witness_program", HexStr(Span<const unsigned char>(id.program, id.length)));
obj.pushKV("witness_program", HexStr({id.program, id.length}));
return obj;
}
};

View file

@ -631,7 +631,7 @@ public:
out.origins.emplace(entry.first.GetID(), std::make_pair<CPubKey, KeyOriginInfo>(CPubKey(entry.first), std::move(entry.second)));
}
output_scripts = MakeScripts(pubkeys, MakeSpan(subscripts), out);
output_scripts = MakeScripts(pubkeys, Span{subscripts}, out);
return true;
}
@ -974,10 +974,10 @@ std::unique_ptr<PubkeyProvider> ParsePubkeyInner(uint32_t key_exp_index, const S
}
KeyPath path;
DeriveType type = DeriveType::NO;
if (split.back() == MakeSpan("*").first(1)) {
if (split.back() == Span{"*"}.first(1)) {
split.pop_back();
type = DeriveType::UNHARDENED;
} else if (split.back() == MakeSpan("*'").first(2) || split.back() == MakeSpan("*h").first(2)) {
} else if (split.back() == Span{"*'"}.first(2) || split.back() == Span{"*h"}.first(2)) {
split.pop_back();
type = DeriveType::HARDENED;
}
@ -1252,7 +1252,7 @@ std::unique_ptr<PubkeyProvider> InferXOnlyPubkey(const XOnlyPubKey& xkey, ParseS
std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptContext ctx, const SigningProvider& provider)
{
if (ctx == ParseScriptContext::P2TR && script.size() == 34 && script[0] == 32 && script[33] == OP_CHECKSIG) {
XOnlyPubKey key{Span<const unsigned char>{script.data() + 1, script.data() + 33}};
XOnlyPubKey key{Span{script}.subspan(1, 32)};
return std::make_unique<PKDescriptor>(InferXOnlyPubkey(key, ctx, provider));
}

View file

@ -1858,7 +1858,7 @@ uint256 ComputeTaprootMerkleRoot(Span<const unsigned char> control, const uint25
uint256 k = tapleaf_hash;
for (int i = 0; i < path_len; ++i) {
CHashWriter ss_branch{HASHER_TAPBRANCH};
Span<const unsigned char> node(control.data() + TAPROOT_CONTROL_BASE_SIZE + TAPROOT_CONTROL_NODE_SIZE * i, TAPROOT_CONTROL_NODE_SIZE);
Span node{Span{control}.subspan(TAPROOT_CONTROL_BASE_SIZE + TAPROOT_CONTROL_NODE_SIZE * i, TAPROOT_CONTROL_NODE_SIZE)};
if (std::lexicographical_compare(k.begin(), k.end(), node.begin(), node.end())) {
ss_branch << k << node;
} else {
@ -1874,7 +1874,7 @@ static bool VerifyTaprootCommitment(const std::vector<unsigned char>& control, c
assert(control.size() >= TAPROOT_CONTROL_BASE_SIZE);
assert(program.size() >= uint256::size());
//! The internal pubkey (x-only, so no Y coordinate parity).
const XOnlyPubKey p{Span<const unsigned char>{control.data() + 1, control.data() + TAPROOT_CONTROL_BASE_SIZE}};
const XOnlyPubKey p{Span{control}.subspan(1, TAPROOT_CONTROL_BASE_SIZE - 1)};
//! The output pubkey (taken from the scriptPubKey).
const XOnlyPubKey q{program};
// Compute the Merkle root from the leaf and the provided path.
@ -1886,7 +1886,7 @@ static bool VerifyTaprootCommitment(const std::vector<unsigned char>& control, c
static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion, const std::vector<unsigned char>& program, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror, bool is_p2sh)
{
CScript exec_script; //!< Actually executed script (last stack item in P2WSH; implied P2PKH script in P2WPKH; leaf script in P2TR)
Span<const valtype> stack{witness.stack};
Span stack{witness.stack};
ScriptExecutionData execdata;
if (witversion == 0) {

View file

@ -167,7 +167,7 @@ static bool SignTaprootScript(const SigningProvider& provider, const BaseSignatu
// <xonly pubkey> OP_CHECKSIG
if (script.size() == 34 && script[33] == OP_CHECKSIG && script[0] == 0x20) {
XOnlyPubKey pubkey(MakeSpan(script).subspan(1, 32));
XOnlyPubKey pubkey{Span{script}.subspan(1, 32)};
std::vector<unsigned char> sig;
if (CreateTaprootScriptSig(creator, sigdata, provider, sig, pubkey, leaf_hash, sigversion)) {
result = Vector(std::move(sig));

View file

@ -149,7 +149,7 @@ void SerializeHDKeypaths(Stream& s, const std::map<CPubKey, KeyOriginInfo>& hd_k
if (!keypath_pair.first.IsValid()) {
throw std::ios_base::failure("Invalid CPubKey being serialized");
}
SerializeToVector(s, type, MakeSpan(keypath_pair.first));
SerializeToVector(s, type, Span{keypath_pair.first});
WriteCompactSize(s, (keypath_pair.second.path.size() + 1) * sizeof(uint32_t));
s << keypath_pair.second.fingerprint;
for (const auto& path : keypath_pair.second.path) {

View file

@ -38,7 +38,7 @@ static bool FetchAndClearCommitmentSection(const Span<const uint8_t> header, CSc
std::vector<uint8_t> pushdata;
while (witness_commitment.GetOp(pc, opcode, pushdata)) {
if (pushdata.size() > 0) {
if (!found_header && pushdata.size() > (size_t) header.size() && Span<const uint8_t>(pushdata.data(), header.size()) == header) {
if (!found_header && pushdata.size() > (size_t)header.size() && Span{pushdata}.first(header.size()) == header) {
// pushdata only counts if it has the header _and_ some data
result.insert(result.end(), pushdata.begin() + header.size(), pushdata.end());
pushdata.erase(pushdata.begin() + header.size(), pushdata.end());

View file

@ -222,13 +222,15 @@ public:
template <typename O> friend class Span;
};
// MakeSpan helps constructing a Span of the right type automatically.
/** MakeSpan for arrays: */
template <typename A, int N> Span<A> constexpr MakeSpan(A (&a)[N]) { return Span<A>(a, N); }
/** MakeSpan for temporaries / rvalue references, only supporting const output. */
template <typename V> constexpr auto MakeSpan(V&& v SPAN_ATTR_LIFETIMEBOUND) -> typename std::enable_if<!std::is_lvalue_reference<V>::value, Span<const typename std::remove_pointer<decltype(v.data())>::type>>::type { return std::forward<V>(v); }
/** MakeSpan for (lvalue) references, supporting mutable output. */
template <typename V> constexpr auto MakeSpan(V& v SPAN_ATTR_LIFETIMEBOUND) -> Span<typename std::remove_pointer<decltype(v.data())>::type> { return v; }
// Deduction guides for Span
// For the pointer/size based and iterator based constructor:
template <typename T, typename EndOrSize> Span(T*, EndOrSize) -> Span<T>;
// For the array constructor:
template <typename T, std::size_t N> Span(T (&)[N]) -> Span<T>;
// For the temporaries/rvalue references constructor, only supporting const output.
template <typename T> Span(T&&) -> Span<std::enable_if_t<!std::is_lvalue_reference_v<T>, const std::remove_pointer_t<decltype(std::declval<T&&>().data())>>>;
// For (lvalue) references, supporting mutable output.
template <typename T> Span(T&) -> Span<std::remove_pointer_t<decltype(std::declval<T&>().data())>>;
/** Pop the last element off a span, and return a reference to that element. */
template <typename T>
@ -256,12 +258,12 @@ Span<std::byte> AsWritableBytes(Span<T> s) noexcept
template <typename V>
Span<const std::byte> MakeByteSpan(V&& v) noexcept
{
return AsBytes(MakeSpan(std::forward<V>(v)));
return AsBytes(Span{std::forward<V>(v)});
}
template <typename V>
Span<std::byte> MakeWritableByteSpan(V&& v) noexcept
{
return AsWritableBytes(MakeSpan(std::forward<V>(v)));
return AsWritableBytes(Span{std::forward<V>(v)});
}
// Helper functions to safely cast to unsigned char pointers.
@ -274,7 +276,7 @@ inline const unsigned char* UCharCast(const std::byte* c) { return reinterpret_c
// Helper function to safely convert a Span to a Span<[const] unsigned char>.
template <typename T> constexpr auto UCharSpanCast(Span<T> s) -> Span<typename std::remove_pointer<decltype(UCharCast(s.data()))>::type> { return {UCharCast(s.data()), s.size()}; }
/** Like MakeSpan, but for (const) unsigned char member types only. Only works for (un)signed char containers. */
template <typename V> constexpr auto MakeUCharSpan(V&& v) -> decltype(UCharSpanCast(MakeSpan(std::forward<V>(v)))) { return UCharSpanCast(MakeSpan(std::forward<V>(v))); }
/** Like the Span constructor, but for (const) unsigned char member types only. Only works for (un)signed char containers. */
template <typename V> constexpr auto MakeUCharSpan(V&& v) -> decltype(UCharSpanCast(Span{std::forward<V>(v)})) { return UCharSpanCast(Span{std::forward<V>(v)}); }
#endif // BITCOIN_SPAN_H

View file

@ -770,8 +770,8 @@ static void TestSHA3_256(const std::string& input, const std::string& output)
int s1 = InsecureRandRange(in_bytes.size() + 1);
int s2 = InsecureRandRange(in_bytes.size() + 1 - s1);
int s3 = in_bytes.size() - s1 - s2;
sha.Write(MakeSpan(in_bytes).first(s1)).Write(MakeSpan(in_bytes).subspan(s1, s2));
sha.Write(MakeSpan(in_bytes).last(s3)).Finalize(out);
sha.Write(Span{in_bytes}.first(s1)).Write(Span{in_bytes}.subspan(s1, s2));
sha.Write(Span{in_bytes}.last(s3)).Finalize(out);
BOOST_CHECK(std::equal(std::begin(out_bytes), std::end(out_bytes), out));
}

View file

@ -49,7 +49,7 @@ FUZZ_TARGET(asmap)
CNetAddr net_addr;
if (ipv6) {
assert(addr_size == ADDR_IPV6_SIZE);
net_addr.SetLegacyIPv6(Span<const uint8_t>(addr_data, addr_size));
net_addr.SetLegacyIPv6({addr_data, addr_size});
} else {
assert(addr_size == ADDR_IPV4_SIZE);
in_addr ipv4;

View file

@ -38,7 +38,7 @@ FUZZ_TARGET_INIT(utxo_snapshot, initialize_chain)
{
CAutoFile outfile{fsbridge::fopen(snapshot_path, "wb"), SER_DISK, CLIENT_VERSION};
const auto file_data{ConsumeRandomLengthByteVector(fuzzed_data_provider)};
outfile << Span<const uint8_t>{file_data};
outfile << Span{file_data};
}
const auto ActivateFuzzedSnapshot{[&] {

View file

@ -46,7 +46,7 @@ BOOST_AUTO_TEST_CASE(key_io_valid_parse)
privkey = DecodeSecret(exp_base58string);
BOOST_CHECK_MESSAGE(privkey.IsValid(), "!IsValid:" + strTest);
BOOST_CHECK_MESSAGE(privkey.IsCompressed() == isCompressed, "compressed mismatch:" + strTest);
BOOST_CHECK_MESSAGE(Span<const uint8_t>{privkey} == Span<const uint8_t>{exp_payload}, "key mismatch:" + strTest);
BOOST_CHECK_MESSAGE(Span{privkey} == Span{exp_payload}, "key mismatch:" + strTest);
// Private key must be invalid public key
destination = DecodeDestination(exp_base58string);

View file

@ -386,9 +386,9 @@ BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
s.SetVersion(s.GetVersion() | ADDRV2_FORMAT);
// Valid IPv4.
s << MakeSpan(ParseHex("01" // network type (IPv4)
"04" // address length
"01020304")); // address
s << Span{ParseHex("01" // network type (IPv4)
"04" // address length
"01020304")}; // address
s >> addr;
BOOST_CHECK(addr.IsValid());
BOOST_CHECK(addr.IsIPv4());
@ -397,35 +397,35 @@ BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
BOOST_REQUIRE(s.empty());
// Invalid IPv4, valid length but address itself is shorter.
s << MakeSpan(ParseHex("01" // network type (IPv4)
"04" // address length
"0102")); // address
s << Span{ParseHex("01" // network type (IPv4)
"04" // address length
"0102")}; // address
BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure, HasReason("end of data"));
BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
s.clear();
// Invalid IPv4, with bogus length.
s << MakeSpan(ParseHex("01" // network type (IPv4)
"05" // address length
"01020304")); // address
s << Span{ParseHex("01" // network type (IPv4)
"05" // address length
"01020304")}; // address
BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
HasReason("BIP155 IPv4 address with length 5 (should be 4)"));
BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
s.clear();
// Invalid IPv4, with extreme length.
s << MakeSpan(ParseHex("01" // network type (IPv4)
"fd0102" // address length (513 as CompactSize)
"01020304")); // address
s << Span{ParseHex("01" // network type (IPv4)
"fd0102" // address length (513 as CompactSize)
"01020304")}; // address
BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
HasReason("Address too long: 513 > 512"));
BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
s.clear();
// Valid IPv6.
s << MakeSpan(ParseHex("02" // network type (IPv6)
"10" // address length
"0102030405060708090a0b0c0d0e0f10")); // address
s << Span{ParseHex("02" // network type (IPv6)
"10" // address length
"0102030405060708090a0b0c0d0e0f10")}; // address
s >> addr;
BOOST_CHECK(addr.IsValid());
BOOST_CHECK(addr.IsIPv6());
@ -434,10 +434,10 @@ BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
BOOST_REQUIRE(s.empty());
// Valid IPv6, contains embedded "internal".
s << MakeSpan(ParseHex(
s << Span{ParseHex(
"02" // network type (IPv6)
"10" // address length
"fd6b88c08724ca978112ca1bbdcafac2")); // address: 0xfd + sha256("bitcoin")[0:5] +
"fd6b88c08724ca978112ca1bbdcafac2")}; // address: 0xfd + sha256("bitcoin")[0:5] +
// sha256(name)[0:10]
s >> addr;
BOOST_CHECK(addr.IsInternal());
@ -446,44 +446,44 @@ BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
BOOST_REQUIRE(s.empty());
// Invalid IPv6, with bogus length.
s << MakeSpan(ParseHex("02" // network type (IPv6)
"04" // address length
"00")); // address
s << Span{ParseHex("02" // network type (IPv6)
"04" // address length
"00")}; // address
BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
HasReason("BIP155 IPv6 address with length 4 (should be 16)"));
BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
s.clear();
// Invalid IPv6, contains embedded IPv4.
s << MakeSpan(ParseHex("02" // network type (IPv6)
"10" // address length
"00000000000000000000ffff01020304")); // address
s << Span{ParseHex("02" // network type (IPv6)
"10" // address length
"00000000000000000000ffff01020304")}; // address
s >> addr;
BOOST_CHECK(!addr.IsValid());
BOOST_REQUIRE(s.empty());
// Invalid IPv6, contains embedded TORv2.
s << MakeSpan(ParseHex("02" // network type (IPv6)
"10" // address length
"fd87d87eeb430102030405060708090a")); // address
s << Span{ParseHex("02" // network type (IPv6)
"10" // address length
"fd87d87eeb430102030405060708090a")}; // address
s >> addr;
BOOST_CHECK(!addr.IsValid());
BOOST_REQUIRE(s.empty());
// TORv2, no longer supported.
s << MakeSpan(ParseHex("03" // network type (TORv2)
"0a" // address length
"f1f2f3f4f5f6f7f8f9fa")); // address
s << Span{ParseHex("03" // network type (TORv2)
"0a" // address length
"f1f2f3f4f5f6f7f8f9fa")}; // address
s >> addr;
BOOST_CHECK(!addr.IsValid());
BOOST_REQUIRE(s.empty());
// Valid TORv3.
s << MakeSpan(ParseHex("04" // network type (TORv3)
"20" // address length
"79bcc625184b05194975c28b66b66b04" // address
"69f7f6556fb1ac3189a79b40dda32f1f"
));
s << Span{ParseHex("04" // network type (TORv3)
"20" // address length
"79bcc625184b05194975c28b66b66b04" // address
"69f7f6556fb1ac3189a79b40dda32f1f"
)};
s >> addr;
BOOST_CHECK(addr.IsValid());
BOOST_CHECK(addr.IsTor());
@ -493,20 +493,20 @@ BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
BOOST_REQUIRE(s.empty());
// Invalid TORv3, with bogus length.
s << MakeSpan(ParseHex("04" // network type (TORv3)
"00" // address length
"00" // address
));
s << Span{ParseHex("04" // network type (TORv3)
"00" // address length
"00" // address
)};
BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
HasReason("BIP155 TORv3 address with length 0 (should be 32)"));
BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
s.clear();
// Valid I2P.
s << MakeSpan(ParseHex("05" // network type (I2P)
"20" // address length
"a2894dabaec08c0051a481a6dac88b64" // address
"f98232ae42d4b6fd2fa81952dfe36a87"));
s << Span{ParseHex("05" // network type (I2P)
"20" // address length
"a2894dabaec08c0051a481a6dac88b64" // address
"f98232ae42d4b6fd2fa81952dfe36a87")};
s >> addr;
BOOST_CHECK(addr.IsValid());
BOOST_CHECK(addr.IsI2P());
@ -516,20 +516,20 @@ BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
BOOST_REQUIRE(s.empty());
// Invalid I2P, with bogus length.
s << MakeSpan(ParseHex("05" // network type (I2P)
"03" // address length
"00" // address
));
s << Span{ParseHex("05" // network type (I2P)
"03" // address length
"00" // address
)};
BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
HasReason("BIP155 I2P address with length 3 (should be 32)"));
BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
s.clear();
// Valid CJDNS.
s << MakeSpan(ParseHex("06" // network type (CJDNS)
"10" // address length
"fc000001000200030004000500060007" // address
));
s << Span{ParseHex("06" // network type (CJDNS)
"10" // address length
"fc000001000200030004000500060007" // address
)};
s >> addr;
BOOST_CHECK(addr.IsValid());
BOOST_CHECK(addr.IsCJDNS());
@ -538,49 +538,49 @@ BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
BOOST_REQUIRE(s.empty());
// Invalid CJDNS, wrong prefix.
s << MakeSpan(ParseHex("06" // network type (CJDNS)
"10" // address length
"aa000001000200030004000500060007" // address
));
s << Span{ParseHex("06" // network type (CJDNS)
"10" // address length
"aa000001000200030004000500060007" // address
)};
s >> addr;
BOOST_CHECK(addr.IsCJDNS());
BOOST_CHECK(!addr.IsValid());
BOOST_REQUIRE(s.empty());
// Invalid CJDNS, with bogus length.
s << MakeSpan(ParseHex("06" // network type (CJDNS)
"01" // address length
"00" // address
));
s << Span{ParseHex("06" // network type (CJDNS)
"01" // address length
"00" // address
)};
BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
HasReason("BIP155 CJDNS address with length 1 (should be 16)"));
BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
s.clear();
// Unknown, with extreme length.
s << MakeSpan(ParseHex("aa" // network type (unknown)
"fe00000002" // address length (CompactSize's MAX_SIZE)
"01020304050607" // address
));
s << Span{ParseHex("aa" // network type (unknown)
"fe00000002" // address length (CompactSize's MAX_SIZE)
"01020304050607" // address
)};
BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
HasReason("Address too long: 33554432 > 512"));
BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
s.clear();
// Unknown, with reasonable length.
s << MakeSpan(ParseHex("aa" // network type (unknown)
"04" // address length
"01020304" // address
));
s << Span{ParseHex("aa" // network type (unknown)
"04" // address length
"01020304" // address
)};
s >> addr;
BOOST_CHECK(!addr.IsValid());
BOOST_REQUIRE(s.empty());
// Unknown, with zero length.
s << MakeSpan(ParseHex("aa" // network type (unknown)
"00" // address length
"" // address
));
s << Span{ParseHex("aa" // network type (unknown)
"00" // address length
"" // address
)};
s >> addr;
BOOST_CHECK(!addr.IsValid());
BOOST_REQUIRE(s.empty());

View file

@ -284,7 +284,7 @@ public:
CScript scriptPubKey = script;
if (wm == WitnessMode::PKH) {
uint160 hash;
CHash160().Write(MakeSpan(script).subspan(1)).Finalize(hash);
CHash160().Write(Span{script}.subspan(1)).Finalize(hash);
script = CScript() << OP_DUP << OP_HASH160 << ToByteVector(hash) << OP_EQUALVERIFY << OP_CHECKSIG;
scriptPubKey = CScript() << witnessversion << ToByteVector(hash);
} else if (wm == WitnessMode::SH) {
@ -1812,7 +1812,7 @@ BOOST_AUTO_TEST_CASE(bip341_keypath_test_vectors)
BOOST_CHECK_EQUAL(HexStr(sighash), input["intermediary"]["sigHash"].get_str());
// To verify the sigmsg, hash the expected sigmsg, and compare it with the (expected) sighash.
BOOST_CHECK_EQUAL(HexStr((CHashWriter(HASHER_TAPSIGHASH) << MakeSpan(ParseHex(input["intermediary"]["sigMsg"].get_str()))).GetSHA256()), input["intermediary"]["sigHash"].get_str());
BOOST_CHECK_EQUAL(HexStr((CHashWriter(HASHER_TAPSIGHASH) << Span{ParseHex(input["intermediary"]["sigMsg"].get_str())}).GetSHA256()), input["intermediary"]["sigHash"].get_str());
}
}

View file

@ -142,13 +142,11 @@ BOOST_AUTO_TEST_CASE(util_HexStr)
"04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f");
BOOST_CHECK_EQUAL(
HexStr(Span<const unsigned char>(
ParseHex_expected + sizeof(ParseHex_expected),
ParseHex_expected + sizeof(ParseHex_expected))),
HexStr(Span{ParseHex_expected}.last(0)),
"");
BOOST_CHECK_EQUAL(
HexStr(Span<const unsigned char>(ParseHex_expected, ParseHex_expected)),
HexStr(Span{ParseHex_expected}.first(0)),
"");
{

View file

@ -35,7 +35,7 @@ std::string static EncodeDumpString(const std::string &str) {
std::stringstream ret;
for (const unsigned char c : str) {
if (c <= 32 || c >= 128 || c == '%') {
ret << '%' << HexStr(Span<const unsigned char>(&c, 1));
ret << '%' << HexStr({&c, 1});
} else {
ret << c;
}

View file

@ -4413,5 +4413,5 @@ static const CRPCCommand commands[] =
{ "wallet", &walletprocesspsbt, },
};
// clang-format on
return MakeSpan(commands);
return commands;
}