Skip to content

Commit 737aa7d

Browse files
refactor(instantsend): extract ISLOCK message validation helpers
1 parent a842707 commit 737aa7d

File tree

2 files changed

+57
-19
lines changed

2 files changed

+57
-19
lines changed

src/instantsend/net_instantsend.cpp

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,46 @@ struct NetInstantSend::BatchVerificationData {
3232
size_t alreadyVerified{0};
3333
};
3434

35+
bool NetInstantSend::ValidateIncomingISLock(const instantsend::InstantSendLock& islock, NodeId node_id)
36+
{
37+
if (!islock.TriviallyValid()) {
38+
m_peer_manager->PeerMisbehaving(node_id, INVALID_ISLOCK_MISBEHAVIOR_SCORE);
39+
return false;
40+
}
41+
42+
return true;
43+
}
44+
45+
std::optional<int> NetInstantSend::ResolveCycleHeight(const uint256& cycle_hash)
46+
{
47+
auto cycle_height = m_is_manager.GetBlockHeight(cycle_hash);
48+
if (cycle_height) {
49+
return cycle_height;
50+
}
51+
52+
const auto block_index = WITH_LOCK(::cs_main, return m_chainstate.m_blockman.LookupBlockIndex(cycle_hash));
53+
if (block_index == nullptr) {
54+
return std::nullopt;
55+
}
56+
57+
m_is_manager.CacheBlockHeight(block_index);
58+
return block_index->nHeight;
59+
}
60+
61+
bool NetInstantSend::ValidateDeterministicCycleHeight(
62+
int cycle_height,
63+
const Consensus::LLMQParams& llmq_params,
64+
NodeId node_id)
65+
{
66+
// Deterministic islocks MUST use rotation based llmq
67+
if (cycle_height % llmq_params.dkgInterval == 0) {
68+
return true;
69+
}
70+
71+
m_peer_manager->PeerMisbehaving(node_id, INVALID_ISLOCK_MISBEHAVIOR_SCORE);
72+
return false;
73+
}
74+
3575
std::unique_ptr<NetInstantSend::BatchVerificationData> NetInstantSend::BuildVerificationBatch(
3676
const Consensus::LLMQParams& llmq_params,
3777
int signOffset,
@@ -170,42 +210,34 @@ void NetInstantSend::ProcessMessage(CNode& pfrom, const std::string& msg_type, C
170210
auto islock = std::make_shared<instantsend::InstantSendLock>();
171211
vRecv >> *islock;
172212

213+
const NodeId from = pfrom.GetId();
173214
uint256 hash = ::SerializeHash(*islock);
174215

175-
WITH_LOCK(::cs_main, m_peer_manager->PeerEraseObjectRequest(pfrom.GetId(), CInv{MSG_ISDLOCK, hash}));
216+
WITH_LOCK(::cs_main, m_peer_manager->PeerEraseObjectRequest(from, CInv{MSG_ISDLOCK, hash}));
176217

177-
if (!islock->TriviallyValid()) {
178-
m_peer_manager->PeerMisbehaving(pfrom.GetId(), INVALID_ISLOCK_MISBEHAVIOR_SCORE);
218+
if (!ValidateIncomingISLock(*islock, from)) {
179219
return;
180220
}
181221

182-
auto cycleHeightOpt = m_is_manager.GetBlockHeight(islock->cycleHash);
183-
if (!cycleHeightOpt) {
184-
const auto blockIndex = WITH_LOCK(::cs_main, return m_chainstate.m_blockman.LookupBlockIndex(islock->cycleHash));
185-
if (blockIndex == nullptr) {
186-
// Maybe we don't have the block yet or maybe some peer spams invalid values for cycleHash
187-
m_peer_manager->PeerMisbehaving(pfrom.GetId(), UNKNOWN_CYCLE_HASH_MISBEHAVIOR_SCORE);
188-
return;
189-
}
190-
m_is_manager.CacheBlockHeight(blockIndex);
191-
cycleHeightOpt = blockIndex->nHeight;
222+
auto cycle_height = ResolveCycleHeight(islock->cycleHash);
223+
if (!cycle_height) {
224+
// Maybe we don't have the block yet or maybe some peer spams invalid values for cycleHash
225+
m_peer_manager->PeerMisbehaving(from, UNKNOWN_CYCLE_HASH_MISBEHAVIOR_SCORE);
226+
return;
192227
}
193-
const int block_height = *cycleHeightOpt;
194228

195-
// Deterministic islocks MUST use rotation based llmq
196229
auto llmqType = Params().GetConsensus().llmqTypeDIP0024InstantSend;
197230
const auto& llmq_params_opt = Params().GetLLMQ(llmqType);
198231
assert(llmq_params_opt);
199-
if (block_height % llmq_params_opt->dkgInterval != 0) {
200-
m_peer_manager->PeerMisbehaving(pfrom.GetId(), INVALID_ISLOCK_MISBEHAVIOR_SCORE);
232+
if (!ValidateDeterministicCycleHeight(*cycle_height, *llmq_params_opt, from)) {
201233
return;
202234
}
203235

204236
if (!m_is_manager.AlreadyHave(CInv{MSG_ISDLOCK, hash})) {
205237
LogPrint(BCLog::INSTANTSEND, "NetInstantSend -- ISDLOCK txid=%s, islock=%s: received islock, peer=%d\n",
206-
islock->txid.ToString(), hash.ToString(), pfrom.GetId());
238+
islock->txid.ToString(), hash.ToString(), from);
207239

208-
m_is_manager.EnqueueInstantSendLock(pfrom.GetId(), hash, std::move(islock));
240+
m_is_manager.EnqueueInstantSendLock(from, hash, std::move(islock));
209241
}
210242
}
211243

src/instantsend/net_instantsend.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@
1111
#include <util/threadinterrupt.h>
1212

1313
#include <memory>
14+
#include <optional>
1415
#include <thread>
1516
#include <vector>
1617

1718
namespace Consensus {
1819
struct LLMQParams;
1920
} // namespace Consensus
2021
namespace instantsend {
22+
struct InstantSendLock;
2123
struct PendingISLockEntry;
2224
} // namespace instantsend
2325
namespace llmq {
@@ -48,6 +50,10 @@ class NetInstantSend final : public NetHandler
4850
private:
4951
struct BatchVerificationData;
5052

53+
bool ValidateIncomingISLock(const instantsend::InstantSendLock& islock, NodeId node_id);
54+
std::optional<int> ResolveCycleHeight(const uint256& cycle_hash);
55+
bool ValidateDeterministicCycleHeight(int cycle_height, const Consensus::LLMQParams& llmq_params, NodeId node_id);
56+
5157
std::unique_ptr<BatchVerificationData> BuildVerificationBatch(
5258
const Consensus::LLMQParams& llmq_params, int signOffset,
5359
const std::vector<instantsend::PendingISLockEntry>& pend);

0 commit comments

Comments
 (0)