Skip to content

Commit 7aba759

Browse files
committed
evo: disallow setting PLATFORM_{HTTPS,P2P} without setting CORE_P2P
1 parent f635abc commit 7aba759

File tree

4 files changed

+53
-6
lines changed

4 files changed

+53
-6
lines changed

src/evo/deterministicmns.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,6 +1193,8 @@ static bool CheckService(const ProTx& proTx, TxValidationState& state)
11931193
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-netinfo-addr-unroutable");
11941194
case NetInfoStatus::Malformed:
11951195
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-netinfo-bad");
1196+
case NetInfoStatus::MissingData:
1197+
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-netinfo-missing-data");
11961198
case NetInfoStatus::Success:
11971199
return true;
11981200
// Shouldn't be possible during self-checks

src/evo/netinfo.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,10 @@ NetInfoStatus ExtNetInfo::ProcessCandidate(const uint8_t purpose, const NetInfoE
357357
entries.push_back(candidate);
358358
return NetInfoStatus::Success;
359359
} else {
360+
if (purpose != Purpose::CORE_P2P && m_data.find(Purpose::CORE_P2P) == m_data.end()) {
361+
// May not register with any other purpose code if CORE_P2P is not defined first
362+
return NetInfoStatus::MissingData;
363+
}
360364
// First entry for purpose code, create new entries list
361365
auto [_, status] = m_data.try_emplace(purpose, std::vector<NetInfoEntry>({candidate}));
362366
assert(status); // We did just check to see if our value already existed, try_emplace shouldn't fail
@@ -492,6 +496,7 @@ NetInfoStatus ExtNetInfo::Validate() const
492496
// Exact duplicates are prohibited *across* lists
493497
return NetInfoStatus::Duplicate;
494498
}
499+
const bool has_core_p2p{m_data.find(Purpose::CORE_P2P) != m_data.end()};
495500
for (const auto& [purpose, entries] : m_data) {
496501
if (!IsValidPurpose(purpose)) {
497502
return NetInfoStatus::Malformed;
@@ -500,6 +505,10 @@ NetInfoStatus ExtNetInfo::Validate() const
500505
// Purpose if present in map must have at least one entry
501506
return NetInfoStatus::Malformed;
502507
}
508+
if (purpose != Purpose::CORE_P2P && !has_core_p2p) {
509+
// Other purpose codes may only be defined *after* CORE_P2P
510+
return NetInfoStatus::MissingData;
511+
}
503512
if (HasDuplicates(&entries)) {
504513
// Partial duplicates are prohibited *within* a list
505514
return NetInfoStatus::Duplicate;

src/evo/netinfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ enum class NetInfoStatus : uint8_t {
3131
BadType,
3232
NotRoutable,
3333
Malformed,
34+
MissingData,
3435

3536
Success
3637
};
@@ -52,6 +53,8 @@ constexpr std::string_view NISToString(const NetInfoStatus code)
5253
return "unroutable address";
5354
case NetInfoStatus::Malformed:
5455
return "malformed";
56+
case NetInfoStatus::MissingData:
57+
return "missing data";
5558
case NetInfoStatus::MaxLimit:
5659
return "too many entries";
5760
case NetInfoStatus::Success:

src/test/evo_netinfo_tests.cpp

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,16 +96,27 @@ void TestExtNetInfo(const TestVectors& vals)
9696
for (const auto& [input, _, expected_ret] : vals) {
9797
const auto& [purpose, addr] = input;
9898
ExtNetInfo netInfo;
99+
if (purpose != Purpose::CORE_P2P) {
100+
// Entries could get rejected because a CORE_P2P entry wasn't added first, we'll do it for them
101+
BOOST_CHECK_EQUAL(netInfo.AddEntry(Purpose::CORE_P2P, strprintf("1.1.1.1:%u", Params().GetDefaultPort())), NetInfoStatus::Success);
102+
}
99103
BOOST_CHECK_EQUAL(netInfo.AddEntry(purpose, addr), expected_ret);
100104
if (expected_ret != NetInfoStatus::Success) {
101-
// An empty ExtNetInfo is considered malformed
102-
BOOST_CHECK_EQUAL(netInfo.Validate(), NetInfoStatus::Malformed);
103-
BOOST_CHECK(!netInfo.HasEntries(purpose));
104-
BOOST_CHECK(netInfo.GetEntries().empty());
105+
if (purpose != Purpose::CORE_P2P) {
106+
// The dummy entry makes the constructed ExtNetInfo valid
107+
BOOST_CHECK_EQUAL(netInfo.Validate(), NetInfoStatus::Success);
108+
BOOST_CHECK(!netInfo.HasEntries(purpose));
109+
ValidateGetEntries(netInfo.GetEntries(), /*expected_size=*/1);
110+
} else {
111+
// An empty ExtNetInfo is considered malformed
112+
BOOST_CHECK_EQUAL(netInfo.Validate(), NetInfoStatus::Malformed);
113+
BOOST_CHECK(!netInfo.HasEntries(purpose));
114+
BOOST_CHECK(netInfo.GetEntries().empty());
115+
}
105116
} else {
106117
BOOST_CHECK_EQUAL(netInfo.Validate(), NetInfoStatus::Success);
107118
BOOST_CHECK(netInfo.HasEntries(purpose));
108-
ValidateGetEntries(netInfo.GetEntries(), /*expected_size=*/1);
119+
ValidateGetEntries(netInfo.GetEntries(), /*expected_size=*/purpose == Purpose::CORE_P2P ? 1 : 2);
109120
}
110121
}
111122
}
@@ -124,7 +135,29 @@ BOOST_AUTO_TEST_CASE(mnnetinfo_rules_main)
124135
}
125136
}
126137

127-
BOOST_AUTO_TEST_CASE(extnetinfo_rules_main) { TestExtNetInfo(vals_main); }
138+
BOOST_AUTO_TEST_CASE(extnetinfo_rules_main)
139+
{
140+
TestExtNetInfo(vals_main);
141+
142+
{
143+
// ExtNetInfo requires adding a CORE_P2P entry before adding an entry for any other purpose
144+
ExtNetInfo netInfo;
145+
BOOST_CHECK_EQUAL(netInfo.AddEntry(Purpose::PLATFORM_HTTPS, "1.1.1.1:443"), NetInfoStatus::MissingData);
146+
BOOST_CHECK_EQUAL(netInfo.AddEntry(Purpose::PLATFORM_P2P, "1.1.1.1:26656"), NetInfoStatus::MissingData);
147+
148+
// Emptiness checks
149+
BOOST_CHECK_EQUAL(netInfo.Validate(), NetInfoStatus::Malformed);
150+
BOOST_CHECK(netInfo.IsEmpty() && netInfo.GetEntries().empty());
151+
152+
BOOST_CHECK_EQUAL(netInfo.AddEntry(Purpose::CORE_P2P, "1.1.1.1:9999"), NetInfoStatus::Success);
153+
BOOST_CHECK_EQUAL(netInfo.AddEntry(Purpose::PLATFORM_HTTPS, "1.1.1.1:443"), NetInfoStatus::Success);
154+
BOOST_CHECK_EQUAL(netInfo.AddEntry(Purpose::PLATFORM_P2P, "1.1.1.1:26656"), NetInfoStatus::Success);
155+
156+
// Presence checks
157+
BOOST_CHECK_EQUAL(netInfo.Validate(), NetInfoStatus::Success);
158+
ValidateGetEntries(netInfo.GetEntries(), /*expected_size=*/3);
159+
}
160+
}
128161

129162
static const TestVectors vals_reg{
130163
// - MnNetInfo doesn't mind using port 0

0 commit comments

Comments
 (0)