diff --git a/gittensor/validator/pat_handler.py b/gittensor/validator/pat_handler.py index 7b9f6aa7..ea73dcf6 100644 --- a/gittensor/validator/pat_handler.py +++ b/gittensor/validator/pat_handler.py @@ -101,6 +101,14 @@ async def priority_pat_broadcast(validator: 'Validator', synapse: PatBroadcastSy async def handle_pat_check(validator: 'Validator', synapse: PatCheckSynapse) -> PatCheckSynapse: """Check if the validator has the miner's PAT stored and re-validate it.""" hotkey = _get_hotkey(synapse) + + if hotkey not in validator.metagraph.hotkeys: + synapse.has_pat = False + synapse.pat_valid = False + synapse.rejection_reason = 'Hotkey not registered on subnet' + bt.logging.warning(f'PAT check rejected — hotkey {hotkey[:16]}... not registered') + return synapse + uid = validator.metagraph.hotkeys.index(hotkey) entry = pat_storage.get_pat_by_uid(uid) diff --git a/tests/validator/test_pat_handler.py b/tests/validator/test_pat_handler.py index 49839bdb..ad9ebfe3 100644 --- a/tests/validator/test_pat_handler.py +++ b/tests/validator/test_pat_handler.py @@ -223,3 +223,11 @@ def test_stored_but_invalid_pat(self, mock_validate, mock_test_query, mock_valid assert result.has_pat is True assert result.pat_valid is False assert 'PAT expired' in (result.rejection_reason or '') + + def test_unregistered_hotkey_returns_no_pat(self, mock_validator): + """handle_pat_check must not raise ValueError for unregistered hotkeys.""" + synapse = _make_check_synapse('unknown_hotkey') + result = _run(handle_pat_check(mock_validator, synapse)) + assert result.has_pat is False + assert result.pat_valid is False + assert 'not registered' in (result.rejection_reason or '').lower()