Add implementation up to (excluded) exchanging the random set of indices
This commit is contained in:
parent
11daae87ad
commit
ad82609715
@ -1 +1,8 @@
|
||||
SECURITY_PARAMETER = 256
|
||||
from hashlib import sha256
|
||||
|
||||
SECURITY_PARAMETER = 256
|
||||
MAXIMUM_HASH_DIFFICULTY = 1 / 16
|
||||
SPACE_TO_PROVE_IN_BITS = 1_000
|
||||
|
||||
def hash(x):
|
||||
return sha256(x.encode('ascii')).hexdigest()
|
66
prover.py
66
prover.py
@ -1,39 +1,75 @@
|
||||
# Proof of Space-Time prover
|
||||
## Proof of Space-Time prover
|
||||
|
||||
import math, common
|
||||
from hashlib import sha256
|
||||
|
||||
SPACE_TO_PROVE_IN_BITS = 1_000
|
||||
MAXIMUM_HASH_DIFFICULTY = 0.1
|
||||
# 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.
|
||||
|
||||
# 1. Receive a random bitstring from the verifier.
|
||||
## Initialization phase: 1. Receive a random bitstring from the verifier.
|
||||
|
||||
protocolExecutionId = input('protocolExecutionId: ')
|
||||
protocolInitializationPhaseId = input('protocolInitializationPhaseId: ')
|
||||
|
||||
# 2. Generate in a table the data that the prover has to store.
|
||||
## Initialization phase: 2. Generate in a table the data that the prover has to store.
|
||||
# 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_DATA_IN_BITS = 0
|
||||
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 STORED_DATA_IN_BITS < SPACE_TO_PROVE_IN_BITS or not math.log2(len(STORED_DATA)).is_integer():
|
||||
print(STORED_DATA_IN_BITS, len(STORED_DATA))
|
||||
# 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.
|
||||
hash = sha256((protocolExecutionId + str(counter)).encode('ascii')).hexdigest()
|
||||
hashInteger = int(hash, 16)
|
||||
hashDifficulty = hashInteger / LEAST_DIFFICULT_HASH
|
||||
if hashDifficulty <= MAXIMUM_HASH_DIFFICULTY:
|
||||
lastCounter = STORED_DATA[-1] if STORED_DATA != [] else -1
|
||||
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 = math.ceil(math.log2(deltaCounter))
|
||||
deltaCounterBits = math.floor(math.log2(deltaCounter)) + 1
|
||||
STORED_DATA += [deltaCounter]
|
||||
STORED_DATA_IN_BITS += deltaCounterBits
|
||||
print(hash, hashDifficulty, counter, lastCounter, deltaCounterBits)
|
||||
lastCounter = counter
|
||||
counter += 1
|
||||
|
||||
## Execution phase: 1. Receive a random bitstring from the verifier.
|
||||
|
||||
protocolExecutionPhaseId = input('protocolExecutionPhaseId: ')
|
||||
|
||||
## Execution phase: 2. The prover commits to the table contents given this random challenge.
|
||||
|
||||
def pairwise(iterable):
|
||||
"s -> (s0, s1), (s2, s3), (s4, s5), ..."
|
||||
a = iter(iterable)
|
||||
return zip(a, a)
|
||||
|
||||
def getNextMerkleTreeLevel(nodes):
|
||||
return [hash(leftNode + rightNode) for leftNode, rightNode in pairwise(nodes)]
|
||||
|
||||
merkleTreeLevel = []
|
||||
counter = 0
|
||||
for deltaCounter in STORED_DATA:
|
||||
counter += deltaCounter
|
||||
hashed = hash(protocolInitializationPhaseId + protocolExecutionPhaseId + str(counter))
|
||||
merkleTreeLevel += [hashed]
|
||||
|
||||
merkleTreeLevels = [merkleTreeLevel]
|
||||
|
||||
while len(merkleTreeLevels[-1]) > 1:
|
||||
nextMerkleTreeLevel = getNextMerkleTreeLevel(merkleTreeLevels[-1])
|
||||
merkleTreeLevels += [nextMerkleTreeLevel]
|
||||
|
||||
merkleTreeRoot = merkleTreeLevels[-1]
|
||||
|
||||
print(f'{merkleTreeRoot=}')
|
||||
|
||||
## Execution phase: 3. Receive a random set of indices from the prover.
|
||||
|
||||
|
||||
|
||||
## Execution phase: 4.
|
||||
|
||||
|
||||
|
32
verifier.py
32
verifier.py
@ -1,11 +1,33 @@
|
||||
# Proof of Space-Time verifier
|
||||
## Proof of Space-Time verifier
|
||||
|
||||
import secrets, common
|
||||
|
||||
# 1. Generate a random bitstring to send to the prover.
|
||||
def generateARandomHexString(hexStringLength):
|
||||
return ''.join(secrets.choice('0123456789abcdef') for _ in range(hexStringLength))
|
||||
|
||||
## 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.
|
||||
|
||||
protocolExecutionId = ''.join(secrets.choice('0123456789abcdef') for _ in range(common.SECURITY_PARAMETER // 4))
|
||||
print(protocolExecutionId)
|
||||
protocolInitializationPhaseId = generateARandomHexString(common.SECURITY_PARAMETER // 4)
|
||||
print(f'{protocolInitializationPhaseId=}')
|
||||
|
||||
## Execution phase: 1. Generate a random bitstring to send to the prover.
|
||||
# TODO: improve step numbering
|
||||
# Wait the initialization phase termination from the prover side before starting the execution phase.
|
||||
|
||||
protocolExecutionPhaseId = generateARandomHexString(common.SECURITY_PARAMETER // 4)
|
||||
print(f'{protocolExecutionPhaseId=}')
|
||||
|
||||
## Execution phase: 2. Receive the prover commitment to the table contents given this random challenge.
|
||||
|
||||
merkleTreeRoot = input('merkleTreeRoot: ')
|
||||
|
||||
## Execution phase: 3. Generate and send a random set of indices to the prover.
|
||||
|
||||
# Need to know the actual table size to choose a random set of indices. This point isn't discussed to the best of my knowledge in Simple Proofs of Space-Time and Rational Proofs of Storage, Tal Moran and Ilan Orlov, 2016.
|
||||
|
||||
|
||||
|
||||
## Execution phase: 4. Receive and verify corresponding table entries and commitment openings.
|
||||
|
||||
|
||||
# 2.
|
Loading…
Reference in New Issue
Block a user