Skip to content

Instantly share code, notes, and snippets.

@redjade
Last active May 19, 2021 08:05
Show Gist options
  • Save redjade/735e8ca49d9c727496fe770492ac77c0 to your computer and use it in GitHub Desktop.
Save redjade/735e8ca49d9c727496fe770492ac77c0 to your computer and use it in GitHub Desktop.
proof of space winning percentage check
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