changed vdf rules to be consistent and based on real world price
This commit is contained in:
parent
0a5749fa0a
commit
1db58e923a
@ -8,26 +8,44 @@ from mimcvdf import vdf_create, vdf_verify
|
|||||||
|
|
||||||
from onionrblocks.universalrules import check_block_sanity
|
from onionrblocks.universalrules import check_block_sanity
|
||||||
|
|
||||||
|
|
||||||
|
class NotEnoughRounds(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class AnonVDFGenerator(generator.KastenBaseGenerator):
|
class AnonVDFGenerator(generator.KastenBaseGenerator):
|
||||||
@classmethod
|
|
||||||
def get_ttl_seconds_per_rounds(cls, rounds: int, size_bytes: int):
|
|
||||||
# 90000 rounds = 1 second (2.8ghz C) = 1 hour storage of 1 MB storage
|
# 90000 rounds = 1 second (2.8ghz C) = 1 hour storage of 1 MB storage
|
||||||
# jan 2021 disk price metric = 0.000017 USD per MB
|
# jan 2021 disk price metric = 0.000017 USD per MB
|
||||||
# mobile MB transfer US/Canada = 0.0125 USD
|
# mobile MB transfer US/Canada = 0.0125 USD
|
||||||
# Max cost of block storage + American mobile data transfer = 0.0751 USD
|
# Max cost of block storage + American mobile data transfer = 0.0751 USD
|
||||||
|
|
||||||
base = 90000
|
byte_cost = 1000
|
||||||
per_byte = 1000
|
second_cost = 25
|
||||||
minimum = base + (per_byte * size_bytes)
|
|
||||||
if rounds < minimum:
|
|
||||||
raise ValueError(
|
|
||||||
"Must be at least " + str(minimum) + " for " + str(size_bytes))
|
|
||||||
|
|
||||||
return (rounds / minimum) * 60
|
@classmethod
|
||||||
|
def get_rounds_for_ttl_seconds(cls, seconds: int, size_bytes: int):
|
||||||
|
return (seconds * cls.second_cost) + (size_bytes * cls.byte_cost)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_ttl_seconds_per_rounds(cls, rounds: int, size_bytes: int):
|
||||||
|
result = (rounds // cls.second_cost) - (cls.byte_cost * size_bytes)
|
||||||
|
if result < 0:
|
||||||
|
raise NotEnoughRounds
|
||||||
|
return result
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate(
|
def generate(
|
||||||
cls, packed_bytes: KastenPacked, rounds: int = 90000) -> Kasten:
|
cls, packed_bytes: KastenPacked, rounds: int = None) -> Kasten:
|
||||||
|
if not rounds:
|
||||||
|
try:
|
||||||
|
rounds = int(Kasten(
|
||||||
|
None,
|
||||||
|
packed_bytes, None,
|
||||||
|
auto_check_generator=False).get_metadata()['rds'])
|
||||||
|
except (KeyError, TypeError) as _: # noqa
|
||||||
|
raise ValueError(
|
||||||
|
"Rounds not specified either in block or as argument")
|
||||||
check_block_sanity(packed_bytes)
|
check_block_sanity(packed_bytes)
|
||||||
return Kasten(
|
return Kasten(
|
||||||
vdf_create(
|
vdf_create(
|
||||||
@ -39,10 +57,20 @@ class AnonVDFGenerator(generator.KastenBaseGenerator):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def validate_id(
|
def validate_id(
|
||||||
hash: KastenChecksum,
|
hash: KastenChecksum,
|
||||||
packed_bytes: KastenPacked, rounds=90000) -> None:
|
packed_bytes: KastenPacked, rounds: int = None) -> None:
|
||||||
|
|
||||||
check_block_sanity(packed_bytes)
|
check_block_sanity(packed_bytes)
|
||||||
|
|
||||||
|
if not rounds:
|
||||||
|
try:
|
||||||
|
rounds = int(Kasten(
|
||||||
|
None,
|
||||||
|
packed_bytes, None,
|
||||||
|
auto_check_generator=False).get_metadata()['rds'])
|
||||||
|
except (KeyError, TypeError) as _: # noqa
|
||||||
|
raise ValueError(
|
||||||
|
"Rounds not specified either in block or as argument")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
hash = int.from_bytes(hash, byteorder="big")
|
hash = int.from_bytes(hash, byteorder="big")
|
||||||
except TypeError:
|
except TypeError:
|
||||||
|
@ -52,7 +52,7 @@ def check_block_sanity(raw_bytes):
|
|||||||
try:
|
try:
|
||||||
if block_timestamp + kasten.get_metadata()['expire'] >= timestamp:
|
if block_timestamp + kasten.get_metadata()['expire'] >= timestamp:
|
||||||
raise BlockExpired()
|
raise BlockExpired()
|
||||||
except (IndexError, TypeError):
|
except (IndexError, TypeError, KeyError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ from time import time
|
|||||||
from math import floor
|
from math import floor
|
||||||
|
|
||||||
class TestAnonVDF(unittest.TestCase):
|
class TestAnonVDF(unittest.TestCase):
|
||||||
|
|
||||||
def test_vdf_create(self):
|
def test_vdf_create(self):
|
||||||
test_data = kasten.generator.pack.pack(b"test", "tst", 0)
|
test_data = kasten.generator.pack.pack(b"test", "tst", 0)
|
||||||
test_vdf = mimcvdf.vdf_create(test_data, 1000, dec=True)
|
test_vdf = mimcvdf.vdf_create(test_data, 1000, dec=True)
|
||||||
@ -19,30 +20,53 @@ class TestAnonVDF(unittest.TestCase):
|
|||||||
self.assertEqual(generated.id, int(test_vdf).to_bytes(64, byteorder="big"))
|
self.assertEqual(generated.id, int(test_vdf).to_bytes(64, byteorder="big"))
|
||||||
|
|
||||||
def test_vdf_block_validate_ok_time(self):
|
def test_vdf_block_validate_ok_time(self):
|
||||||
rds = 90000
|
rds = 0
|
||||||
test_data = kasten.generator.pack.pack(b"test", "tst", 0)
|
test_data = kasten.generator.pack.pack(b"test", "tst")
|
||||||
rds += len(test_data) * 1000
|
rds += len(test_data) * 90000
|
||||||
test_id = mimcvdf.vdf_create(test_data, rds)
|
test_id = mimcvdf.vdf_create(test_data, rds)
|
||||||
anonvdf.AnonVDFGenerator.validate_id(test_id, test_data, rounds=rds)
|
anonvdf.AnonVDFGenerator.validate_id(test_id, test_data, rounds=rds)
|
||||||
|
|
||||||
def test_vdf_block_validate_not_enough(self):
|
def test_vdf_block_validate_not_enough(self):
|
||||||
rds = 90000
|
rds = 133240
|
||||||
t = floor(time()) - 60
|
t = floor(time()) - 60
|
||||||
test_data = kasten.generator.pack.pack(b"test", "tst", 0, timestamp=t)
|
test_data = kasten.generator.pack.pack(b"test", "tst", app_metadata=None, timestamp=t)
|
||||||
test_id = mimcvdf.vdf_create(test_data, rds)
|
test_id = mimcvdf.vdf_create(test_data, rds)
|
||||||
self.assertRaises(ValueError, anonvdf.AnonVDFGenerator.validate_id, test_id, test_data, rounds=rds)
|
self.assertRaises(anonvdf.NotEnoughRounds, anonvdf.AnonVDFGenerator.validate_id, test_id, test_data, rounds=rds)
|
||||||
|
|
||||||
def test_vdf_incermental(self):
|
def test_vdf_incermental(self):
|
||||||
last = 1
|
last = 1
|
||||||
for i in range(1, 20):
|
for i in range(1, 5):
|
||||||
t = time()
|
t = time()
|
||||||
rds = 90000
|
rds = 0
|
||||||
test_data = kasten.generator.pack.pack(b"test" * i, "tst", 0)
|
test_data = kasten.generator.pack.pack(b"test" * i, "tst", 0)
|
||||||
rds += len(test_data) * 1000
|
rds += len(test_data) * 90000
|
||||||
test_id = mimcvdf.vdf_create(test_data, rds)
|
test_id = mimcvdf.vdf_create(test_data, rds)
|
||||||
anonvdf.AnonVDFGenerator.validate_id(test_id, test_data, rounds=rds)
|
anonvdf.AnonVDFGenerator.validate_id(test_id, test_data, rounds=rds)
|
||||||
newT = time()
|
newT = time()
|
||||||
self.assertGreater(newT - t, last)
|
self.assertGreater(newT - t, last)
|
||||||
|
|
||||||
|
def test_block_embedded_vdf_rounds(self):
|
||||||
|
t = floor(time())
|
||||||
|
rds = 90000 + (4000 * 1000)
|
||||||
|
test_data = kasten.generator.pack.pack(b"test", "tst", app_metadata={"rds": rds}, timestamp=t)
|
||||||
|
test_vdf = anonvdf.AnonVDFGenerator.generate(test_data, None)
|
||||||
|
anonvdf.AnonVDFGenerator.validate_id(test_vdf.id, test_data, rounds=None)
|
||||||
|
|
||||||
|
def test_block_embedded_vdf_rounds_invalid(self):
|
||||||
|
t = floor(time())
|
||||||
|
rds = 90000
|
||||||
|
test_data = kasten.generator.pack.pack(b"test", "tst", app_metadata={"rds": rds}, timestamp=t)
|
||||||
|
test_vdf = anonvdf.AnonVDFGenerator.generate(test_data, None)
|
||||||
|
|
||||||
|
self.assertRaises(
|
||||||
|
anonvdf.NotEnoughRounds,
|
||||||
|
anonvdf.AnonVDFGenerator.validate_id, test_vdf.id, test_data, rounds=None)
|
||||||
|
|
||||||
|
def test_vdf_rounds_seconds(self):
|
||||||
|
size = 10000
|
||||||
|
per_byte = 1000
|
||||||
|
per_second = 25
|
||||||
|
expected_rounds = (3600 * 25) + 100000
|
||||||
|
self.assertEqual(anonvdf.AnonVDFGenerator.get_rounds_for_ttl_seconds(3600, 100), expected_rounds)
|
||||||
|
|
||||||
unittest.main()
|
unittest.main()
|
Loading…
Reference in New Issue
Block a user