Files
@ e6752944fe6b
Branch filter:
Location: Morevna/src/hashtree.py - annotation
e6752944fe6b
2.0 KiB
text/x-python
hashtree loading and saving
34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 e6752944fe6b 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 e6752944fe6b e6752944fe6b e6752944fe6b e6752944fe6b e6752944fe6b e6752944fe6b e6752944fe6b e6752944fe6b e6752944fe6b e6752944fe6b e6752944fe6b e6752944fe6b e6752944fe6b e6752944fe6b e6752944fe6b e6752944fe6b e6752944fe6b 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 34f4027c1bd6 | import hashlib
import os
class HashTree:
HASH_LEN=16 # bytes
BLOCK_SIZE=4096 # bytes
## Prepares a tree containing leafCount leaves.
def __init__(self,leafCount):
self.store=[b""]*(leafCount*2-1)
self.leafStart=leafCount-1
self.index=self.leafStart
self.leafCount=leafCount
@classmethod
def fromFile(cls,fd):
stat=os.fstat(fd.fileno())
size=stat.st_size # !! symlinks
leafCount=(size-1)//HashTree.BLOCK_SIZE+1 # number of leaf blocks
res=cls(leafCount)
for i in range(leafCount):
data=fd.read(HashTree.BLOCK_SIZE)
res.insertLeaf(hashlib.sha256(data).digest()[HashTree.HASH_LEN:])
res.buildTree()
return res
@classmethod
def load(cls,filename):
with open(filename,"rb") as f:
stat=os.fstat(f.fileno())
size=stat.st_size
nodeCount=size//HashTree.HASH_LEN
res=cls((nodeCount+1)//2)
for i in range(nodeCount):
res.store[i]=f.read(HashTree.HASH_LEN)
def save(self,filename):
with open(filename,"wb") as f:
for h in self.store:
f.write(h)
## Inserts a leaf at the first empty position.
#
# Useful and used only during the tree construction.
def insertLeaf(self,h):
self.store[self.index]=h
self.index+=1
## Updates a hash stored in the leaf.
def updateLeaf(self,index,h):
if index<self.leafStart: raise IndexError()
self.store[index]=h
self.updateNode((index-1)//2)
## Updates the node at index and all its ancestors.
def updateNode(self,index):
while index>=0:
self.store[index]=hashlib.sha256(self.store[index*2+1]+self.store[index*2+2]).digest()[HashTree.HASH_LEN:]
index=(index-1)//2
## Fast construction of the tree over the leaves. O(n).
def buildTree(self):
for i in range(self.leafStart-1,-1,-1):
self.store[i]=hashlib.sha256(self.store[i*2+1]+self.store[i*2+2]).digest()[HashTree.HASH_LEN:]
if __name__=="__main__":
f1=HashTree.fromFile(open("serverFile.txt",mode='rb'))
f2=HashTree.fromFile(open("clientFile.txt",mode='rb'))
for i,(h1,h2) in enumerate(zip(f1.store,f2.store)):
print("{0:2}".format(i),h1.hex(),h2.hex(),h1==h2)
|