Skip to content

Commit 22d9e93

Browse files
committed
evo: use interface shared ptr for netInfo instead of implementation
1 parent f212caa commit 22d9e93

File tree

8 files changed

+97
-18
lines changed

8 files changed

+97
-18
lines changed

src/evo/deterministicmns.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -460,8 +460,8 @@ void CDeterministicMNList::UpdateMN(const CDeterministicMN& oldDmn, const std::s
460460
// Using this temporary map as a checkpoint to roll back to in case of any issues.
461461
decltype(mnUniquePropertyMap) mnUniquePropertyMapSaved = mnUniquePropertyMap;
462462

463-
auto updateNetInfo = [this](const CDeterministicMN& dmn, const std::shared_ptr<MnNetInfo>& oldInfo,
464-
const std::shared_ptr<MnNetInfo>& newInfo) -> std::string {
463+
auto updateNetInfo = [this](const CDeterministicMN& dmn, const std::shared_ptr<NetInfoInterface>& oldInfo,
464+
const std::shared_ptr<NetInfoInterface>& newInfo) -> std::string {
465465
if (util::shared_ptr_not_equal(oldInfo, newInfo)) {
466466
// We track each individual entry in netInfo as opposed to netInfo itself (preventing us from
467467
// using UpdateUniqueProperty()), so we need to successfully purge all old entries and insert

src/evo/deterministicmns.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ class CDeterministicMNList
386386
DMNL_NO_TEMPLATE(MnNetInfo);
387387
DMNL_NO_TEMPLATE(NetInfoEntry);
388388
DMNL_NO_TEMPLATE(NetInfoInterface);
389+
DMNL_NO_TEMPLATE(std::shared_ptr<NetInfoInterface>);
389390
#undef DMNL_NO_TEMPLATE
390391
return ::SerializeHash(v);
391392
}

src/evo/dmnstate.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class CDeterministicMNState
5555
CKeyID keyIDOwner;
5656
CBLSLazyPublicKey pubKeyOperator;
5757
CKeyID keyIDVoting;
58-
std::shared_ptr<MnNetInfo> netInfo{MakeNetInfo()};
58+
std::shared_ptr<NetInfoInterface> netInfo{NetInfoInterface::MakeNetInfo()};
5959
CScript scriptPayout;
6060
CScript scriptOperatorPayout;
6161

@@ -97,7 +97,7 @@ class CDeterministicMNState
9797
READWRITE(CBLSLazyPublicKeyVersionWrapper(const_cast<CBLSLazyPublicKey&>(obj.pubKeyOperator), obj.nVersion == ProTxVersion::LegacyBLS));
9898
READWRITE(
9999
obj.keyIDVoting,
100-
obj.netInfo,
100+
NetInfoSerWrapper(const_cast<std::shared_ptr<NetInfoInterface>&>(obj.netInfo)),
101101
obj.scriptPayout,
102102
obj.scriptOperatorPayout,
103103
obj.platformNodeID,
@@ -109,7 +109,7 @@ class CDeterministicMNState
109109
{
110110
nVersion = ProTxVersion::LegacyBLS;
111111
pubKeyOperator = CBLSLazyPublicKey();
112-
netInfo = MakeNetInfo();
112+
netInfo = NetInfoInterface::MakeNetInfo();
113113
scriptOperatorPayout = CScript();
114114
nRevocationReason = CProUpRevTx::REASON_NOT_SPECIFIED;
115115
platformNodeID = uint160();
@@ -253,6 +253,10 @@ class CDeterministicMNStateDiff
253253
SER_READ(obj, read_pubkey = true);
254254
READWRITE(CBLSLazyPublicKeyVersionWrapper(const_cast<CBLSLazyPublicKey&>(obj.state.pubKeyOperator), obj.state.nVersion == ProTxVersion::LegacyBLS));
255255
}
256+
} else if constexpr (BaseType::mask == Field_netInfo) {
257+
if (obj.fields & member.mask) {
258+
READWRITE(NetInfoSerWrapper(const_cast<std::shared_ptr<NetInfoInterface>&>(obj.state.netInfo)));
259+
}
256260
} else {
257261
if (obj.fields & member.mask) {
258262
READWRITE(member.get(obj.state));

src/evo/netinfo.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ std::string NetInfoEntry::ToStringAddrPort() const
147147
m_data);
148148
}
149149

150+
std::shared_ptr<NetInfoInterface> NetInfoInterface::MakeNetInfo()
151+
{
152+
return std::make_shared<MnNetInfo>();
153+
}
154+
150155
NetInfoStatus MnNetInfo::ValidateService(const CService& service)
151156
{
152157
if (!service.IsValid()) {

src/evo/netinfo.h

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ using NetInfoList = std::vector<std::reference_wrapper<const NetInfoEntry>>;
128128

129129
class NetInfoInterface
130130
{
131+
public:
132+
static std::shared_ptr<NetInfoInterface> MakeNetInfo();
133+
131134
public:
132135
virtual ~NetInfoInterface() = default;
133136

@@ -140,6 +143,12 @@ class NetInfoInterface
140143
virtual std::string ToString() const = 0;
141144

142145
virtual void Clear() = 0;
146+
147+
bool operator==(const NetInfoInterface& rhs) const { return typeid(*this) == typeid(rhs) && this->IsEqual(rhs); }
148+
bool operator!=(const NetInfoInterface& rhs) const { return !(*this == rhs); }
149+
150+
private:
151+
virtual bool IsEqual(const NetInfoInterface& rhs) const = 0;
143152
};
144153

145154
class MnNetInfo final : public NetInfoInterface
@@ -157,9 +166,6 @@ class MnNetInfo final : public NetInfoInterface
157166

158167
~MnNetInfo() = default;
159168

160-
bool operator==(const MnNetInfo& rhs) const { return m_addr == rhs.m_addr; }
161-
bool operator!=(const MnNetInfo& rhs) const { return !(*this == rhs); }
162-
163169
template <typename Stream>
164170
void Serialize(Stream& s) const
165171
{
@@ -187,16 +193,55 @@ class MnNetInfo final : public NetInfoInterface
187193
NetInfoList GetEntries() const override;
188194

189195
const CService& GetPrimary() const override;
190-
bool IsEmpty() const override { return *this == MnNetInfo(); }
196+
bool IsEmpty() const override { return m_addr.IsEmpty(); }
191197
NetInfoStatus Validate() const override;
192198
std::string ToString() const override;
193199

194200
void Clear() override { m_addr.Clear(); }
201+
202+
private:
203+
// operator== and operator!= are defined by the parent which then leverage the child's IsEqual() override
204+
// IsEqual() should only be called by NetInfoInterface::operator== otherwise static_cast assumption could fail
205+
bool IsEqual(const NetInfoInterface& rhs) const override
206+
{
207+
ASSERT_IF_DEBUG(typeid(*this) == typeid(rhs));
208+
const auto& rhs_obj{static_cast<const MnNetInfo&>(rhs)};
209+
return m_addr == rhs_obj.m_addr;
210+
}
195211
};
196212

197-
inline std::shared_ptr<MnNetInfo> MakeNetInfo()
213+
class NetInfoSerWrapper
198214
{
199-
return std::make_shared<MnNetInfo>();
200-
}
215+
private:
216+
std::shared_ptr<NetInfoInterface>& m_data;
217+
218+
public:
219+
NetInfoSerWrapper() = delete;
220+
NetInfoSerWrapper(const NetInfoSerWrapper&) = delete;
221+
NetInfoSerWrapper(std::shared_ptr<NetInfoInterface>& data) :
222+
m_data{data}
223+
{
224+
}
225+
226+
~NetInfoSerWrapper() = default;
227+
228+
template <typename Stream>
229+
void Serialize(Stream& s) const
230+
{
231+
if (const auto ptr{std::dynamic_pointer_cast<MnNetInfo>(m_data)}) {
232+
s << *ptr;
233+
} else {
234+
// NetInfoInterface::MakeNetInfo() supplied an unexpected implementation or we didn't call it and
235+
// are left with a nullptr. Neither should happen.
236+
assert(false);
237+
}
238+
}
239+
240+
template <typename Stream>
241+
void Unserialize(Stream& s)
242+
{
243+
m_data = std::make_shared<MnNetInfo>(deserialize, s);
244+
}
245+
};
201246

202247
#endif // BITCOIN_EVO_NETINFO_H

src/evo/providertx.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class CProRegTx
4141
MnType nType{MnType::Regular};
4242
uint16_t nMode{0}; // only 0 supported for now
4343
COutPoint collateralOutpoint{uint256(), (uint32_t)-1}; // if hash is null, we refer to a ProRegTx output
44-
std::shared_ptr<MnNetInfo> netInfo{MakeNetInfo()};
44+
std::shared_ptr<NetInfoInterface> netInfo{NetInfoInterface::MakeNetInfo()};
4545
uint160 platformNodeID{};
4646
uint16_t platformP2PPort{0};
4747
uint16_t platformHTTPPort{0};
@@ -67,7 +67,7 @@ class CProRegTx
6767
obj.nType,
6868
obj.nMode,
6969
obj.collateralOutpoint,
70-
obj.netInfo,
70+
NetInfoSerWrapper(const_cast<std::shared_ptr<NetInfoInterface>&>(obj.netInfo)),
7171
obj.keyIDOwner,
7272
CBLSLazyPublicKeyVersionWrapper(const_cast<CBLSLazyPublicKey&>(obj.pubKeyOperator), (obj.nVersion == ProTxVersion::LegacyBLS)),
7373
obj.keyIDVoting,
@@ -110,7 +110,7 @@ class CProUpServTx
110110
uint16_t nVersion{ProTxVersion::LegacyBLS}; // message version
111111
MnType nType{MnType::Regular};
112112
uint256 proTxHash;
113-
std::shared_ptr<MnNetInfo> netInfo{MakeNetInfo()};
113+
std::shared_ptr<NetInfoInterface> netInfo{NetInfoInterface::MakeNetInfo()};
114114
uint160 platformNodeID{};
115115
uint16_t platformP2PPort{0};
116116
uint16_t platformHTTPPort{0};
@@ -133,7 +133,7 @@ class CProUpServTx
133133
}
134134
READWRITE(
135135
obj.proTxHash,
136-
obj.netInfo,
136+
NetInfoSerWrapper(const_cast<std::shared_ptr<NetInfoInterface>&>(obj.netInfo)),
137137
obj.scriptOperatorPayout,
138138
obj.inputsHash
139139
);

src/evo/simplifiedmns.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class CSimplifiedMNListEntry
3636
public:
3737
uint256 proRegTxHash;
3838
uint256 confirmedHash;
39-
std::shared_ptr<MnNetInfo> netInfo{MakeNetInfo()};
39+
std::shared_ptr<NetInfoInterface> netInfo{NetInfoInterface::MakeNetInfo()};
4040
CBLSLazyPublicKey pubKeyOperator;
4141
CKeyID keyIDVoting;
4242
bool isValid{false};
@@ -77,7 +77,7 @@ class CSimplifiedMNListEntry
7777
READWRITE(
7878
obj.proRegTxHash,
7979
obj.confirmedHash,
80-
obj.netInfo,
80+
NetInfoSerWrapper(const_cast<std::shared_ptr<NetInfoInterface>&>(obj.netInfo)),
8181
CBLSLazyPublicKeyVersionWrapper(const_cast<CBLSLazyPublicKey&>(obj.pubKeyOperator), (obj.nVersion == ProTxVersion::LegacyBLS)),
8282
obj.keyIDVoting,
8383
obj.isValid

src/test/evo_netinfo_tests.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <evo/netinfo.h>
1010
#include <netbase.h>
1111
#include <streams.h>
12+
#include <util/pointer.h>
1213

1314
#include <boost/test/unit_test.hpp>
1415

@@ -214,4 +215,27 @@ BOOST_AUTO_TEST_CASE(cservice_compatible)
214215
BOOST_CHECK(CheckIfSerSame(service, netInfo));
215216
}
216217

218+
BOOST_AUTO_TEST_CASE(interface_equality)
219+
{
220+
// We also check for symmetry as NetInfoInterface, MnNetInfo and NetInfoEntry
221+
// define their operator!= as the inverse of operator==
222+
std::shared_ptr<NetInfoInterface> ptr_lhs{nullptr}, ptr_rhs{nullptr};
223+
224+
// Equal initialization state (uninitialized)
225+
BOOST_CHECK(util::shared_ptr_equal(ptr_lhs, ptr_rhs) && !util::shared_ptr_not_equal(ptr_lhs, ptr_rhs));
226+
227+
// Unequal initialization state (lhs initialized, rhs unchanged)
228+
ptr_lhs = std::make_shared<MnNetInfo>();
229+
BOOST_CHECK(!util::shared_ptr_equal(ptr_lhs, ptr_rhs) && util::shared_ptr_not_equal(ptr_lhs, ptr_rhs));
230+
231+
// Equal initialization state (lhs unchanged, rhs initialized), same values
232+
ptr_rhs = std::make_shared<MnNetInfo>();
233+
BOOST_CHECK(ptr_lhs->IsEmpty() && ptr_rhs->IsEmpty());
234+
BOOST_CHECK(util::shared_ptr_equal(ptr_lhs, ptr_rhs) && !util::shared_ptr_not_equal(ptr_lhs, ptr_rhs));
235+
236+
// Equal initialization state, same type, differing values
237+
BOOST_CHECK_EQUAL(ptr_rhs->AddEntry("1.1.1.1:9999"), NetInfoStatus::Success);
238+
BOOST_CHECK(!util::shared_ptr_equal(ptr_lhs, ptr_rhs) && util::shared_ptr_not_equal(ptr_lhs, ptr_rhs));
239+
}
240+
217241
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)