Repository navigation
fix: guard against zero stakes and mutable default rng in VRF #1759
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: v0.123-dev
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| from backend.consensus.vrf import get_validators_for_transaction | ||
| from unittest.mock import Mock | ||
| import pytest | ||
|
|
||
|
|
||
| def list_of_dicts_to_set(list_of_dicts: list[dict]) -> set: | ||
|
|
@@ -66,3 +67,21 @@ def choice_mock(a, p, size, replace): | |
|
|
||
| rng.choice.assert_called_once() | ||
| assert validators == [{"stake": 3}, {"stake": 2}, {"stake": 1}] | ||
|
|
||
|
|
||
| def test_get_validators_zero_stake_raises(): | ||
| """When all stakes are zero, selection should raise ValueError.""" | ||
| nodes = [{"stake": 0}, {"stake": 0}] | ||
| with pytest.raises(ValueError, match="all stakes are zero"): | ||
| get_validators_for_transaction(nodes, 1) | ||
|
|
||
|
|
||
| def test_get_validators_rng_not_shared_between_calls(): | ||
| """Each call without an explicit rng should get a fresh generator.""" | ||
| nodes = [{"stake": 1}, {"stake": 2}, {"stake": 3}] | ||
| # Call twice without passing rng — the default must be created fresh each time. | ||
| v1 = get_validators_for_transaction(nodes, 1) | ||
| v2 = get_validators_for_transaction(nodes, 1) | ||
| # Both should succeed (no shared mutable state corruption). | ||
| assert len(v1) == 1 | ||
| assert len(v2) == 1 | ||
|
Comment on lines
+83
to
+87
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Make the RNG test detect shared defaults. The test only checks result lengths. The former module-level generator would also pass these assertions. Patch 🤖 Prompt for AI Agents |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔒 Security & Privacy | 🛡️ Analyzed with Security Review | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
Repository: genlayerlabs/genlayer-studio
Length of output: 11508
🏁 Script executed:
Repository: genlayerlabs/genlayer-studio
Length of output: 195
🏁 Script executed:
Repository: genlayerlabs/genlayer-studio
Length of output: 17386
Weak Cryptography
CWE: CWE-338 — Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG)
Do not seed consensus randomness from wall-clock seconds.
Consensus callers omit
rng, so this default path is used for validator selection. Identical inputs can produce the same sequence within one second. Use VRF-derived randomness or require a caller-supplied VRF-backed generator.🤖 Prompt for AI Agents
Source: Coding guidelines