aboutsummaryrefslogtreecommitdiff
path: root/src/serialize.h
diff options
context:
space:
mode:
authorfanquake <fanquake@gmail.com>2020-10-11 08:16:41 +0800
committerfanquake <fanquake@gmail.com>2020-10-11 08:51:57 +0800
commit0b2abaa666d6f3331e3246ffd64dd47946e9dcdf (patch)
treed1b254fd219179db7fb0657a8299f5707eb5bbea /src/serialize.h
parent12a1c3ad1a43634d2a98717e49e3f02c4acea2fe (diff)
parentdcf0cb477699d11afd0ff37c8bfb2b1b4f7f1ee5 (diff)
downloadbitcoin-0b2abaa666d6f3331e3246ffd64dd47946e9dcdf.tar.xz
Merge #19954: Complete the BIP155 implementation and upgrade to TORv3
dcf0cb477699d11afd0ff37c8bfb2b1b4f7f1ee5 tor: make a TORv3 hidden service instead of TORv2 (Vasil Dimov) 353a3fdaad055eea42a0baf7326bdd591f541170 net: advertise support for ADDRv2 via new message (Vasil Dimov) 201a4596d92d640d5eb7e76cc8d959228fa09dbb net: CAddress & CAddrMan: (un)serialize as ADDRv2 (Vasil Dimov) 1d3ec2a1fda7446323786a52da1fd109c01aa6fb Support bypassing range check in ReadCompactSize (Pieter Wuille) Pull request description: This PR contains the two remaining commits from #19031 to complete the [BIP155](https://github.com/bitcoin/bips/blob/master/bip-0155.mediawiki) implementation: `net: CAddress & CAddrMan: (un)serialize as ADDRv2` `net: advertise support for ADDRv2 via new message` plus one more commit: `tor: make a TORv3 hidden service instead of TORv2` ACKs for top commit: jonatack: re-ACK dcf0cb477699d11afd0ff37c8bfb2b1b4f7f1ee5 per `git diff 9b56a68 dcf0cb4` only change since last review is an update to the release notes which partially picked up the suggested text. Running a node on this branch and addnode-ing to 6 other Tor v3 nodes, I see "addrv2" and "sendaddrv2" messages in getpeerinfo in both the "bytesrecv_per_msg" and "bytessent_per_msg" JSON objects. sipa: ACK dcf0cb477699d11afd0ff37c8bfb2b1b4f7f1ee5 hebasto: re-ACK dcf0cb477699d11afd0ff37c8bfb2b1b4f7f1ee5, the node works flawlessly in all of the modes: Tor-only, clearnet-only, mixed. laanwj: Edit: I have to retract this ACK for now, I'm having some problems with this PR on a FreeBSD node. It drops all outgoing connections with this dcf0cb477699d11afd0ff37c8bfb2b1b4f7f1ee5 merged on master (12a1c3ad1a43634d2a98717e49e3f02c4acea2fe). ariard: Code Review ACK dcf0cb4 Tree-SHA512: 28d4d0d817b8664d2f4b18c0e0f31579b2f0f2d23310ed213f1f436a4242afea14dfbf99e07e15889bc5c5c71ad50056797e9307ff8a90e96704f588a6171308
Diffstat (limited to 'src/serialize.h')
-rw-r--r--src/serialize.h22
1 files changed, 17 insertions, 5 deletions
diff --git a/src/serialize.h b/src/serialize.h
index 7a94e704b2..d9ca984f9c 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -24,7 +24,11 @@
#include <prevector.h>
#include <span.h>
-static const unsigned int MAX_SIZE = 0x02000000;
+/**
+ * The maximum size of a serialized object in bytes or number of elements
+ * (for eg vectors) when the size is encoded as CompactSize.
+ */
+static constexpr uint64_t MAX_SIZE = 0x02000000;
/** Maximum amount of memory (in bytes) to allocate at once when deserializing vectors. */
static const unsigned int MAX_VECTOR_ALLOCATE = 5000000;
@@ -304,8 +308,14 @@ void WriteCompactSize(Stream& os, uint64_t nSize)
return;
}
+/**
+ * Decode a CompactSize-encoded variable-length integer.
+ *
+ * As these are primarily used to encode the size of vector-like serializations, by default a range
+ * check is performed. When used as a generic number encoding, range_check should be set to false.
+ */
template<typename Stream>
-uint64_t ReadCompactSize(Stream& is)
+uint64_t ReadCompactSize(Stream& is, bool range_check = true)
{
uint8_t chSize = ser_readdata8(is);
uint64_t nSizeRet = 0;
@@ -331,8 +341,9 @@ uint64_t ReadCompactSize(Stream& is)
if (nSizeRet < 0x100000000ULL)
throw std::ios_base::failure("non-canonical ReadCompactSize()");
}
- if (nSizeRet > (uint64_t)MAX_SIZE)
+ if (range_check && nSizeRet > MAX_SIZE) {
throw std::ios_base::failure("ReadCompactSize(): size too large");
+ }
return nSizeRet;
}
@@ -466,7 +477,7 @@ static inline Wrapper<Formatter, T&> Using(T&& t) { return Wrapper<Formatter, T&
#define VARINT_MODE(obj, mode) Using<VarIntFormatter<mode>>(obj)
#define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj)
-#define COMPACTSIZE(obj) Using<CompactSizeFormatter>(obj)
+#define COMPACTSIZE(obj) Using<CompactSizeFormatter<true>>(obj)
#define LIMITED_STRING(obj,n) Using<LimitedStringFormatter<n>>(obj)
/** Serialization wrapper class for integers in VarInt format. */
@@ -529,12 +540,13 @@ struct CustomUintFormatter
template<int Bytes> using BigEndianFormatter = CustomUintFormatter<Bytes, true>;
/** Formatter for integers in CompactSize format. */
+template<bool RangeCheck>
struct CompactSizeFormatter
{
template<typename Stream, typename I>
void Unser(Stream& s, I& v)
{
- uint64_t n = ReadCompactSize<Stream>(s);
+ uint64_t n = ReadCompactSize<Stream>(s, RangeCheck);
if (n < std::numeric_limits<I>::min() || n > std::numeric_limits<I>::max()) {
throw std::ios_base::failure("CompactSize exceeds limit of type");
}