From 82ec8dfdc29dd81cefbdd2525daf9873ae7a1a44 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sun, 30 Sep 2018 09:56:43 -0500 Subject: [PATCH 1/5] [integer-sqrt] add integer_sqrt helper function and use in rewards calculations --- specs/casper_sharding_v2.1.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/specs/casper_sharding_v2.1.md b/specs/casper_sharding_v2.1.md index 9e5f8c241..1d7b48954 100644 --- a/specs/casper_sharding_v2.1.md +++ b/specs/casper_sharding_v2.1.md @@ -282,7 +282,7 @@ Here's a diagram of what's going on: ![](http://vitalik.ca/files/ShuffleAndAssign.png?1) -We also define: +We also define two functions retrieving data from the state: ```python def get_shards_and_committees_for_slot(crystallized_state, slot): @@ -298,6 +298,18 @@ def get_block_hash(active_state, curblock, slot): `get_block_hash(*, *, h)` should always return the block in the chain at slot `h`, and `get_shards_and_committees_for_slot(*, h)` should not change unless the dynasty changes. +Finally, we define `integer_sqrt` for use in reward/penalty calculations: + +```python +def integer_sqrt(n): + x = n + y = (x + 1) // 2 + while y < x: + x = y + y = (x + n // x) // 2 + return x +``` + ### On startup * Let `x = get_new_shuffling(bytes([0] * 32), validators, 1, 0)` and set `crystallized_state.shard_and_committee_for_slots` to `x + x` @@ -375,7 +387,7 @@ For all (`shard_id`, `shard_block_hash`) tuples, compute the total deposit size Let `time_since_finality = block.slot_number - last_finalized_slot`, and let `B` be the balance of any given validator whose balance we are adjusting, not including any balance changes from this round of state recalculation. Let: * `total_deposits = sum([v.balance for i, v in enumerate(validators) if i in get_active_validator_indices(validators, current_dynasty)])` and `total_deposits_in_ETH = total_deposits // 10**18` -* `reward_quotient = BASE_REWARD_QUOTIENT * int(sqrt(total_deposits_in_ETH))` (1/this is the per-slot max interest rate) +* `reward_quotient = BASE_REWARD_QUOTIENT * integer_sqrt(total_deposits_in_ETH)` (1/this is the per-slot max interest rate) * `quadratic_penalty_quotient = (SQRT_E_DROP_TIME / SLOT_DURATION)**2` (after D slots, ~D2/2 divided by this is the portion lost by offline validators) For each slot `S` in the range `last_state_recalc - CYCLE_LENGTH ... last_state_recalc - 1`: From ec1eee41335c1f6c021f2b5fa3321281bc23cf22 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sun, 30 Sep 2018 10:04:02 -0500 Subject: [PATCH 2/5] [integer-sqrt] add comment to credit 'newton's method' --- specs/casper_sharding_v2.1.md | 1 + 1 file changed, 1 insertion(+) diff --git a/specs/casper_sharding_v2.1.md b/specs/casper_sharding_v2.1.md index 1d7b48954..9d7e1f023 100644 --- a/specs/casper_sharding_v2.1.md +++ b/specs/casper_sharding_v2.1.md @@ -302,6 +302,7 @@ Finally, we define `integer_sqrt` for use in reward/penalty calculations: ```python def integer_sqrt(n): + # Utilizes "Newton's Method" x = n y = (x + 1) // 2 while y < x: From 4cb9790ea88daa979ad8338c27029f2b1602176c Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sun, 30 Sep 2018 11:50:44 -0500 Subject: [PATCH 3/5] [integer-sqrt] use abstract def of integer_sqrt --- specs/casper_sharding_v2.1.md | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/specs/casper_sharding_v2.1.md b/specs/casper_sharding_v2.1.md index 9d7e1f023..eb6ce5ec3 100644 --- a/specs/casper_sharding_v2.1.md +++ b/specs/casper_sharding_v2.1.md @@ -298,19 +298,15 @@ def get_block_hash(active_state, curblock, slot): `get_block_hash(*, *, h)` should always return the block in the chain at slot `h`, and `get_shards_and_committees_for_slot(*, h)` should not change unless the dynasty changes. -Finally, we define `integer_sqrt` for use in reward/penalty calculations: - +Finally, we abstractly define `integer_sqrt` for use in reward/penalty calculations: ```python def integer_sqrt(n): - # Utilizes "Newton's Method" - x = n - y = (x + 1) // 2 - while y < x: - x = y - y = (x + n // x) // 2 - return x + return max(n in Z: n**2 <= x) ``` +We leave `integer_sqrt` implementation details to each particular language/framework. + + ### On startup * Let `x = get_new_shuffling(bytes([0] * 32), validators, 1, 0)` and set `crystallized_state.shard_and_committee_for_slots` to `x + x` From 2f9b8b2f08767eed7ab75db8f0649b46bb9e81f8 Mon Sep 17 00:00:00 2001 From: vbuterin Date: Sun, 30 Sep 2018 14:38:51 -0400 Subject: [PATCH 4/5] Update casper_sharding_v2.1.md --- specs/casper_sharding_v2.1.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/specs/casper_sharding_v2.1.md b/specs/casper_sharding_v2.1.md index eb6ce5ec3..80445d6dc 100644 --- a/specs/casper_sharding_v2.1.md +++ b/specs/casper_sharding_v2.1.md @@ -298,15 +298,18 @@ def get_block_hash(active_state, curblock, slot): `get_block_hash(*, *, h)` should always return the block in the chain at slot `h`, and `get_shards_and_committees_for_slot(*, h)` should not change unless the dynasty changes. -Finally, we abstractly define `integer_sqrt` for use in reward/penalty calculations: +Finally, we abstractly define `integer_sqrt(x)` for use in reward/penalty calculations as the largest integer `n` such that `n**2 <= x`. Here is one possible implementation, though clients are free to use their own including standard libraries if available. + ```python def integer_sqrt(n): - return max(n in Z: n**2 <= x) + x = n + y = (x + 1) // 2 + while y < x: + x = y + y = (x + n // x) // 2 + return x ``` -We leave `integer_sqrt` implementation details to each particular language/framework. - - ### On startup * Let `x = get_new_shuffling(bytes([0] * 32), validators, 1, 0)` and set `crystallized_state.shard_and_committee_for_slots` to `x + x` From d25f536ec5b581e903b3420403acc502c7c104fd Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sun, 30 Sep 2018 18:02:09 -0500 Subject: [PATCH 5/5] [integer-sqrt] add concrete implementation that meets the requirements --- specs/casper_sharding_v2.1.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/specs/casper_sharding_v2.1.md b/specs/casper_sharding_v2.1.md index eb6ce5ec3..7812d038d 100644 --- a/specs/casper_sharding_v2.1.md +++ b/specs/casper_sharding_v2.1.md @@ -298,13 +298,17 @@ def get_block_hash(active_state, curblock, slot): `get_block_hash(*, *, h)` should always return the block in the chain at slot `h`, and `get_shards_and_committees_for_slot(*, h)` should not change unless the dynasty changes. -Finally, we abstractly define `integer_sqrt` for use in reward/penalty calculations: +Finally, we define `int_sqrt` that for an input `n` returns `max(n in Z: n**2 <= x)`: + ```python -def integer_sqrt(n): - return max(n in Z: n**2 <= x) +def int_sqrt(n): + k = n + while True: + newk = (k + (n // k)) // 2 + if newk in (k, k+1): return k + k = newk ``` -We leave `integer_sqrt` implementation details to each particular language/framework. ### On startup @@ -384,7 +388,7 @@ For all (`shard_id`, `shard_block_hash`) tuples, compute the total deposit size Let `time_since_finality = block.slot_number - last_finalized_slot`, and let `B` be the balance of any given validator whose balance we are adjusting, not including any balance changes from this round of state recalculation. Let: * `total_deposits = sum([v.balance for i, v in enumerate(validators) if i in get_active_validator_indices(validators, current_dynasty)])` and `total_deposits_in_ETH = total_deposits // 10**18` -* `reward_quotient = BASE_REWARD_QUOTIENT * integer_sqrt(total_deposits_in_ETH)` (1/this is the per-slot max interest rate) +* `reward_quotient = BASE_REWARD_QUOTIENT * int_sqrt(total_deposits_in_ETH)` (1/this is the per-slot max interest rate) * `quadratic_penalty_quotient = (SQRT_E_DROP_TIME / SLOT_DURATION)**2` (after D slots, ~D2/2 divided by this is the portion lost by offline validators) For each slot `S` in the range `last_state_recalc - CYCLE_LENGTH ... last_state_recalc - 1`: