From 7076fb2b759fe2d8135a9c1523af5f90494c59b2 Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Wed, 14 Feb 2024 17:18:05 +0800 Subject: [PATCH 1/3] Handle `integer_squareroot` bound case --- specs/phase0/beacon-chain.md | 3 +++ .../test/phase0/unittests/math/__init__.py | 0 .../unittests/math/test_integer_squareroot.py | 23 +++++++++++++++++++ 3 files changed, 26 insertions(+) create mode 100644 tests/core/pyspec/eth2spec/test/phase0/unittests/math/__init__.py create mode 100644 tests/core/pyspec/eth2spec/test/phase0/unittests/math/test_integer_squareroot.py diff --git a/specs/phase0/beacon-chain.md b/specs/phase0/beacon-chain.md index bdfb078380..536bba3364 100644 --- a/specs/phase0/beacon-chain.md +++ b/specs/phase0/beacon-chain.md @@ -178,6 +178,7 @@ The following values are (non-configurable) constants used throughout the specif | Name | Value | | - | - | +| `MAX_UINT_64` | `uint64(2**64 - 1)` | | `GENESIS_SLOT` | `Slot(0)` | | `GENESIS_EPOCH` | `Epoch(0)` | | `FAR_FUTURE_EPOCH` | `Epoch(2**64 - 1)` | @@ -599,6 +600,8 @@ def integer_squareroot(n: uint64) -> uint64: """ Return the largest integer ``x`` such that ``x**2 <= n``. """ + if n == MAX_UINT_64: + return uint64(4294967295) x = n y = (x + 1) // 2 while y < x: diff --git a/tests/core/pyspec/eth2spec/test/phase0/unittests/math/__init__.py b/tests/core/pyspec/eth2spec/test/phase0/unittests/math/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/core/pyspec/eth2spec/test/phase0/unittests/math/test_integer_squareroot.py b/tests/core/pyspec/eth2spec/test/phase0/unittests/math/test_integer_squareroot.py new file mode 100644 index 0000000000..988de1657c --- /dev/null +++ b/tests/core/pyspec/eth2spec/test/phase0/unittests/math/test_integer_squareroot.py @@ -0,0 +1,23 @@ +import random +from math import isqrt +from eth2spec.test.context import ( + spec_test, + single_phase, + with_all_phases, +) + + +@with_all_phases +@spec_test +@single_phase +def test_integer_squareroot(spec): + values = [0, 100, 2**64 - 2, 2**64 - 1] + for n in values: + uint64_n = spec.uint64(n) + assert spec.integer_squareroot(uint64_n) == isqrt(n) + + rng = random.Random(5566) + for _ in range(10): + n = rng.randint(0, 2**64 - 1) + uint64_n = spec.uint64(n) + assert spec.integer_squareroot(uint64_n) == isqrt(n) From 42bc6004e58f71960276a86feb10164735652035 Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Wed, 14 Feb 2024 22:26:58 +0800 Subject: [PATCH 2/3] Add overflow case --- .../test/phase0/unittests/math/test_integer_squareroot.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/core/pyspec/eth2spec/test/phase0/unittests/math/test_integer_squareroot.py b/tests/core/pyspec/eth2spec/test/phase0/unittests/math/test_integer_squareroot.py index 988de1657c..159f3c9b94 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/unittests/math/test_integer_squareroot.py +++ b/tests/core/pyspec/eth2spec/test/phase0/unittests/math/test_integer_squareroot.py @@ -21,3 +21,9 @@ def test_integer_squareroot(spec): n = rng.randint(0, 2**64 - 1) uint64_n = spec.uint64(n) assert spec.integer_squareroot(uint64_n) == isqrt(n) + + try: + spec.integer_squareroot(spec.uint64(2**64)) + assert False + except ValueError: + pass From e3d91d8e2a4f319dc4dcc3a5ea7f8264d2b569e0 Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Thu, 15 Feb 2024 15:00:56 +0800 Subject: [PATCH 3/3] Rename `MAX_UINT_64` -> `UINT64_MAX` --- specs/phase0/beacon-chain.md | 4 ++-- .../pyspec/eth2spec/test/helpers/constants.py | 2 +- .../unittests/test_config_invariants.py | 22 +++++++++---------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/specs/phase0/beacon-chain.md b/specs/phase0/beacon-chain.md index 536bba3364..572f46246c 100644 --- a/specs/phase0/beacon-chain.md +++ b/specs/phase0/beacon-chain.md @@ -178,7 +178,7 @@ The following values are (non-configurable) constants used throughout the specif | Name | Value | | - | - | -| `MAX_UINT_64` | `uint64(2**64 - 1)` | +| `UINT64_MAX` | `uint64(2**64 - 1)` | | `GENESIS_SLOT` | `Slot(0)` | | `GENESIS_EPOCH` | `Epoch(0)` | | `FAR_FUTURE_EPOCH` | `Epoch(2**64 - 1)` | @@ -600,7 +600,7 @@ def integer_squareroot(n: uint64) -> uint64: """ Return the largest integer ``x`` such that ``x**2 <= n``. """ - if n == MAX_UINT_64: + if n == UINT64_MAX: return uint64(4294967295) x = n y = (x + 1) // 2 diff --git a/tests/core/pyspec/eth2spec/test/helpers/constants.py b/tests/core/pyspec/eth2spec/test/helpers/constants.py index fc939ce097..a51201906c 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/constants.py +++ b/tests/core/pyspec/eth2spec/test/helpers/constants.py @@ -89,4 +89,4 @@ # # Number # -MAX_UINT_64 = 2**64 - 1 +UINT64_MAX = 2**64 - 1 diff --git a/tests/core/pyspec/eth2spec/test/phase0/unittests/test_config_invariants.py b/tests/core/pyspec/eth2spec/test/phase0/unittests/test_config_invariants.py index 6216ea2f00..c58f817f7d 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/unittests/test_config_invariants.py +++ b/tests/core/pyspec/eth2spec/test/phase0/unittests/test_config_invariants.py @@ -2,7 +2,7 @@ spec_state_test, with_all_phases, ) -from eth2spec.test.helpers.constants import MAX_UINT_64 +from eth2spec.test.helpers.constants import UINT64_MAX from eth2spec.test.helpers.forks import ( is_post_altair, is_post_bellatrix, ) @@ -16,9 +16,9 @@ def check_bound(value, lower_bound, upper_bound): @with_all_phases @spec_state_test def test_validators(spec, state): - check_bound(spec.VALIDATOR_REGISTRY_LIMIT, 1, MAX_UINT_64) - check_bound(spec.MAX_COMMITTEES_PER_SLOT, 1, MAX_UINT_64) - check_bound(spec.TARGET_COMMITTEE_SIZE, 1, MAX_UINT_64) + check_bound(spec.VALIDATOR_REGISTRY_LIMIT, 1, UINT64_MAX) + check_bound(spec.MAX_COMMITTEES_PER_SLOT, 1, UINT64_MAX) + check_bound(spec.TARGET_COMMITTEE_SIZE, 1, UINT64_MAX) # Note: can be less if you assume stricters bounds on validator set based on total ETH supply maximum_validators_per_committee = ( @@ -30,24 +30,24 @@ def test_validators(spec, state): check_bound(spec.config.MIN_PER_EPOCH_CHURN_LIMIT, 1, spec.VALIDATOR_REGISTRY_LIMIT) check_bound(spec.config.CHURN_LIMIT_QUOTIENT, 1, spec.VALIDATOR_REGISTRY_LIMIT) - check_bound(spec.config.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT, spec.TARGET_COMMITTEE_SIZE, MAX_UINT_64) + check_bound(spec.config.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT, spec.TARGET_COMMITTEE_SIZE, UINT64_MAX) @with_all_phases @spec_state_test def test_balances(spec, state): assert spec.MAX_EFFECTIVE_BALANCE % spec.EFFECTIVE_BALANCE_INCREMENT == 0 - check_bound(spec.MIN_DEPOSIT_AMOUNT, 1, MAX_UINT_64) - check_bound(spec.MAX_EFFECTIVE_BALANCE, spec.MIN_DEPOSIT_AMOUNT, MAX_UINT_64) - check_bound(spec.MAX_EFFECTIVE_BALANCE, spec.EFFECTIVE_BALANCE_INCREMENT, MAX_UINT_64) + check_bound(spec.MIN_DEPOSIT_AMOUNT, 1, UINT64_MAX) + check_bound(spec.MAX_EFFECTIVE_BALANCE, spec.MIN_DEPOSIT_AMOUNT, UINT64_MAX) + check_bound(spec.MAX_EFFECTIVE_BALANCE, spec.EFFECTIVE_BALANCE_INCREMENT, UINT64_MAX) @with_all_phases @spec_state_test def test_hysteresis_quotient(spec, state): - check_bound(spec.HYSTERESIS_QUOTIENT, 1, MAX_UINT_64) + check_bound(spec.HYSTERESIS_QUOTIENT, 1, UINT64_MAX) check_bound(spec.HYSTERESIS_DOWNWARD_MULTIPLIER, 1, spec.HYSTERESIS_QUOTIENT) - check_bound(spec.HYSTERESIS_UPWARD_MULTIPLIER, spec.HYSTERESIS_QUOTIENT, MAX_UINT_64) + check_bound(spec.HYSTERESIS_UPWARD_MULTIPLIER, spec.HYSTERESIS_QUOTIENT, UINT64_MAX) @with_all_phases @@ -68,7 +68,7 @@ def test_time(spec, state): assert spec.SLOTS_PER_EPOCH <= spec.SLOTS_PER_HISTORICAL_ROOT assert spec.MIN_SEED_LOOKAHEAD < spec.MAX_SEED_LOOKAHEAD assert spec.SLOTS_PER_HISTORICAL_ROOT % spec.SLOTS_PER_EPOCH == 0 - check_bound(spec.SLOTS_PER_HISTORICAL_ROOT, spec.SLOTS_PER_EPOCH, MAX_UINT_64) + check_bound(spec.SLOTS_PER_HISTORICAL_ROOT, spec.SLOTS_PER_EPOCH, UINT64_MAX) check_bound(spec.MIN_ATTESTATION_INCLUSION_DELAY, 1, spec.SLOTS_PER_EPOCH)