Skip to content

Commit 8e191eb

Browse files
Merge #7303: refactor: drop dependency of spork manager on network code
4e6f844 refactor: collapse spork signer recovery to one ECDSA op, restore peer info in logs (UdjinM6) 6a4ee52 fix: replace assert to if-return. Less probability to get troubles in the future (Konstantin Akimov) 7460211 refactor: address review feedback on spork ProcessMessage refactor (UdjinM6) 7c899a2 refactor: drop dependency of spork manager on network code (Konstantin Akimov) bd2bff1 refactor: move network implementation of spork to net_processing (Konstantin Akimov) Pull request description: ## Issue being fixed or feature implemented It helps to break circular dependencies over spork <-> net. It helps to get spork manager ready kernel project. Apparantly, chainstate implementation uses sporks for validation of blockchain but network dependencies could be avoided there. This changes is PR-ready changes from #7234 for spork manager. ## What was done? Dropped dependency of spork manager on network code by moving network code to net_processing. There's no need dedicated NetHandler because imlementation is trivial, short and doesn't have any async worker or threads. ## How Has This Been Tested? Run unit & functional tests. ## Breaking Changes N/A ## Checklist: - [x] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone ACKs for top commit: PastaPastaPasta: utACK 4e6f844 Tree-SHA512: 5b06e49c716cf66b66ffe9902fa0f987d0492236b87c45eb285d30def49a2bc66f8ef21b0ae4372465de4598b02f17605c5e127bab79bf2f35c83f0e819b7caf
2 parents f4f0b49 + 4e6f844 commit 8e191eb

4 files changed

Lines changed: 63 additions & 65 deletions

File tree

src/net_processing.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5462,6 +5462,35 @@ void PeerManagerImpl::ProcessMessage(
54625462
return;
54635463
}
54645464

5465+
if (msg_type == NetMsgType::SPORK) {
5466+
CSporkMessage spork;
5467+
vRecv >> spork;
5468+
5469+
uint256 hash = spork.GetHash();
5470+
CInv spork_inv{MSG_SPORK, hash};
5471+
WITH_LOCK(::cs_main, EraseObjectRequest(pfrom.GetId(), spork_inv));
5472+
auto opt_signer = m_sporkman.GetValidSporkSigner(spork);
5473+
if (!opt_signer) {
5474+
Misbehaving(pfrom.GetId(), 100, strprintf("invalid spork received. peer=%d", pfrom.GetId()));
5475+
return;
5476+
}
5477+
if (m_sporkman.ProcessSpork(spork, *opt_signer, strprintf(" peer=%d", pfrom.GetId()))) {
5478+
RelayInv(spork_inv);
5479+
}
5480+
return;
5481+
}
5482+
5483+
if (msg_type == NetMsgType::GETSPORKS) {
5484+
// For 'getsporks', active sporks is sent to the requesting peer.
5485+
auto active_sporks = m_sporkman.ActiveSporks();
5486+
for (const auto& pair : active_sporks) {
5487+
for (const auto& signerSporkPair : pair.second) {
5488+
m_connman.PushMessage(&pfrom, CNetMsgMaker(pfrom.GetCommonVersion()).Make(NetMsgType::SPORK, signerSporkPair.second));
5489+
}
5490+
}
5491+
return;
5492+
}
5493+
54655494
if (msg_type == NetMsgType::QUORUMROTATIONINFO) {
54665495
// we have never requested this
54675496
Misbehaving(pfrom.GetId(), 100, strprintf("received not-requested quorumrotationinfo. peer=%d", pfrom.GetId()));
@@ -5508,7 +5537,6 @@ void PeerManagerImpl::ProcessMessage(
55085537
PostProcessMessage(m_cj_walletman->processMessage(pfrom, m_chainman.ActiveChainstate(), m_connman, m_mempool, msg_type, vRecv), pfrom.GetId());
55095538
}
55105539
PostProcessMessage(DKGSessionProcessMessage(pfrom, is_masternode, msg_type, vRecv), pfrom.GetId());
5511-
PostProcessMessage(m_sporkman.ProcessMessage(pfrom, m_connman, msg_type, vRecv), pfrom.GetId());
55125540
PostProcessMessage(CMNAuth::ProcessMessage(pfrom, peer->m_their_services, m_connman, m_mn_metaman, (m_active_ctx ? m_active_ctx->nodeman.get() : nullptr), m_mn_sync, m_dmnman->GetListAtChainTip(), msg_type, vRecv), pfrom.GetId());
55135541
PostProcessMessage(m_llmq_ctx->quorum_block_processor->ProcessMessage(pfrom, msg_type, vRecv), pfrom.GetId());
55145542
PostProcessMessage(ProcessPlatformBanMessage(pfrom.GetId(), msg_type, vRecv), pfrom.GetId());

src/spork.cpp

Lines changed: 18 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,15 @@
44

55
#include <spork.h>
66

7-
#include <flat-database.h>
8-
#include <util/helpers.h>
9-
107
#include <chainparams.h>
8+
#include <flat-database.h>
119
#include <key_io.h>
1210
#include <logging.h>
1311
#include <messagesigner.h>
14-
#include <net.h>
15-
#include <netmessagemaker.h>
1612
#include <protocol.h>
1713
#include <script/standard.h>
1814
#include <timedata.h>
15+
#include <util/helpers.h>
1916
#include <util/message.h> // for MESSAGE_MAGIC
2017
#include <util/string.h>
2118

@@ -126,51 +123,35 @@ void CSporkManager::CheckAndRemove()
126123
}
127124
}
128125

129-
MessageProcessingResult CSporkManager::ProcessMessage(CNode& peer, CConnman& connman, std::string_view msg_type, CDataStream& vRecv)
130-
{
131-
if (msg_type == NetMsgType::SPORK) {
132-
return ProcessSpork(peer.GetId(), vRecv);
133-
} else if (msg_type == NetMsgType::GETSPORKS) {
134-
ProcessGetSporks(peer, connman);
135-
}
136-
return {};
137-
}
138-
139-
MessageProcessingResult CSporkManager::ProcessSpork(NodeId from, CDataStream& vRecv)
126+
std::optional<CKeyID> CSporkManager::GetValidSporkSigner(const CSporkMessage& spork) const
140127
{
141-
CSporkMessage spork;
142-
vRecv >> spork;
143-
144-
uint256 hash = spork.GetHash();
145-
146-
MessageProcessingResult ret{};
147-
ret.m_to_erase = CInv{MSG_SPORK, hash};
148-
149128
if (spork.nTimeSigned > GetAdjustedTime() + 2 * 60 * 60) {
150-
LogPrint(BCLog::SPORK, "CSporkManager::ProcessSpork -- ERROR: too far into the future\n");
151-
ret.m_error = MisbehavingError{100};
152-
return ret;
129+
LogPrint(BCLog::SPORK, "CSporkManager::%s -- ERROR: too far into the future\n", __func__);
130+
return std::nullopt;
153131
}
154132

155133
auto opt_keyIDSigner = spork.GetSignerKeyID();
156134

157135
if (opt_keyIDSigner == std::nullopt || WITH_LOCK(cs, return !setSporkPubKeyIDs.count(*opt_keyIDSigner))) {
158-
LogPrint(BCLog::SPORK, "CSporkManager::ProcessSpork -- ERROR: invalid signature\n");
159-
ret.m_error = MisbehavingError{100};
160-
return ret;
136+
LogPrint(BCLog::SPORK, "CSporkManager::%s -- ERROR: invalid signature\n", __func__);
137+
return std::nullopt;
161138
}
139+
return opt_keyIDSigner;
140+
}
162141

163-
std::string strLogMsg{strprintf("SPORK -- hash: %s id: %d value: %10d peer=%d", hash.ToString(), spork.nSporkID,
164-
spork.nValue, from)};
165-
auto keyIDSigner = *opt_keyIDSigner;
142+
bool CSporkManager::ProcessSpork(const CSporkMessage& spork, const CKeyID& keyIDSigner, std::string_view peer_log_suffix)
143+
{
144+
uint256 hash = spork.GetHash();
145+
std::string strLogMsg{strprintf("SPORK -- hash: %s id: %d value: %10d%s", hash.ToString(), spork.nSporkID,
146+
spork.nValue, peer_log_suffix)};
166147

167148
{
168149
LOCK(cs); // make sure to not lock this together with cs_main
169150
if (mapSporksActive.count(spork.nSporkID)) {
170151
if (mapSporksActive[spork.nSporkID].count(keyIDSigner)) {
171152
if (mapSporksActive[spork.nSporkID][keyIDSigner].nTimeSigned >= spork.nTimeSigned) {
172153
LogPrint(BCLog::SPORK, "%s seen\n", strLogMsg);
173-
return ret;
154+
return false;
174155
} else {
175156
LogPrintf("%s updated\n", strLogMsg);
176157
}
@@ -191,21 +172,15 @@ MessageProcessingResult CSporkManager::ProcessSpork(NodeId from, CDataStream& vR
191172
}
192173
}
193174

194-
ret.m_inventory.emplace_back(MSG_SPORK, hash);
195-
return ret;
175+
return true;
196176
}
197177

198-
void CSporkManager::ProcessGetSporks(CNode& peer, CConnman& connman)
178+
std::unordered_map<SporkId, std::map<CKeyID, CSporkMessage>> CSporkManager::ActiveSporks() const
199179
{
200180
LOCK(cs); // make sure to not lock this together with cs_main
201-
for (const auto& pair : mapSporksActive) {
202-
for (const auto& signerSporkPair : pair.second) {
203-
connman.PushMessage(&peer, CNetMsgMaker(peer.GetCommonVersion()).Make(NetMsgType::SPORK, signerSporkPair.second));
204-
}
205-
}
181+
return mapSporksActive;
206182
}
207183

208-
209184
std::optional<CInv> CSporkManager::UpdateSpork(SporkId nSporkID, SporkValue nValue)
210185
{
211186
CSporkMessage spork(nSporkID, nValue, GetAdjustedTime());

src/spork.h

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,23 @@
55
#ifndef BITCOIN_SPORK_H
66
#define BITCOIN_SPORK_H
77

8-
#include <msg_result.h>
9-
108
#include <hash.h>
119
#include <key.h>
12-
#include <net.h>
13-
#include <net_types.h>
1410
#include <pubkey.h>
1511
#include <saltedhasher.h>
1612
#include <sync.h>
17-
#include <uint256.h>
1813

1914
#include <array>
2015
#include <optional>
2116
#include <string_view>
2217
#include <unordered_map>
2318
#include <vector>
2419

25-
class CConnman;
2620
template<typename T>
2721
class CFlatDB;
28-
class CNode;
2922
class CDataStream;
23+
class uint256;
24+
class CInv;
3025

3126
class CSporkMessage;
3227
class CSporkManager;
@@ -249,26 +244,27 @@ class CSporkManager : public SporkStore
249244
void CheckAndRemove() EXCLUSIVE_LOCKS_REQUIRED(!cs);
250245

251246
/**
252-
* ProcessMessage is used to call ProcessSpork and ProcessGetSporks. See below
247+
* GetValidSporkSigner validates signed time and recovers the signer pubkey.
248+
* Returns the signer's CKeyID on success, or std::nullopt if the spork is invalid
249+
* (peer should be punished in that case).
253250
*/
254-
[[nodiscard]] MessageProcessingResult ProcessMessage(CNode& peer, CConnman& connman, std::string_view msg_type,
255-
CDataStream& vRecv) EXCLUSIVE_LOCKS_REQUIRED(!cs_cache);
256-
251+
[[nodiscard]] std::optional<CKeyID> GetValidSporkSigner(const CSporkMessage& spork) const
252+
EXCLUSIVE_LOCKS_REQUIRED(!cs);
257253
/**
258-
* ProcessSpork is used to handle the 'spork' p2p message.
259-
*
260-
* For 'spork', it validates the spork and adds it to the internal spork storage and
261-
* performs any necessary processing.
254+
* ProcessSpork adds the spork to local state. Returns true if the spork was new or
255+
* updated and should be relayed. `keyIDSigner` must be the signer key previously
256+
* recovered via GetValidSporkSigner. `peer_log_suffix` is appended to log lines for
257+
* cross-referencing with the source peer (e.g. " peer=42").
262258
*/
263-
[[nodiscard]] MessageProcessingResult ProcessSpork(NodeId from, CDataStream& vRecv)
259+
[[nodiscard]] bool ProcessSpork(const CSporkMessage& spork, const CKeyID& keyIDSigner,
260+
std::string_view peer_log_suffix = {})
264261
EXCLUSIVE_LOCKS_REQUIRED(!cs, !cs_cache);
265262

266263
/**
267-
* ProcessGetSporks is used to handle the 'getsporks' p2p message.
268-
*
269-
* For 'getsporks', it sends active sporks to the requesting peer.
264+
* ActiveSporks returns a snapshot of currently active sporks indexed by SporkId then
265+
* signer CKeyID. Used by net_processing to answer the 'getsporks' p2p message.
270266
*/
271-
void ProcessGetSporks(CNode& peer, CConnman& connman) EXCLUSIVE_LOCKS_REQUIRED(!cs);
267+
std::unordered_map<SporkId, std::map<CKeyID, CSporkMessage>> ActiveSporks() const EXCLUSIVE_LOCKS_REQUIRED(!cs);
272268

273269
/**
274270
* UpdateSpork is used by the spork RPC command to set a new spork value, sign

test/lint/lint-circular-dependencies.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
# Dash
2424
"active/context -> active/dkgsessionhandler -> llmq/dkgsessionhandler -> net_processing -> active/context",
2525
"banman -> common/bloom -> evo/assetlocktx -> llmq/quorumsman -> llmq/blockprocessor -> net -> banman",
26-
"chainlock/chainlock -> spork -> net -> evo/deterministicmns -> evo/providertx -> validation -> chainlock/chainlock",
2726
"coinjoin/client -> coinjoin/util -> wallet/wallet -> psbt -> node/transaction -> net_processing -> coinjoin/walletman -> coinjoin/client",
2827
"common/bloom -> evo/assetlocktx -> llmq/commitment -> evo/deterministicmns -> evo/simplifiedmns -> merkleblock -> common/bloom",
2928
"common/bloom -> evo/assetlocktx -> llmq/quorumsman -> llmq/blockprocessor -> net -> common/bloom",

0 commit comments

Comments
 (0)