Skip to content

Commit 81524af

Browse files
committed
fix(validator): check sudo/owner FIRST before any stake validation
Subnet owner (5GziQCcRpN8NCJktX343brnfuVe3w6gUYieeStXPD1Dag2At) now bypasses ALL stake checks for ANY P2P message, not just SudoAction. This allows the owner to: - Send proposals without stake validation - Broadcast any message type during bootstrap - Bootstrap the network before validators have stake The owner's messages are pre-validated by signature, so no additional stake check is needed.
1 parent 34f65a0 commit 81524af

File tree

1 file changed

+29
-27
lines changed

1 file changed

+29
-27
lines changed

bins/validator-node/src/main.rs

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2267,41 +2267,43 @@ async fn run_validator() -> Result<()> {
22672267
None, // IP extracted separately if needed
22682268
);
22692269

2270-
// Check if we have a validator with sufficient stake
2271-
let (has_sufficient_stake, actual_stake_tao) = {
2270+
// FIRST: Check if sender is subnet owner (sudo) - bypass ALL stake checks
2271+
// During bootstrap, owner can send any message without stake validation
2272+
let is_sudo = {
22722273
let state = chain_state_clone.read();
2273-
if let Some(validator) = state.get_validator(signed.signer()) {
2274-
let actual = validator.stake.0 as f64 / 1e9;
2275-
(validator.stake.0 >= min_stake_rao, Some(actual))
2276-
} else {
2277-
// Unknown validator - check against cached stake
2278-
match protection.check_cached_stake(&signer_hex) {
2279-
Some(platform_network::StakeValidation::Valid { stake_tao }) => {
2280-
(true, Some(stake_tao))
2281-
}
2282-
Some(platform_network::StakeValidation::Insufficient { stake_tao, .. }) => {
2283-
(false, Some(stake_tao))
2284-
}
2285-
_ => {
2286-
// Not in metagraph at all
2287-
(false, None)
2288-
}
2289-
}
2290-
}
2274+
state.is_sudo(signed.signer())
22912275
};
22922276

2293-
if has_sufficient_stake {
2294-
// Forward all messages to consensus handler
2277+
if is_sudo {
2278+
// Subnet owner bypasses all stake checks - forward immediately
2279+
debug!("Accepting message from subnet owner {} (stake check bypassed)", &signer_hex[..16]);
22952280
handle_message(&consensus, signed, &chain_state_clone, challenge_orchestrator.as_ref(), challenge_routes_for_p2p.as_ref(), endpoints_for_p2p.as_ref(), db_for_p2p.as_ref(), keypair_for_p2p.as_ref(), auth_sessions_for_p2p.as_ref()).await;
22962281
} else {
2297-
// Allow Sudo to bypass stake check for bootstrapping and upgrades
2298-
let is_sudo = {
2282+
// Non-owner: validate stake normally
2283+
let (has_sufficient_stake, actual_stake_tao) = {
22992284
let state = chain_state_clone.read();
2300-
state.is_sudo(signed.signer())
2285+
if let Some(validator) = state.get_validator(signed.signer()) {
2286+
let actual = validator.stake.0 as f64 / 1e9;
2287+
(validator.stake.0 >= min_stake_rao, Some(actual))
2288+
} else {
2289+
// Unknown validator - check against cached stake
2290+
match protection.check_cached_stake(&signer_hex) {
2291+
Some(platform_network::StakeValidation::Valid { stake_tao }) => {
2292+
(true, Some(stake_tao))
2293+
}
2294+
Some(platform_network::StakeValidation::Insufficient { stake_tao, .. }) => {
2295+
(false, Some(stake_tao))
2296+
}
2297+
_ => {
2298+
// Not in metagraph at all
2299+
(false, None)
2300+
}
2301+
}
2302+
}
23012303
};
23022304

2303-
if is_sudo {
2304-
info!("Bypassing stake check for Sudo message from {}", &signer_hex[..16]);
2305+
if has_sufficient_stake {
2306+
// Forward all messages to consensus handler
23052307
handle_message(&consensus, signed, &chain_state_clone, challenge_orchestrator.as_ref(), challenge_routes_for_p2p.as_ref(), endpoints_for_p2p.as_ref(), db_for_p2p.as_ref(), keypair_for_p2p.as_ref(), auth_sessions_for_p2p.as_ref()).await;
23062308
} else {
23072309
// Show actual stake if known, otherwise indicate not in metagraph

0 commit comments

Comments
 (0)