added and implemented block time validation based on VDF time

This commit is contained in:
Kevin Froman 2020-12-13 03:49:43 +00:00
parent 3de5a46483
commit 2797334059
4 changed files with 86 additions and 16 deletions

View File

@ -0,0 +1,49 @@
import time
from kasten import Kasten, generator
from kasten.types import KastenPacked, KastenChecksum
from kasten.exceptions import InvalidID
from mimcvdf import vdf_create, vdf_verify
from onionrblocks.universalrules import check_block_sanity
class AnonVDFGenerator(generator.KastenBaseGenerator):
@classmethod
def get_ttl_seconds_per_rounds(cls, rounds: int):
# 8000 rounds = 1 second (2.8ghz python) = 1 hour storage
if rounds < 8000:
raise ValueError("Rounds must be at least 8000")
return (rounds / 8000) * 60
@classmethod
def generate(
cls, packed_bytes: KastenPacked, rounds: int = 5000) -> Kasten:
return Kasten(
vdf_create(
packed_bytes,
rounds, dec=True
).to_bytes(
64, "big"), packed_bytes, cls, auto_check_generator=False)
@staticmethod
def validate_id(
hash: KastenChecksum,
packed_bytes: KastenPacked, rounds=5000) -> None:
try:
hash = int.from_bytes(hash, byteorder="big")
except TypeError:
pass
if not vdf_verify(packed_bytes, hash, rounds):
raise InvalidID
test_obj = Kasten(
None, packed_bytes, None, auto_check_generator=False)
allowed_age_seconds = AnonVDFGenerator.get_ttl_seconds_per_rounds(
rounds)
if time.time() > test_obj.get_timestamp() + allowed_age_seconds:
raise ValueError(
f"Block rounds only vaild through {allowed_age_seconds}")
return None

View File

@ -3,7 +3,6 @@ from kasten import Kasten
from time import time from time import time
from math import floor from math import floor
MAX_AGE_SECONDS = 60 * 60 * 24 * 30
MAX_FUTURE_SKEW_SECONDS = 60 * 2 MAX_FUTURE_SKEW_SECONDS = 60 * 2
TOTAL_MAX_SIZE = 6 * (10**6) TOTAL_MAX_SIZE = 6 * (10**6)
@ -12,9 +11,6 @@ class BlockRulesException(Exception):
pass pass
class BlockOutdated(BlockRulesException):
pass
class BlockExpired(Exception): class BlockExpired(Exception):
pass pass
@ -37,14 +33,12 @@ def check_block_sanity(raw_bytes):
timestamp: int = floor(time()) timestamp: int = floor(time())
block_timestamp = kasten.get_timestamp() block_timestamp = kasten.get_timestamp()
difference = timestamp - block_timestamp difference = timestamp - block_timestamp
if difference > MAX_AGE_SECONDS:
raise BlockOutdated()
if difference < -MAX_FUTURE_SKEW_SECONDS: if difference < -MAX_FUTURE_SKEW_SECONDS:
raise BlockFutureSkewedBeyondMax() raise BlockFutureSkewedBeyondMax()
try: try:
if timestamp < block_timestamp + kasten.get_metadata()[ if block_timestamp + kasten.get_metadata()['expire'] >= timestamp:
'expire']:
raise BlockExpired() raise BlockExpired()
except (IndexError, TypeError): except (IndexError, TypeError):
pass pass

33
tests/test_anonvdf.py Normal file
View File

@ -0,0 +1,33 @@
import unittest
from onionrblocks.generators import anonvdf
import kasten
import mimcvdf
from time import time
from math import floor
class TestAnonVDF(unittest.TestCase):
def test_vdf_create(self):
test_data = kasten.generator.pack.pack(b"test", "tst", 0)
test_vdf = mimcvdf.vdf_create(test_data, 1000)
self.assertEqual(
anonvdf.AnonVDFGenerator.generate(test_data, rounds=1000).get_packed(),
test_data
)
def test_vdf_block_validate_ok_time(self):
rds = 8000
test_data = kasten.generator.pack.pack(b"test", "tst", 0)
test_id = mimcvdf.vdf_create(test_data, rds)
anonvdf.AnonVDFGenerator.validate_id(test_id, test_data, rounds=rds)
def test_vdf_block_validate_not_enough(self):
rds = 8000
t = floor(time()) - 60
test_data = kasten.generator.pack.pack(b"test", "tst", 0, timestamp=t)
test_id = mimcvdf.vdf_create(test_data, rds)
self.assertRaises(ValueError, anonvdf.AnonVDFGenerator.validate_id, test_id, test_data, rounds=rds)
unittest.main()

View File

@ -13,12 +13,6 @@ class TestUniversalRules(unittest.TestCase):
universalrules.BlockTooLarge, universalrules.BlockTooLarge,
universalrules.check_block_sanity, packed) universalrules.check_block_sanity, packed)
def test_block_too_old(self):
packed = kasten.generator.pack.pack(b"1"*10, b"tst", 0, timestamp=1000)
self.assertRaises(
universalrules.BlockOutdated,
universalrules.check_block_sanity, packed)
def test_block_future_skew_ok(self): def test_block_future_skew_ok(self):
t = floor(time()) + 120 t = floor(time()) + 120
packed = kasten.generator.pack.pack(b"1"*10, b"tst", 0, timestamp=t) packed = kasten.generator.pack.pack(b"1"*10, b"tst", 0, timestamp=t)
@ -32,14 +26,14 @@ class TestUniversalRules(unittest.TestCase):
universalrules.check_block_sanity, packed) universalrules.check_block_sanity, packed)
def test_block_not_expired(self): def test_block_not_expired(self):
packed = kasten.generator.pack.pack(b"1"*10, b"tst", 0, app_metadata={"expire": 10000}) packed = kasten.generator.pack.pack(b"1"*10, b"tst", 0, app_metadata={"expire": 7})
self.assertRaises( self.assertRaises(
universalrules.BlockExpired, universalrules.BlockExpired,
universalrules.check_block_sanity, packed) universalrules.check_block_sanity, packed)
def test_block_expired(self): def test_block_expired(self):
t = floor(time()) - 6 t = floor(time()) - 6
packed = kasten.generator.pack.pack(b"1"*10, b"tst", 0, timestamp=t, app_metadata={"expire": 5}) packed = kasten.generator.pack.pack(b"1"*10, b"tst", 0, timestamp=t, app_metadata={"expire": 6})
self.assertRaises( self.assertRaises(
universalrules.BlockExpired, universalrules.BlockExpired,
universalrules.check_block_sanity, packed) universalrules.check_block_sanity, packed)