diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a295864 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.pyc +__pycache__ diff --git a/next.py b/next.py index 137a2fb..578944f 100644 --- a/next.py +++ b/next.py @@ -1,5 +1,4 @@ -from typing import Mapping, MutableMapping, Sequence, Iterable, List, Set -import pyfuse3 +#import pyfuse3 from iota import Iota, ProposedTransaction, Address, TryteString, Tag from iota.crypto.addresses import AddressGenerator @@ -39,28 +38,31 @@ class Atom(): else: if data[1]==True: self.type = "dir" + self.milestoneIndex = data[4] else: self.type = "file" - self.size = data[5] + self.size = data[4] self.name = data[2] self.token = data[3] - self.milestoneIndex = data[4] def dump(self) -> bytes: # TODO: Delimiter? # TODO: compression? - return msgpack.dump(self._dumpAsArray()) + return msgpack.dumps(self._dumpAsArray()) def _dumpAsArray(self): if self.type=="milestone": return [True]+self.milestone else: - return [False, self.type, self.name, self.token, self.milestoneIndex, self.size] + if self.type=="file": + return [False, self.type, self.name, self.token, self.size] + else: + return [False, self.type, self.name, self.token, self.milestoneIndex] class BlobChunk(): def __init__(self, data: bytes = b'', sealed: bool = False) -> None: self.data = data - self.sealded = sealed + self.sealed = sealed def getData(self) -> bytes: return self.data @@ -89,7 +91,8 @@ class TangleBlob(): self.chunks = [] m = hashlib.sha3_512() m.update(self.token) - self.adressGen = AddressGenerator(Seed(m.digest())) + trSeed = TryteString.from_bytes(m.digest())[:81] + self.adressGen = AddressGenerator(Seed(trSeed)) self.fetched = False self.pushedNum = 0 @@ -117,12 +120,12 @@ class TangleBlob(): inputs = [addr] )['trytes'] - def _dumpChunk(self, chunkNum: int, security_level=2) -> str: + def _dumpChunk(self, chunkNum: int) -> str: key = self._getKey(chunkNum + self.preChunks) data = self.chunks[chunkNum].getData() cipher = AES.new(key[16:][:16], AES.MODE_CBC, key[:16]) ct_bytes = cipher.encrypt(pad(data, AES.block_size)) - addr = self.adressGen.get_addresses(start=chunkNum + self.preChunks, count=1, security_level=security_level)['addresses'][0] + addr = self.adressGen.get_addresses(start=chunkNum + self.preChunks, count=1)[0] return self._genBundle(ct_bytes, addr) def append(self, data: bytes, newBlock: bool = False) -> None: @@ -157,15 +160,16 @@ class TangleBlob(): data = "" for c in range(len(self.chunks)-self.pushedNum): num = c + self.pushedNum - data += self._dumpChunk(num, 2) + data += self._dumpChunk(num) # num is without preChunks + self.pushedNum = self.getChunkLen() return data - def fetch(self, security_level=2, skipChunks: int = 0) -> None: + def fetch(self, skipChunks: int = 0) -> None: chunkNum = self.getChunkLen() + skipChunks while True: key = self._getKey(chunkNum) cipher = AES.new(key[16:][:16], AES.MODE_CBC, key[:16]) - addr = self.adressGen.get_addresses(start=chunkNum, count=1, security_level=security_level)['addresses'][0] + addr = self.adressGen.get_addresses(start=chunkNum, count=1)[0] txHash = self.api.find_transactions(tags=[Tag("IOTAFS")], addresses=[addr])["hashes"] if len(txHash)==0: break @@ -184,17 +188,26 @@ class TangleBlob(): self.fetched = True self._afterFetch() - def _afterFetch() -> None: - return + def _afterFetch(self) -> None: + return + + def genToken(self) -> bytes: + return secrets.token_bytes(32) class TangleFileTreeElement(TangleBlob): - def __init__(self, token: bytes, iotaApi: Iota) -> None: - super(TangleFileTreeElement, self).__init__(token) + def __init__(self, token: bytes, parent, iotaApi: Iota) -> None: + super(TangleFileTreeElement, self).__init__(token, iotaApi) self.inodes = {} self.atomStack = -1 + self.api = iotaApi + self.parent = parent def _afterFetch(self) -> None: - data = msgpack.load(self.read()) + raw = self.read() + if raw==b'': + self.atomStack = 0 + return + data = msgpack.loads(raw, raw=True) newAtoms = [] for i, elem in enumerate(reversed(data)): atom = Atom() @@ -216,20 +229,20 @@ class TangleFileTreeElement(TangleBlob): self.inodes[atom.name] = atom def _applyAtom(self, atom: Atom) -> None: - if atom.name in self.inode: + if atom.name in self.inodes: self.atomStack += 1 self.inodes[atom.name] = atom if atom.type=="dir": - self.inodes[atom.name].elem = TangleFileTreeElement(atom.token, self.iotaApi) + self.inodes[atom.name].elem = TangleFileTreeElement(atom.token, self, self.iotaApi) elif atom.type=="file": - self.inodes[atom.name].elem = TangleFile(atom.token, self.iotaApi) + self.inodes[atom.name].elem = TangleFile(atom.name, self, self.api) else: raise Exception("How did such an atom get here?") def _newAtom(self, atom: Atom) -> None: self.append(atom.dump()) - def getNameList(self) -> List(str): + def getNameList(self): self._requireFetched() return list(self.inodes.keys()) @@ -244,7 +257,7 @@ class TangleFileTreeElement(TangleBlob): atom = Atom() atom.type="dir" atom.name = name - atom.token = "GENTOKENHERE" # TODO: < + atom.token = self.genToken() atom.milestoneIndex = 0 self._newAtom(atom) self._applyAtom(atom) @@ -257,8 +270,8 @@ class TangleFileTreeElement(TangleBlob): atom = Atom() atom.type="file" atom.name = name - atom.token = "GENTOKENHERE" # TODO: < - atom.milestoneIndex = 0 + atom.token = self.genToken() + atom.size = 0 self._newAtom(atom) self._applyAtom(atom) return True @@ -276,22 +289,24 @@ class TangleFileTreeElement(TangleBlob): def performMilestone(self): stones = [] - for atom in self.inodes: - stones.append(atom._dumpAsArray()) + for a in self.inodes: + stones.append(self.inodes[a]._dumpAsArray()) self.atomStack = 0 # TODO: Delimiter ? # TODO: compression ? - data = msgpack.dump(stones) + data = msgpack.dumps(stones) self.append(data) + # inform parent about milestone (when merged) class TangleFile(): def __init__(self, name: str, parent: TangleFileTreeElement, iotaApi: Iota) -> None: + self.api = iotaApi self.name = name self.parent = parent self.reflexiveAtom = parent.inodes[name] self.size = self.reflexiveAtom.size self.token = self.reflexiveAtom.token - super(TangleFile, self).__init__(self.token, iotaApi) + self.blob = TangleBlob(self.token, iotaApi) def write(self, offset: int, data: bytes): if offset == self.size: @@ -303,7 +318,7 @@ class TangleFile(): class IotaFs(): def __init__(self, token) -> None: self.api = Iota('https://nodes.thetangle.org:443', local_pow=True) - self.genesis = TangleFileTreeElement(token, self.api) + self.genesis = TangleFileTreeElement(token, None, self.api) log("Fetching Genesis...") self.genesis.fetch() log("Retrieving reference to root") @@ -321,3 +336,7 @@ class IotaFs(): def createNewFile(self, name) -> None: pass + +api = Iota('https://nodes.thetangle.org:443', local_pow=True) +token = b'testToken' +genesis = TangleFileTreeElement(token, None, api)