class CredDefStoreFile(CredDefStore): def __init__(self, baseDir: str, name: str): self.store = DirectoryStore(baseDir, name) @staticmethod def key(name: str, version: str, dest: str): key = "{}_{}_{}".format(name, version, dest) return base64.urlsafe_b64encode(key.encode()).decode() def addCredDef(self, name: str, version: str, dest: str, type: str, ip: str, port: int, keys: Dict): key = self.key(name, version, dest) self.store.put(key, json.dumps({ TYPE: type, IP: ip, PORT: port, KEYS: keys })) def getCredDef(self, name: str, version: str, dest: str = None): key = self.key(name, version, dest) value = self.store.get(key) if value: credDef = json.loads(value) credDef.update({ NAME: name, VERSION: version, TARGET_NYM: dest }) return credDef
class AttributeStoreFile(AttributeStore): def __init__(self, baseDir: str, name: str): self.store = DirectoryStore(baseDir, name) @staticmethod def attrKey(name: str, dest: Optional[str] = None): dest = dest or "" key = "{}_{}".format(name, dest) return base64.urlsafe_b64encode(key.encode()).decode() @staticmethod def attrKeyParts(attrKey: str): key = base64.urlsafe_b64decode(attrKey).decode() return str.rsplit(key, "_", 1) @staticmethod def constructAttrData(fileData: str, name: str, dest: Optional[str]=None): attr = json.loads(fileData) attr[NAME] = name if dest: attr[TARGET_NYM] = dest return attr # TODO: May be need to provide hash type also, assuming sha256 for now def addAttribute(self, name: str, val: Any, origin: str, dest: Optional[str]=None, encKey: Optional[str]=None, encType: Optional[str]=None, hashed: bool=False): key = self.attrKey(name, dest) if hashed: dataKeyName = HASH elif encKey: dataKeyName = ENC else: dataKeyName = RAW value = {dataKeyName: val, ORIGIN: origin} if encKey: value.update({SKEY: encKey}) if encType: value.update({ENC_TYPE: encType}) self.store.put(key, value=json.dumps(value)) def getAttribute(self, name: str, dest: Optional[str] = None): key = self.attrKey(name, dest) value = self.store.get(key) if value: return self.constructAttrData(value, name, dest) @property def attributes(self): return [self.constructAttrData(val, *self.attrKeyParts(key)) for key, val in self.store.iterator()]
class ClientReqRepStoreFile(ClientReqRepStore, HasFileStorage): def __init__(self, name, baseDir): self.baseDir = baseDir self.dataDir = "data/clients" self.name = name HasFileStorage.__init__(self, name=self.name, baseDir=baseDir, dataDir=self.dataDir) if not os.path.exists(self.dataLocation): os.makedirs(self.dataLocation) self.reqStore = DirectoryStore(self.dataLocation, "Requests") self._serializer = None @property def lastReqId(self) -> int: reqIds = self.reqStore.keys return max(map(int, reqIds)) if reqIds else 0 def addRequest(self, req: Request): idr = req.identifier reqId = req.reqId key = "{}{}".format(idr, reqId) self.reqStore.appendToValue(key, "0:{}". format(self.serializeReq(req))) def addAck(self, msg: Any, sender: str): idr = msg[f.IDENTIFIER.nm] reqId = msg[f.REQ_ID.nm] key = "{}{}".format(idr, reqId) self.reqStore.appendToValue(key, "A:{}".format(sender)) def addNack(self, msg: Any, sender: str): idr = msg[f.IDENTIFIER.nm] reqId = msg[f.REQ_ID.nm] key = "{}{}".format(idr, reqId) reason = msg[f.REASON.nm] self.reqStore.appendToValue(key, "N:{}:{}". format(sender, reason)) def addReply(self, identifier: str, reqId: int, sender: str, result: Any) -> Sequence[str]: serializedReply = self.txnSerializer.serialize(result, toBytes=False) key = "{}{}".format(identifier, reqId) self.reqStore.appendToValue(key, "R:{}:{}".format(sender, serializedReply)) return len(self._getSerializedReplies(identifier, reqId)) def hasRequest(self, identifier: str, reqId: int) -> bool: key = '{}{}'.format(identifier, reqId) return self.reqStore.exists(key) def getRequest(self, identifier: str, reqId: int) -> Request: for r in self._getLinesWithPrefix(identifier, reqId, "0:"): return self.deserializeReq(r[2:]) def getReplies(self, identifier: str, reqId: int): replies = self._getSerializedReplies(identifier, reqId) for sender, reply in replies.items(): replies[sender] = self.txnSerializer.deserialize(reply) return replies def getAcks(self, identifier: str, reqId: int) -> List[str]: ackLines = self._getLinesWithPrefix(identifier, reqId, "A:") return [line[2:] for line in ackLines] def getNacks(self, identifier: str, reqId: int) -> dict: nackLines = self._getLinesWithPrefix(identifier, reqId, "N:") result = {} for line in nackLines: sender, reason = line[2:].split(":", 1) result[sender] = reason return result @property def txnFieldOrdering(self): fields = getTxnOrderedFields() return updateFieldsWithSeqNo(fields) @staticmethod def serializeReq(req: Request) -> str: return json.dumps(req.__getstate__()) @staticmethod def deserializeReq(serReq: str) -> Request: return Request.fromState(json.loads(serReq)) def _getLinesWithPrefix(self, identifier: str, reqId: int, prefix: str) -> List[str]: key = '{}{}'.format(identifier, reqId) data = self.reqStore.get(key) return [line for line in data.split(os.linesep) if line.startswith(prefix)] if data else [] def _getSerializedReplies(self, identifier: str, reqId: int) -> \ Dict[str, str]: replyLines = self._getLinesWithPrefix(identifier, reqId, "R:") result = {} for line in replyLines: sender, reply = line[2:].split(":", 1) result[sender] = reply return result
class ClientReqRepStoreFile(ClientReqRepStore, HasFileStorage): LinePrefixes = namedtuple('LP', ['Request', REQACK, REQNACK, REPLY]) def __init__(self, name, baseDir): self.baseDir = baseDir self.dataDir = "data/clients" self.name = name HasFileStorage.__init__(self, name=self.name, baseDir=baseDir, dataDir=self.dataDir) if not os.path.exists(self.dataLocation): os.makedirs(self.dataLocation) self.reqStore = DirectoryStore(self.dataLocation, "Requests") self._serializer = None self.delimiter = '~' self.linePrefixes = self.LinePrefixes('0', 'A', 'N', 'R') @property def lastReqId(self) -> int: reqIds = self.reqStore.keys return max(map(int, reqIds)) if reqIds else 0 def addRequest(self, req: Request): idr = req.identifier reqId = req.reqId key = "{}{}".format(idr, reqId) self.reqStore.appendToValue( key, "{}{}{}".format(self.linePrefixes.Request, self.delimiter, self.serializeReq(req))) def addAck(self, msg: Any, sender: str): idr = msg[f.IDENTIFIER.nm] reqId = msg[f.REQ_ID.nm] key = "{}{}".format(idr, reqId) self.reqStore.appendToValue( key, "{}{}{}".format(self.linePrefixes.REQACK, self.delimiter, sender)) def addNack(self, msg: Any, sender: str): idr = msg[f.IDENTIFIER.nm] reqId = msg[f.REQ_ID.nm] key = "{}{}".format(idr, reqId) reason = msg[f.REASON.nm] self.reqStore.appendToValue( key, "{}{}{}{}{}".format(self.linePrefixes.REQNACK, self.delimiter, sender, self.delimiter, reason)) def addReply(self, identifier: str, reqId: int, sender: str, result: Any) -> int: serializedReply = self.txnSerializer.serialize(result, toBytes=False) key = "{}{}".format(identifier, reqId) self.reqStore.appendToValue( key, "{}{}{}{}{}".format(self.linePrefixes.REPLY, self.delimiter, sender, self.delimiter, serializedReply)) return len(self._getSerializedReplies(identifier, reqId)) def hasRequest(self, identifier: str, reqId: int) -> bool: key = '{}{}'.format(identifier, reqId) return self.reqStore.exists(key) def getRequest(self, identifier: str, reqId: int) -> Request: for r in self._getLinesWithPrefix( identifier, reqId, "{}{}".format(self.linePrefixes.Request, self.delimiter)): return self.deserializeReq(r[2:]) def getReplies(self, identifier: str, reqId: int): replies = self._getSerializedReplies(identifier, reqId) for sender, reply in replies.items(): replies[sender] = self.txnSerializer.deserialize(reply) return replies def getAcks(self, identifier: str, reqId: int) -> List[str]: ackLines = self._getLinesWithPrefix( identifier, reqId, "{}{}".format(self.linePrefixes.REQACK, self.delimiter)) return [line[2:] for line in ackLines] def getNacks(self, identifier: str, reqId: int) -> dict: nackLines = self._getLinesWithPrefix( identifier, reqId, "{}{}".format(self.linePrefixes.REQNACK, self.delimiter)) result = {} for line in nackLines: sender, reason = line[2:].split(self.delimiter, 1) result[sender] = reason return result @property def txnFieldOrdering(self): fields = getTxnOrderedFields() return updateFieldsWithSeqNo(fields) @staticmethod def serializeReq(req: Request) -> str: return json.dumps(req.__getstate__()) @staticmethod def deserializeReq(serReq: str) -> Request: return Request.fromState(json.loads(serReq)) def _getLinesWithPrefix(self, identifier: str, reqId: int, prefix: str) -> List[str]: key = '{}{}'.format(identifier, reqId) data = self.reqStore.get(key) return [line for line in data.splitlines() if line.startswith(prefix)] if data else [] def _getSerializedReplies(self, identifier: str, reqId: int) -> \ Dict[str, str]: replyLines = self._getLinesWithPrefix( identifier, reqId, "{}{}".format(self.linePrefixes.REPLY, self.delimiter)) result = {} for line in replyLines: sender, reply = line[2:].split(self.delimiter, 1) result[sender] = reply return result
class ClientReqRepStoreFile(ClientReqRepStore, HasFileStorage): def __init__(self, name, baseDir): self.baseDir = baseDir self.dataDir = "data/clients" self.name = name HasFileStorage.__init__(self, name=self.name, baseDir=baseDir, dataDir=self.dataDir) if not os.path.exists(self.dataLocation): os.makedirs(self.dataLocation) self.reqStore = DirectoryStore(self.dataLocation, "Requests") self._serializer = None @property def lastReqId(self) -> int: reqIds = self.reqStore.keys return max(map(int, reqIds)) if reqIds else 0 def addRequest(self, req: Request): reqId = req.reqId self.reqStore.appendToValue(str(reqId), "0:{}".format(self.serializeReq(req))) def addAck(self, msg: Any, sender: str): reqId = msg[f.REQ_ID.nm] self.reqStore.appendToValue(str(reqId), "A:{}".format(sender)) def addNack(self, msg: Any, sender: str): reqId = msg[f.REQ_ID.nm] reason = msg[f.REASON.nm] self.reqStore.appendToValue(str(reqId), "N:{}:{}".format(sender, reason)) def addReply(self, reqId: int, sender: str, result: Any) -> Sequence[str]: serializedReply = self.txnSerializer.serialize(result, toBytes=False) self.reqStore.appendToValue(str(reqId), "R:{}:{}".format(sender, serializedReply)) return len(self._getSerializedReplies(reqId)) def hasRequest(self, reqId: int) -> bool: return self.reqStore.exists(str(reqId)) def getReplies(self, reqId: int): replies = self._getSerializedReplies(reqId) for sender, reply in replies.items(): replies[sender] = self.txnSerializer.deserialize(reply) return replies def getAcks(self, reqId: int) -> List[str]: ackLines = self._getLinesWithPrefix(reqId, "A:") return [line[2:] for line in ackLines] def getNacks(self, reqId: int) -> dict: nackLines = self._getLinesWithPrefix(reqId, "N:") result = {} for line in nackLines: sender, reason = line[2:].split(":", 1) result[sender] = reason return result @property def txnFieldOrdering(self): fields = getTxnOrderedFields() return updateFieldsWithSeqNo(fields) @staticmethod def serializeReq(req: Request) -> str: return json.dumps(req.__getstate__()) def _getLinesWithPrefix(self, reqId: int, prefix: str) -> List[str]: data = self.reqStore.get(str(reqId)) return [ line for line in data.split(os.linesep) if line.startswith(prefix) ] if data else [] def _getSerializedReplies(self, reqId: int) -> Dict[str, str]: replyLines = self._getLinesWithPrefix(reqId, "R:") result = {} for line in replyLines: sender, reply = line[2:].split(":", 1) result[sender] = reply return result