Skip to content

Commit a8263e7

Browse files
committed
evo: change internal type of MnNetInfo to NetInfoEntry
1 parent fa43cfb commit a8263e7

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
@@ -172,12 +172,11 @@ NetInfoStatus MnNetInfo::ValidateService(const CService& service)
172172

173173
NetInfoStatus MnNetInfo::AddEntry(const std::string& input)
174174
{
175-
if (auto service = Lookup(input, /*portDefault=*/Params().GetDefaultPort(), /*fAllowLookup=*/false);
176-
service.has_value()) {
177-
const auto ret = ValidateService(service.value());
175+
if (auto service_opt{Lookup(input, /*portDefault=*/Params().GetDefaultPort(), /*fAllowLookup=*/false)}) {
176+
const auto ret{ValidateService(*service_opt)};
178177
if (ret == NetInfoStatus::Success) {
179-
m_addr = service.value();
180-
ASSERT_IF_DEBUG(m_addr != empty_service);
178+
m_addr = NetInfoEntry{*service_opt};
179+
ASSERT_IF_DEBUG(GetPrimary() != empty_service);
181180
}
182181
return ret;
183182
}
@@ -188,18 +187,34 @@ CServiceList MnNetInfo::GetEntries() const
188187
{
189188
CServiceList ret;
190189
if (!IsEmpty()) {
191-
ASSERT_IF_DEBUG(m_addr != empty_service);
192-
ret.push_back(m_addr);
190+
ASSERT_IF_DEBUG(GetPrimary() != empty_service);
191+
ret.push_back(GetPrimary());
193192
}
194193
// If MnNetInfo is empty, we probably don't expect any entries to show up, so
195194
// we return a blank set instead.
196195
return ret;
197196
}
198197

198+
const CService& MnNetInfo::GetPrimary() const
199+
{
200+
if (const auto& service_opt{m_addr.GetAddrPort()}) {
201+
return *service_opt;
202+
}
203+
return empty_service;
204+
}
205+
206+
NetInfoStatus MnNetInfo::Validate() const
207+
{
208+
if (!m_addr.IsTriviallyValid()) {
209+
return NetInfoStatus::Malformed;
210+
}
211+
return ValidateService(GetPrimary());
212+
}
213+
199214
std::string MnNetInfo::ToString() const
200215
{
201216
// Extra padding to account for padding done by the calling function.
202217
return strprintf("MnNetInfo()\n"
203-
" CService(addr=%s, port=%u)\n",
204-
m_addr.ToStringAddr(), m_addr.GetPort());
218+
" %s\n",
219+
m_addr.ToString());
205220
}

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)