Make the prover verification work
This commit is contained in:
parent
b336087da8
commit
edfe8d183b
26
prover.py
26
prover.py
@ -13,24 +13,22 @@ protocolInitializationPhaseId = input('protocolInitializationPhaseId: ')
|
||||
# To ensure that this data is cheaper to store than to generate and to allow public verifiability by requiring the stored data to be Proof of Works.
|
||||
# For the ease of this implementation, the data are stored in the memory instead of the disk.
|
||||
|
||||
# Could rename `STORED_DATA` to what it is actually storing.
|
||||
STORED_DATA = []
|
||||
STORED_NONCES = []
|
||||
counter = 0
|
||||
lastCounter = 0
|
||||
|
||||
LEAST_DIFFICULT_HASH = int('F' * (common.SECURITY_PARAMETER // 4), 16)
|
||||
|
||||
# We enforce `STORED_DATA` to have its length being a power of 2, to ease Merkle tree implementation.
|
||||
while len(STORED_DATA) < common.ENTRIES_NUMBER:
|
||||
# We enforce `STORED_NONCES` to have its length being a power of 2, to ease Merkle tree implementation.
|
||||
while len(STORED_NONCES) < common.ENTRIES_NUMBER:
|
||||
hashed = common.hash(protocolInitializationPhaseId + str(counter))
|
||||
hashedInteger = int(hashed, 16)
|
||||
hashedDifficulty = hashedInteger / LEAST_DIFFICULT_HASH
|
||||
if hashedDifficulty <= common.MAXIMUM_HASH_DIFFICULTY:
|
||||
deltaCounter = counter - lastCounter
|
||||
deltaCounterBits = common.numberOfBitsOf(deltaCounter)
|
||||
STORED_DATA += [deltaCounter]
|
||||
STORED_NONCES += [deltaCounter]
|
||||
lastCounter = counter
|
||||
print(len(STORED_DATA), common.ENTRIES_NUMBER)
|
||||
print(len(STORED_NONCES), common.ENTRIES_NUMBER)
|
||||
counter += 1
|
||||
|
||||
## Execution phase: 1. Receive a random bitstring from the verifier.
|
||||
@ -49,7 +47,7 @@ def getNextMerkleTreeLevel(nodes):
|
||||
|
||||
merkleTreeLevel = []
|
||||
counter = 0
|
||||
for deltaCounter in STORED_DATA:
|
||||
for deltaCounter in STORED_NONCES:
|
||||
counter += deltaCounter
|
||||
hashed = common.hash(protocolInitializationPhaseId + protocolExecutionPhaseId + str(counter))
|
||||
merkleTreeLevel += [hashed]
|
||||
@ -74,17 +72,15 @@ indexesRequest = ast.literal_eval(input('indexesRequest: '))
|
||||
# Then just transmit the hashes of these indexes, as the verifier can compute these indexes on its own.
|
||||
# Then proceed to the Merkle tree root validation. Designing this first to make sure transmit in the easiest way make sense.
|
||||
|
||||
# Note that should avoid repeating already needed index, for instance if request 0 and 2 then it requires also 1 and 3 on the first level but on the second level it would be bad to mention twice on the above level 0 and 1. Let's don't care about this detail for this prototype.
|
||||
|
||||
# Using an array of dict to keep array-lookup by indexes without wasting empty memory seems to make sense.
|
||||
|
||||
# For verifying treat level by level
|
||||
|
||||
# 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.
|
||||
|
||||
# Could also proceed index by index by providing entry and siblings up to the root for each index.
|
||||
# Could use page 28 of FlyClient: Super-Light Clients for Cryptocurrencies for the implementation.
|
||||
|
||||
verificationMerkleTreeLevels = [{} for _ in range(common.LEVELS)]
|
||||
|
||||
for indexRequest in indexesRequest:
|
||||
@ -110,12 +106,12 @@ for verificationMerkleTreeLevelsIndex, verificationMerkleTreeLevel in enumerate(
|
||||
if verificationMerkleTreeLevelsIndex > 0 or leftIndex == index:
|
||||
if verificationMerkleTreeLevelsIndex == 0:
|
||||
print(leftIndex, rightIndex)
|
||||
#entries += [leftHash, rightHash]
|
||||
entries += [leftHash, rightHash]
|
||||
# for i, hash in zip([leftIndex, rightIndex], [leftHash, rightHash]):
|
||||
# verificationMerkleTreeLevels[verificationMerkleTreeLevelsIndex][i] = hash
|
||||
else:
|
||||
print(otherIndex)
|
||||
#entries += [otherHash]
|
||||
entries += [otherHash]
|
||||
# verificationMerkleTreeLevels[verificationMerkleTreeLevelsIndex][otherIndex] = otherHash
|
||||
|
||||
print(f'{entries=}')
|
||||
|
26
verifier.py
26
verifier.py
@ -3,6 +3,8 @@
|
||||
import secrets, common, ast
|
||||
|
||||
# Propose a probability of confidence setting is left for future work.
|
||||
# Is actually a fraction giving a constant probability of confidence no matter the number of entries? I mean doesn't a constant number of entries to verify doesn't provide such a constant probability even for various number of entries?
|
||||
# Have to address this scalability issue.
|
||||
FRACTION_OF_SPACE_TO_VERIFY = 10 ** -2
|
||||
|
||||
## Initialization phase: Generate a random bitstring to send to the prover.
|
||||
@ -42,7 +44,7 @@ print(f'{indexesRequest=}')
|
||||
# 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
|
||||
# TODO: verify hash difficulty - requires to send actual nonces
|
||||
# Proceeding in a minimum number of passes could be interesting but this can be left for future work.
|
||||
|
||||
entries = ast.literal_eval(input('entries: '))
|
||||
@ -52,25 +54,24 @@ 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)]):
|
||||
for i, hash in zip([leftIndex, rightIndex], [entries.pop(0) for _ in range(2)]):
|
||||
merkleTreeLevels[0][i] = hash
|
||||
|
||||
for merkleTreeLevelsIndex, merkleTreeLevel in enumerate(merkleTreeLevels[:-1]):
|
||||
print(merkleTreeLevelsIndex)
|
||||
print('before', merkleTreeLevels[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()
|
||||
if merkleTreeLevelsIndex > 0:
|
||||
print(f'current: {otherIndex}')
|
||||
merkleTreeLevels[merkleTreeLevelsIndex][otherIndex] = entries.pop(0)
|
||||
leftHash, rightHash = [merkleTreeLevels[merkleTreeLevelsIndex][i] for i in [leftIndex, rightIndex]]
|
||||
for i, hash in zip([leftIndex // 2, common.otherIndex(leftIndex)], [common.hash(leftHash + rightHash), '']):
|
||||
merkleTreeLevels[merkleTreeLevelsIndex + 1][leftIndex // 2] = common.hash(leftHash + rightHash)
|
||||
"""for i, hash in zip([leftIndex // 2, common.otherIndex(leftIndex)], [common.hash(leftHash + rightHash), '']):
|
||||
print(f'next: {i}')
|
||||
merkleTreeLevels[merkleTreeLevelsIndex + 1][i] = hash
|
||||
merkleTreeLevels[merkleTreeLevelsIndex + 1][i] = hash"""
|
||||
print('after', merkleTreeLevels[merkleTreeLevelsIndex])
|
||||
|
||||
"""
|
||||
for merkleTreeLevelsIndex, merkleTreeLevel in enumerate(merkleTreeLevels[:-1]):
|
||||
@ -87,7 +88,8 @@ for merkleTreeLevelsIndex, merkleTreeLevel in enumerate(merkleTreeLevels[:-1]):
|
||||
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)')
|
||||
# Could precise the probability.
|
||||
print(f'Verified with some probability that the prover is storing in average {common.SPACE_TO_PROVE_IN_BITS} (actually the prover is storing in average {actualStorage} bits)')
|
||||
else:
|
||||
print("The prover hasn't provided a correct proof!")
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user