Fix #2, fix #7 but now face issue #8 for `̀PROBABILITY_TO_CATCH_MALICIOUS = 1 - 2 ** -50

This commit is contained in:
Benjamin Loison 2023-05-16 20:58:45 +02:00
parent e81b8da855
commit 2196afc414
No known key found for this signature in database
3 changed files with 36 additions and 16 deletions

View File

@ -2,20 +2,34 @@ import math
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.
# Note that notably `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
INITIAL_SPACE_TO_PROVE_IN_BITS = 10_000
SPACE_TO_PROVE_IN_BITS = 10_000
LEAST_DIFFICULT_HASH = int('F' * (SECURITY_PARAMETER // 4), 16)
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)
PROBABILITY_TO_CATCH_MALICIOUS = 1 - 2 ** -1
# Let's hardcode that we dedicate 1% of extra storage for the proof probability.
SPACE_UPPER_BOUND_IN_BITS_POTENTIALLY_MALICIOUS = math.ceil(SPACE_TO_PROVE_IN_BITS / 100)
PROBABILITY_NOT_TO_CATCH_MALICIOUS_WITH_ONE_QUERY = (SPACE_TO_PROVE_IN_BITS - SPACE_UPPER_BOUND_IN_BITS_POTENTIALLY_MALICIOUS) / SPACE_TO_PROVE_IN_BITS
NUMBER_OF_BITS_TO_VERIFY = math.ceil(math.log(1 - PROBABILITY_TO_CATCH_MALICIOUS) / math.log(PROBABILITY_NOT_TO_CATCH_MALICIOUS_WITH_ONE_QUERY))
NUMBER_OF_ENTRIES_TO_VERIFY = math.ceil(NUMBER_OF_BITS_TO_VERIFY / NUMBER_OF_BITS_IN_AVERAGE_FOR_SOLVING_PUZZLE)
SPACE_TO_PROVE_IN_BITS = math.ceil(SPACE_TO_PROVE_IN_BITS + SPACE_UPPER_BOUND_IN_BITS_POTENTIALLY_MALICIOUS)
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
# Do we have a problem due to length extension attacks? If so, could sha256 one more time as in Bitcoin.
def hash(x):
return sha256(x.encode('ascii')).hexdigest()

View File

@ -62,7 +62,8 @@ print(f'{merkleTreeRoot=}')
## Execution phase: 3. Receive a random set of indexes from the verifier.
indexesRequest = ast.literal_eval(input('indexesRequest: '))
with open(input('indexesRequest: ')) as f:
indexesRequest = ast.literal_eval(f.read())
## Execution phase: 4. Respond with the corresponding table entries and commitment openings.
@ -103,5 +104,10 @@ for verificationMerkleTreeLevelsIndex, verificationMerkleTreeLevel in enumerate(
else:
entries += [otherHash]
print(f'{entries=}')
entriesFilePath = 'entries.txt'
with open(entriesFilePath, 'w') as f:
f.write(str(entries))
print(f'entries: {entriesFilePath}')

View File

@ -4,11 +4,6 @@
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.
# To make sure that the following protocol execution can't be used partially or totally by the prover to reduce the cost of another protocol execution.
@ -35,11 +30,16 @@ merkleTreeRoot = input('merkleTreeRoot: ')
indexesRequest = set()
while len(indexesRequest) < common.ENTRIES_NUMBER * FRACTION_OF_SPACE_TO_VERIFY:
while len(indexesRequest) < common.NUMBER_OF_ENTRIES_TO_VERIFY:
index = secrets.randbelow(common.ENTRIES_NUMBER)
indexesRequest.add(index)
print(f'{indexesRequest=}')
indexesRequestFilePath = 'indexesRequest.txt'
with open(indexesRequestFilePath, 'w') as f:
f.write(str(indexesRequest))
print(f'indexesRequest: {indexesRequestFilePath}')
## Execution phase: 4. Receive and verify corresponding table entries and commitment openings.
@ -48,7 +48,8 @@ print(f'{indexesRequest=}')
# Proceeding in a minimum number of passes could be interesting but this can be left for future work.
entries = ast.literal_eval(input('entries: '))
with open(input('entries: ')) as f:
entries = ast.literal_eval(f.read())
merkleTreeLevels = [{} for _ in range(common.LEVELS)]
@ -58,7 +59,7 @@ for index in indexesRequest:
for i, nonce in zip([leftIndex, rightIndex], [entries.pop(0) for _ in range(2)]):
hashed = common.hash(protocolInitializationPhaseId + str(nonce))
if not common.doesHashMatchDifficulty(hashed):
print("The received difficulty doesn't match the claimed one!'")
print("The received difficulty doesn't match the claimed one!")
exit(1)
merkleTreeLevels[0][i] = common.hash(protocolInitializationPhaseId + protocolExecutionPhaseId + str(nonce))
@ -76,8 +77,7 @@ 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:
# 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)')
print(f'Verified with probability {common.PROBABILITY_TO_CATCH_MALICIOUS} that the prover is storing in average {common.INITIAL_SPACE_TO_PROVE_IN_BITS} (actually the prover is storing in average {actualStorage} bits)')
else:
print("The prover hasn't provided a correct proof!")