Correcting latest details before having a working proof verification
This commit is contained in:
parent
e58af4e3d0
commit
b336087da8
12
common.py
12
common.py
@ -3,13 +3,16 @@ from hashlib import sha256
|
||||
|
||||
SECURITY_PARAMETER = 256
|
||||
# Note that `MAXIMUM_HASH_DIFFICULTY` and `SPACE_TO_PROVE_IN_BITS` should be sent from the prover to the verifier before the second verifier initialization step. However to ease this prototype this communication isn't performed.
|
||||
# For the ease of this prototype only 1 / (2 ** n) values are supported for `MAXIMUM_HASH_DIFFICULTY`.
|
||||
MAXIMUM_HASH_DIFFICULTY = 1 / 16
|
||||
# The following space is a minimum.
|
||||
SPACE_TO_PROVE_IN_BITS = 1_000
|
||||
|
||||
ENTRIES_NUMBER = math.ceil(SPACE_TO_PROVE_IN_BITS // int(math.log2(1 / MAXIMUM_HASH_DIFFICULTY)))
|
||||
# To ease Merkle tree implementation.
|
||||
NUMBER_OF_BITS_IN_AVERAGE_FOR_SOLVING_PUZZLE = int(math.log2(1 / MAXIMUM_HASH_DIFFICULTY))
|
||||
ENTRIES_NUMBER = math.ceil(SPACE_TO_PROVE_IN_BITS // NUMBER_OF_BITS_IN_AVERAGE_FOR_SOLVING_PUZZLE)
|
||||
# To ease Merkle tree implementation use a power of 2 number of leafs.
|
||||
ENTRIES_NUMBER = 2 ** math.ceil(math.log2(ENTRIES_NUMBER))
|
||||
LEVELS = int(math.log2(ENTRIES_NUMBER)) + 1
|
||||
|
||||
def hash(x):
|
||||
return sha256(x.encode('ascii')).hexdigest()
|
||||
@ -18,4 +21,7 @@ def hash(x):
|
||||
# TODO: sure that this function is meaningly correct? cf below comment, should also consider the serialization of the actual array - should in a similar way verify `ENTRIES_NUMBER` computation
|
||||
# Have to pay attention that `0` isn't interesting us.
|
||||
def numberOfBitsOf(n):
|
||||
return math.floor(math.log2(n)) + 1
|
||||
return math.floor(math.log2(n)) + 1
|
||||
|
||||
def otherIndex(n):
|
||||
return n + (1 if n % 2 == 0 else -1)
|
48
prover.py
48
prover.py
@ -1,6 +1,6 @@
|
||||
## Proof of Space-Time prover
|
||||
|
||||
import math, common
|
||||
import math, common, ast
|
||||
|
||||
# For the ratio between storing and power:
|
||||
# Note that for a production ready system hashing speedup (as designed for Bitcoin in [AsicBoost - A Speedup for Bitcoin Mining, Dr. Timo Hanke, March 31, 2016 (rev. 5)](https://arxiv.org/pdf/1604.00575.pdf)) should be considered.
|
||||
@ -66,7 +66,7 @@ print(f'{merkleTreeRoot=}')
|
||||
|
||||
## Execution phase: 3. Receive a random set of indexes from the verifier.
|
||||
|
||||
indexesRequest = set([int(n) for n in input('indexesRequest: ')[1:-1].split(',')])
|
||||
indexesRequest = ast.literal_eval(input('indexesRequest: '))
|
||||
|
||||
## Execution phase: 4. Respond with the corresponding table entries and commitment openings.
|
||||
|
||||
@ -83,54 +83,40 @@ indexesRequest = set([int(n) for n in input('indexesRequest: ')[1:-1].split(',')
|
||||
# Can't just send the `dict`, as could fill penultimate both entries and not the previous ones, that way would end up with same Merkle tree root without providing it and without providing the given entries requested.
|
||||
# Just sending a list of hashes that the verifier fills its data structure with, as the prover generated this list.
|
||||
# So have to just verify that there's no such attack when filling the first level.
|
||||
# Verify especially my parsing even with the use of `ast.literal_eval` like the type and the size of entries and possibly subentries.
|
||||
|
||||
indexes = []
|
||||
|
||||
"""
|
||||
for indexRequest in indexesRequest:
|
||||
otherIndex = indexRequest + (1 if indexRequest % 2 == 0 else -1)
|
||||
#indexes += []
|
||||
leftIndex, rightIndex = sorted([indexRequest, otherIndex])
|
||||
#leftHash, rightHash = merkleTreeLevels[0][leftIndex], merkleTreeLevels[0][rightIndex]
|
||||
"""
|
||||
|
||||
levels = int(math.log2(common.ENTRIES_NUMBER)) + 1
|
||||
verificationMerkleTreeLevels = [{} for _ in range(levels)]
|
||||
verificationMerkleTreeLevels = [{} for _ in range(common.LEVELS)]
|
||||
|
||||
for indexRequest in indexesRequest:
|
||||
otherIndex = indexRequest + (1 if indexRequest % 2 == 0 else -1)
|
||||
otherIndex = common.otherIndex(indexRequest)
|
||||
for index in [indexRequest, otherIndex]:
|
||||
verificationMerkleTreeLevels[0][index] = merkleTreeLevels[0][index]
|
||||
|
||||
#import copy
|
||||
|
||||
#verificationMerkleTreeLevels = copy.deepcopy(merkleTreeLevels)
|
||||
|
||||
"""
|
||||
for merkleTreeLevelsIndex, merkleTreeLevel in enumerate(merkleTreeLevels):
|
||||
for i, hash in enumerate(merkleTreeLevel):
|
||||
verificationMerkleTreeLevels[merkleTreeLevelsIndex][i] = hash
|
||||
"""
|
||||
|
||||
entries = []
|
||||
for verificationMerkleTreeLevelsIndex, verificationMerkleTreeLevel in enumerate(verificationMerkleTreeLevels[:-1]):
|
||||
#print(verificationMerkleTreeLevel)
|
||||
for index in verificationMerkleTreeLevel:
|
||||
otherIndex = index + (1 if index % 2 == 0 else -1)
|
||||
otherIndex = common.otherIndex(index)
|
||||
leftIndex, rightIndex = sorted([index, otherIndex])
|
||||
#leftHash, rightHash = verificationMerkleTreeLevel[leftIndex], verificationMerkleTreeLevel[rightIndex]
|
||||
leftHash, rightHash = merkleTreeLevels[verificationMerkleTreeLevelsIndex][leftIndex], merkleTreeLevels[verificationMerkleTreeLevelsIndex][rightIndex]
|
||||
#leftHash, rightHash = [merkleTreeLevels[verificationMerkleTreeLevel][i] for i in [leftIndex, rightIndex]]
|
||||
leftHash, rightHash = [merkleTreeLevels[verificationMerkleTreeLevelsIndex][i] for i in [leftIndex, rightIndex]]
|
||||
otherHash = merkleTreeLevels[verificationMerkleTreeLevelsIndex][otherIndex]
|
||||
verificationMerkleTreeLevels[verificationMerkleTreeLevelsIndex + 1][leftIndex // 2] = common.hash(leftHash + rightHash)
|
||||
if verificationMerkleTreeLevelsIndex > 0 or leftIndex == index:
|
||||
if verificationMerkleTreeLevelsIndex == 0:
|
||||
#print(leftIndex, rightIndex)
|
||||
entries += [leftHash, rightHash]
|
||||
print(leftIndex, rightIndex)
|
||||
#entries += [leftHash, rightHash]
|
||||
# for i, hash in zip([leftIndex, rightIndex], [leftHash, rightHash]):
|
||||
# verificationMerkleTreeLevels[verificationMerkleTreeLevelsIndex][i] = hash
|
||||
else:
|
||||
#print(otherIndex)
|
||||
entries += [otherHash]
|
||||
print(otherIndex)
|
||||
#entries += [otherHash]
|
||||
# verificationMerkleTreeLevels[verificationMerkleTreeLevelsIndex][otherIndex] = otherHash
|
||||
|
||||
print(f'{entries=}')
|
||||
|
||||
# Assuming first level filled.
|
||||
|
||||
#for level in range(levels):
|
||||
|
||||
|
58
verifier.py
58
verifier.py
@ -1,8 +1,8 @@
|
||||
## Proof of Space-Time verifier
|
||||
|
||||
import secrets, common
|
||||
import secrets, common, ast
|
||||
|
||||
# Should instead propose a probability of confidence setting.
|
||||
# Propose a probability of confidence setting is left for future work.
|
||||
FRACTION_OF_SPACE_TO_VERIFY = 10 ** -2
|
||||
|
||||
## Initialization phase: Generate a random bitstring to send to the prover.
|
||||
@ -12,7 +12,7 @@ protocolInitializationPhaseId = secrets.token_hex(common.SECURITY_PARAMETER // 8
|
||||
print(f'{protocolInitializationPhaseId=}')
|
||||
|
||||
## Execution phase: 1. Generate a random bitstring to send to the prover.
|
||||
# TODO: improve step numbering
|
||||
# TODO: improve step numbering, as it's a bit unclear what step of each to run after which one
|
||||
# Wait the initialization phase termination from the prover side before starting the execution phase.
|
||||
|
||||
protocolExecutionPhaseId = secrets.token_hex(common.SECURITY_PARAMETER // 8)
|
||||
@ -39,5 +39,55 @@ print(f'{indexesRequest=}')
|
||||
|
||||
## Execution phase: 4. Receive and verify corresponding table entries and commitment openings.
|
||||
|
||||
# Use `MAXIMUM_HASH_DIFFICULTY` to estimate amount of stored data and any incorrect hash shows that the prover cheated
|
||||
# Add mentions of rationality and code its factor? or/and precise when to run initialization and execution phases
|
||||
# TODO: precising `entries` size could be interesting.
|
||||
|
||||
# TODO: verify hash difficulty
|
||||
# Proceeding in a minimum number of passes could be interesting but this can be left for future work.
|
||||
|
||||
entries = ast.literal_eval(input('entries: '))
|
||||
|
||||
merkleTreeLevels = [{} for _ in range(common.LEVELS)]
|
||||
|
||||
for index in indexesRequest:
|
||||
otherIndex = common.otherIndex(index)
|
||||
leftIndex, rightIndex = sorted([index, otherIndex])
|
||||
for i, hash in zip([leftIndex, rightIndex], [entries.pop() for _ in range(2)]):
|
||||
merkleTreeLevels[0][i] = hash
|
||||
|
||||
for merkleTreeLevelsIndex, merkleTreeLevel in enumerate(merkleTreeLevels[:-1]):
|
||||
print(merkleTreeLevelsIndex)
|
||||
for index in merkleTreeLevel.copy():
|
||||
otherIndex = common.otherIndex(index)
|
||||
leftIndex, rightIndex = sorted([index, otherIndex])
|
||||
if merkleTreeLevelsIndex > 0 or leftIndex == index:
|
||||
if merkleTreeLevelsIndex == 0:
|
||||
for i, hash in zip([leftIndex, rightIndex], [entries.pop() for _ in range(2)]):
|
||||
merkleTreeLevels[merkleTreeLevelsIndex][i] = hash
|
||||
else:
|
||||
print(f'current: {otherIndex}')
|
||||
merkleTreeLevels[merkleTreeLevelsIndex][otherIndex] = entries.pop()
|
||||
leftHash, rightHash = [merkleTreeLevels[merkleTreeLevelsIndex][i] for i in [leftIndex, rightIndex]]
|
||||
for i, hash in zip([leftIndex // 2, common.otherIndex(leftIndex)], [common.hash(leftHash + rightHash), '']):
|
||||
print(f'next: {i}')
|
||||
merkleTreeLevels[merkleTreeLevelsIndex + 1][i] = hash
|
||||
|
||||
"""
|
||||
for merkleTreeLevelsIndex, merkleTreeLevel in enumerate(merkleTreeLevels[:-1]):
|
||||
for index in merkleTreeLevel:
|
||||
otherIndex = common.otherIndex(index)
|
||||
leftIndex, rightIndex = sorted([index, otherIndex])
|
||||
leftHash, rightHash = [merkleTreeLevels[merkleTreeLevel][i] for i in [leftIndex, rightIndex]]
|
||||
otherHash = merkleTreeLevels[merkleTreeLevelsIndex][otherIndex]
|
||||
merkleTreeLevels[merkleTreeLevelsIndex + 1][leftIndex // 2] = common.hash(leftHash + rightHash)
|
||||
"""
|
||||
|
||||
# Note that `actualStorage` is the average storage that the prover should have dedicated to be able to solve this execution phase challenge.
|
||||
# If any entry corresponding to requested indexes is incorrect, the Merkle tree won't match or the verification of the claimed difficulty of the provided hash will fail.
|
||||
actualStorage = common.ENTRIES_NUMBER * common.NUMBER_OF_BITS_IN_AVERAGE_FOR_SOLVING_PUZZLE
|
||||
|
||||
if merkleTreeRoot == merkleTreeLevels[-1][0] and actualStorage >= common.SPACE_TO_PROVE_IN_BITS:
|
||||
print(f'Verified with high probability that the prover is storing {common.SPACE_TO_PROVE_IN_BITS} (actually the prover is storing {actualStorage} bits)')
|
||||
else:
|
||||
print("The prover hasn't provided a correct proof!")
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user