Last active
May 19, 2021 08:05
-
-
Save redjade/735e8ca49d9c727496fe770492ac77c0 to your computer and use it in GitHub Desktop.
proof of space winning percentage check
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import hashlib | |
''' | |
r = hashlib.sha256('hello'.encode()) | |
print(r.digest()) | |
''' | |
def _expected_plot_size(k): | |
""" | |
Given the plot size parameter k (which is between 32 and 59), computes the | |
expected size of the plot in bytes (times a constant factor). This is based on efficient encoding | |
of the plot, and aims to be scale agnostic, so larger plots don't | |
necessarily get more rewards per byte. The +1 is added to give half a bit more space per entry, which | |
is necessary to store the entries in the plot. | |
""" | |
return ((2 * k) + 1) * (2 ** (k - 1)) | |
def calculate_iterations_quality( | |
difficulty_constant_factor, | |
quality_string, | |
size, | |
difficulty, | |
cc_sp_output_hash): | |
""" | |
Calculates the number of iterations from the quality. This is derives as the difficulty times the constant factor | |
times a random number between 0 and 1 (based on quality string), divided by plot size. | |
""" | |
sp_quality_string = hashlib.sha256(quality_string + cc_sp_output_hash).digest() | |
iters = int(difficulty) * int(difficulty_constant_factor) * \ | |
int.from_bytes(sp_quality_string, "big", signed=False) // \ | |
(int(pow(2, 256)) * int(_expected_plot_size(size))) | |
return max(iters, 1) | |
def test_win(): | |
""" | |
Tests that the percentage of blocks won is proportional to the space of each farmer, | |
with the assumption that all farmers have access to the same VDF speed. | |
""" | |
farmer_ks = { | |
32: 800, | |
33: 400, | |
34: 200, | |
35: 100, | |
36: 100, | |
} | |
farmer_space = {k: _expected_plot_size(k) * count for k, count in farmer_ks.items()} | |
print('farmer_space') | |
print(farmer_space) | |
total_space = sum(farmer_space.values()) | |
percentage_space = {k: float(sp / total_space) for k, sp in farmer_space.items()} | |
print('percentage_space') | |
print(percentage_space) | |
wins = {k: 0 for k in farmer_ks.keys()} | |
total_slots = 50 | |
num_sps = 16 | |
sp_interval_iters = 100000000 // 32 | |
# difficulty = 5000000000000 | |
difficulty = 2 ** 42 | |
print(difficulty) | |
for slot_index in range(total_slots): | |
total_wins_in_slot = 0 | |
for sp_index in range(num_sps): | |
sp_hash = hashlib.sha256(slot_index.to_bytes(4, "big") + sp_index.to_bytes(4, "big")).digest() | |
for k, count in farmer_ks.items(): | |
for farmer_index in range(count): | |
quality = hashlib.sha256(slot_index.to_bytes(4, "big") + k.to_bytes(1, "big") + bytes(farmer_index)).digest() | |
required_iters = calculate_iterations_quality(2 ** 25, quality, k, difficulty, sp_hash) | |
if required_iters < sp_interval_iters: | |
print(slot_index, sp_index, k, farmer_index) | |
wins[k] += 1 | |
total_wins_in_slot += 1 | |
print('wins') | |
print(wins) | |
win_percentage = {k: wins[k] / sum(wins.values()) for k in farmer_ks.keys()} | |
print('win_percentage') | |
print(win_percentage) | |
for k in farmer_ks.keys(): | |
# Win rate is proportional to percentage of space | |
assert abs(win_percentage[k] - percentage_space[k]) < 0.01 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment