Skip to content

Commit 6286c9b

Browse files
committed
evo: change internal type of MnNetInfo to NetInfoEntry
1 parent b0a634e commit 6286c9b

File tree

4 files changed

+96
-15
lines changed

4 files changed

+96
-15
lines changed

src/evo/deterministicmns.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,6 +1213,8 @@ static bool CheckService(const ProTx& proTx, TxValidationState& state)
12131213
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-netinfo-addr-type");
12141214
case NetInfoStatus::NotRoutable:
12151215
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-netinfo-addr-unroutable");
1216+
case NetInfoStatus::Malformed:
1217+
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-netinfo-bad");
12161218
case NetInfoStatus::Success:
12171219
return true;
12181220
// Shouldn't be possible during self-checks

src/evo/netinfo.cpp

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,11 @@ NetInfoStatus MnNetInfo::ValidateService(const CService& service)
163163

164164
NetInfoStatus MnNetInfo::AddEntry(const std::string& input)
165165
{
166-
if (auto service = Lookup(input, /*portDefault=*/Params().GetDefaultPort(), /*fAllowLookup=*/false);
167-
service.has_value()) {
168-
const auto ret = ValidateService(service.value());
166+
if (auto service_opt{Lookup(input, /*portDefault=*/Params().GetDefaultPort(), /*fAllowLookup=*/false)}) {
167+
const auto ret{ValidateService(*service_opt)};
169168
if (ret == NetInfoStatus::Success) {
170-
m_addr = service.value();
171-
ASSERT_IF_DEBUG(m_addr != empty_service);
169+
m_addr = NetInfoEntry{*service_opt};
170+
ASSERT_IF_DEBUG(GetPrimary() != empty_service);
172171
}
173172
return ret;
174173
}
@@ -179,18 +178,34 @@ CServiceList MnNetInfo::GetEntries() const
179178
{
180179
CServiceList ret;
181180
if (!IsEmpty()) {
182-
ASSERT_IF_DEBUG(m_addr != empty_service);
183-
ret.push_back(m_addr);
181+
ASSERT_IF_DEBUG(GetPrimary() != empty_service);
182+
ret.push_back(GetPrimary());
184183
}
185184
// If MnNetInfo is empty, we probably don't expect any entries to show up, so
186185
// we return a blank set instead.
187186
return ret;
188187
}
189188

189+
const CService& MnNetInfo::GetPrimary() const
190+
{
191+
if (const auto& service_opt{m_addr.GetAddrPort()}) {
192+
return *service_opt;
193+
}
194+
return empty_service;
195+
}
196+
197+
NetInfoStatus MnNetInfo::Validate() const
198+
{
199+
if (!m_addr.IsTriviallyValid()) {
200+
return NetInfoStatus::Malformed;
201+
}
202+
return ValidateService(GetPrimary());
203+
}
204+
190205
std::string MnNetInfo::ToString() const
191206
{
192207
// Extra padding to account for padding done by the calling function.
193208
return strprintf("MnNetInfo()\n"
194-
" CService(addr=%s, port=%u)\n",
195-
m_addr.ToStringAddr(), m_addr.GetPort());
209+
" %s\n",
210+
m_addr.ToString());
196211
}

src/evo/netinfo.h

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ enum class NetInfoStatus : uint8_t {
2222
BadPort,
2323
BadType,
2424
NotRoutable,
25+
Malformed,
2526

2627
Success
2728
};
@@ -39,6 +40,8 @@ constexpr std::string_view NISToString(const NetInfoStatus code)
3940
return "invalid address type";
4041
case NetInfoStatus::NotRoutable:
4142
return "unroutable address";
43+
case NetInfoStatus::Malformed:
44+
return "malformed";
4245
case NetInfoStatus::Success:
4346
return "success";
4447
} // no default case, so the compiler can warn about missing cases
@@ -121,7 +124,7 @@ using CServiceList = std::vector<std::reference_wrapper<const CService>>;
121124
class MnNetInfo
122125
{
123126
private:
124-
CService m_addr{};
127+
NetInfoEntry m_addr{};
125128

126129
private:
127130
static NetInfoStatus ValidateService(const CService& service);
@@ -133,20 +136,38 @@ class MnNetInfo
133136
bool operator==(const MnNetInfo& rhs) const { return m_addr == rhs.m_addr; }
134137
bool operator!=(const MnNetInfo& rhs) const { return !(*this == rhs); }
135138

136-
SERIALIZE_METHODS(MnNetInfo, obj)
139+
template <typename Stream>
140+
void Serialize(Stream& s) const
141+
{
142+
if (const auto& service{m_addr.GetAddrPort()}; service.has_value()) {
143+
s << service->get();
144+
} else {
145+
s << CService{};
146+
}
147+
}
148+
149+
void Serialize(CSizeComputer& s) const
150+
{
151+
s.seek(::GetSerializeSize(CService{}, s.GetVersion()));
152+
}
153+
154+
template <typename Stream>
155+
void Unserialize(Stream& s)
137156
{
138-
READWRITE(obj.m_addr);
157+
CService service;
158+
s >> service;
159+
m_addr = NetInfoEntry{service};
139160
}
140161

141162
NetInfoStatus AddEntry(const std::string& service);
142163
CServiceList GetEntries() const;
143164

144-
const CService& GetPrimary() const { return m_addr; }
165+
const CService& GetPrimary() const;
145166
bool IsEmpty() const { return *this == MnNetInfo(); }
146-
NetInfoStatus Validate() const { return ValidateService(m_addr); }
167+
NetInfoStatus Validate() const;
147168
std::string ToString() const;
148169

149-
void Clear() { m_addr = CService(); }
170+
void Clear() { m_addr.Clear(); }
150171
};
151172

152173
#endif // BITCOIN_EVO_NETINFO_H

src/test/evo_netinfo_tests.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,11 @@ BOOST_AUTO_TEST_CASE(mnnetinfo_rules)
4949
MnNetInfo netInfo;
5050
BOOST_CHECK_EQUAL(netInfo.AddEntry(input), expected_ret);
5151
if (expected_ret != NetInfoStatus::Success) {
52+
// An empty MnNetInfo is considered malformed
53+
BOOST_CHECK_EQUAL(netInfo.Validate(), NetInfoStatus::Malformed);
5254
BOOST_CHECK(netInfo.GetEntries().empty());
5355
} else {
56+
BOOST_CHECK_EQUAL(netInfo.Validate(), NetInfoStatus::Success);
5457
ValidateGetEntries(netInfo.GetEntries(), /*expected_size=*/1);
5558
}
5659
}
@@ -160,4 +163,44 @@ BOOST_AUTO_TEST_CASE(netinfo_retvals)
160163
BOOST_CHECK(entry < entry_empty);
161164
}
162165

166+
bool CheckIfSerSame(const CService& lhs, const MnNetInfo& rhs)
167+
{
168+
CHashWriter ss_lhs(SER_GETHASH, 0), ss_rhs(SER_GETHASH, 0);
169+
ss_lhs << lhs;
170+
ss_rhs << rhs;
171+
return ss_lhs.GetSHA256() == ss_rhs.GetSHA256();
172+
}
173+
174+
BOOST_AUTO_TEST_CASE(cservice_compatible)
175+
{
176+
// Empty values should be the same
177+
CService service;
178+
MnNetInfo netInfo;
179+
BOOST_CHECK(CheckIfSerSame(service, netInfo));
180+
181+
// Valid IPv4 address, valid port
182+
service = LookupNumeric("1.1.1.1", 9999);
183+
netInfo.Clear();
184+
BOOST_CHECK_EQUAL(netInfo.AddEntry("1.1.1.1:9999"), NetInfoStatus::Success);
185+
BOOST_CHECK(CheckIfSerSame(service, netInfo));
186+
187+
// Valid IPv4 address, default P2P port implied
188+
service = LookupNumeric("1.1.1.1", Params().GetDefaultPort());
189+
netInfo.Clear();
190+
BOOST_CHECK_EQUAL(netInfo.AddEntry("1.1.1.1"), NetInfoStatus::Success);
191+
BOOST_CHECK(CheckIfSerSame(service, netInfo));
192+
193+
// Lookup() failure (domains not allowed), MnNetInfo should remain empty if Lookup() failed
194+
service = CService();
195+
netInfo.Clear();
196+
BOOST_CHECK_EQUAL(netInfo.AddEntry("example.com"), NetInfoStatus::BadInput);
197+
BOOST_CHECK(CheckIfSerSame(service, netInfo));
198+
199+
// Validation failure (non-IPv4 not allowed), MnNetInfo should remain empty if ValidateService() failed
200+
service = CService();
201+
netInfo.Clear();
202+
BOOST_CHECK_EQUAL(netInfo.AddEntry("[2606:4700:4700::1111]:9999"), NetInfoStatus::BadType);
203+
BOOST_CHECK(CheckIfSerSame(service, netInfo));
204+
}
205+
163206
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)