def sendMessage(self, msg, name: str = None, ha: Tuple = None): try: remote = self.endpoint.getRemote(name=name, ha=ha) name = remote.name ha = remote.ha except RemoteNotFound as ex: if not (isinstance(self.endpoint, ZEndpoint) and self.endpoint.hasRemote( name.encode() if isinstance(name, str) else name)): fault(ex, "Do not know {} {}".format(name, ha)) return def _send(msg): nonlocal name, ha self.endpoint.send(msg, name) logger.debug("Message sent (to -> {}): {}".format(ha, msg)) # TODO: if we call following isConnectedTo method by ha, # there was a case it found more than one remote, so for now, # I have changed it to call by remote name (which I am not sure # fixes the issue), need to come back to this. if not self.endpoint.isConnectedTo(name=name, ha=ha): self.ensureConnectedToDest(name, ha, _send, msg) else: _send(msg)
def addNymTxnToGraph(self, txn): origin = txn.get(f.IDENTIFIER.nm) role = txn.get(ROLE) or USER if not isValidRole(role): raise ValueError("Unknown role {} for nym, cannot add nym to graph" .format(role)) nym = txn[TARGET_NYM] # Not using `txn.get(VERKEY, '') as txn might have VERKEY but set as None` verkey = txn.get(VERKEY) or '' try: txnId = txn[TXN_ID] seqNo = txn.get(F.seqNo.name) # Since NYM vertex has a unique index on the identifier, # (CID or DID) a unique constraint violattion would occur if the # nym exists. Instead of catching an exception, a call to hasNym or # getNym could be done but since NYM update txns would be less # common then NYM adding transactions so avoidinhg the cost of # extra db query try: self.addNym(txnId, nym, verkey, role, frm=origin, reference=txn.get(REF), seqNo=seqNo) except pyorient.PyOrientORecordDuplicatedException: self.updateNym(txnId, nym, verkey, seqNo) else: # Only update edge in case of new NYM transaction self._updateTxnIdEdgeWithTxn(txnId, Edges.AddsNym, txn) except pyorient.PyOrientORecordDuplicatedException: logger.debug("The nym {} was already added to graph". format(nym)) except pyorient.PyOrientCommandException as ex: fault(ex, "An exception was raised while adding " "nym {}: {}".format(nym, ex))
def addNymTxnToGraph(self, txn): origin = txn.get(f.IDENTIFIER.nm) role = txn.get(ROLE) or USER if not isValidRole(role): raise ValueError( "Unknown role {} for nym, cannot add nym to graph".format( role)) else: nym = txn[TARGET_NYM] try: txnId = txn[TXN_ID] self.addNym(txnId, nym, role, frm=origin, reference=txn.get(REFERENCE), seqNo=txn.get(F.seqNo.name)) self._updateTxnIdEdgeWithTxn(txnId, Edges.AddsNym, txn) except pyorient.PyOrientORecordDuplicatedException: logger.debug( "The nym {} was already added to graph".format(nym)) except pyorient.PyOrientCommandException as ex: fault( ex, "An exception was raised while adding " "nym {}: {}".format(nym, ex))
def sendMessage(self, msg, destName: str = None, destHa: Tuple = None): try: remote = self.endpoint.getRemote(name=destName, ha=destHa) except RemoteNotFound as ex: fault(ex, "Do not know {} {}".format(destName, destHa)) return self.endpoint.transmit(msg, remote.uid)
def addAttribTxnToGraph(self, txn): origin = txn.get(f.IDENTIFIER.nm) txnId = txn[TXN_ID] try: self.addAttribute(frm=origin, txnId=txnId, raw=txn.get(RAW), enc=txn.get(ENC), hash=txn.get(HASH), to=txn.get(TARGET_NYM)) self._updateTxnIdEdgeWithTxn(txnId, Edges.AddsAttribute, txn) except pyorient.PyOrientCommandException as ex: fault(ex, "An exception was raised while adding attribute: {}". format(ex))
def parseTxnData(self, data): """ parse stringified data to json :param data: stringfied data :return: """ try: return json.loads(data) except Exception as ex: fault(ex, "Cannot convert string data {} to JSON".format(data)) return
def postReplyRecvd(self, identifier, reqId, frm, result, numReplies): reply = super().postReplyRecvd(identifier, reqId, frm, result, numReplies) if reply: for name in self._observers: try: self._observers[name](name, reqId, frm, result, numReplies) except Exception as ex: # TODO: All errors should not be shown on CLI, or maybe we # show errors with different color according to the # severity. Like an error occurring due to node sending # a malformed message should not result in an error message # being shown on the cli since the clients would anyway # collect enough replies from other nodes. logger.debug("Observer threw an exception", exc_info=ex) if isinstance(self.reqRepStore, ClientReqRepStoreOrientDB): self.reqRepStore.setConsensus(identifier, reqId) if result[TXN_TYPE] == NYM: if self.graphStore: self.addNymToGraph(result) elif result[TXN_TYPE] == ATTRIB: if self.graphStore: self.graphStore.addAttribTxnToGraph(result) elif result[TXN_TYPE] == GET_NYM: if self.graphStore: if DATA in result and result[DATA]: self.addNymToGraph(json.loads(result[DATA])) elif result[TXN_TYPE] == GET_TXNS: if DATA in result and result[DATA]: data = json.loads(result[DATA]) self.reqRepStore.setLastTxnForIdentifier( result[f.IDENTIFIER.nm], data[LAST_TXN]) if self.graphStore: for txn in data[TXNS]: if txn[TXN_TYPE] == NYM: self.addNymToGraph(txn) elif txn[TXN_TYPE] == ATTRIB: try: self.graphStore.addAttribTxnToGraph(txn) except pyorient.PyOrientCommandException as ex: fault( ex, "An exception was raised while " "adding attribute") elif result[TXN_TYPE] == CLAIM_DEF: if self.graphStore: self.graphStore.addClaimDefTxnToGraph(result) elif result[TXN_TYPE] == ISSUER_KEY: if self.graphStore: self.graphStore.addIssuerKeyTxnToGraph(result)
def addSchemaTxnToGraph(self, txn): origin = txn.get(f.IDENTIFIER.nm) txnId = txn[TXN_ID] data = txn.get(DATA) try: self.addSchema(frm=origin, txnId=txnId, name=data.get(NAME), version=data.get(VERSION), attrNames=data.get(ATTR_NAMES), typ=data.get(TYPE)) self._updateTxnIdEdgeWithTxn(txnId, Edges.AddsSchema, txn) except Exception as ex: fault(ex, "Error adding cred def to orientdb")
def addIssuerKeyTxnToGraph(self, txn): origin = txn.get(f.IDENTIFIER.nm) txnId = txn[TXN_ID] data = txn.get(DATA) try: self.addIssuerKey( frm=origin, txnId=txnId, data=data, reference=txn.get(REF), ) self._updateTxnIdEdgeWithTxn(txnId, Edges.HasIssuerKey, txn) except Exception as ex: fault(ex, "Error adding issuer key to orientdb") pass
def sendMessage(self, msg, name: str = None, ha: Tuple = None): try: remote = self.endpoint.getRemote(name=name, ha=ha) except RemoteNotFound as ex: fault(ex, "Do not know {} {}".format(name, ha)) return def _send(msg, remote): self.endpoint.transmit(msg, remote.uid) logger.debug("Message sent (to -> {}): {}".format(remote.ha, msg)) if not self.endpoint.isConnectedTo(ha=remote.ha): self.ensureConnectedToDest(remote.ha, _send, msg, remote) else: _send(msg, remote)
def addNymTxnToGraph(self, txn): origin = txn.get(f.IDENTIFIER.nm) role = txn.get(ROLE) if not Authoriser.isValidRole(role): raise ValueError( "Unknown role {} for nym, cannot add nym to graph".format( role)) verkey = txn.get(VERKEY) nym = txn[TARGET_NYM] try: txnId = txn[TXN_ID] seqNo = txn.get(F.seqNo.name) # Since NYM vertex has a unique index on the identifier, # (CID or DID) a unique constraint violation would occur if the # nym exists. Instead of catching an exception, a call to hasNym or # getNym could be done but since NYM update txns would be less # common then NYM adding transactions so avoiding the cost of # extra db query try: self.addNym(txnId, nym, verkey, role, frm=origin, reference=txn.get(REF), seqNo=seqNo) except pyorient.PyOrientORecordDuplicatedException: updateData = {} # Since role can be None, it is only included for update if # it was supplied in the transaction as if ROLE was not # supplied in transaction, the client did not intend to update # the role, but if absence of role is considered None then it # will lead to the identity losing its role if ROLE in txn: updateData[ROLE] = txn[ROLE] if VERKEY in txn: updateData[VERKEY] = txn[VERKEY] self.updateNym(txnId, nym, seqNo, **updateData) else: # Only update edge in case of new NYM transaction self._updateTxnIdEdgeWithTxn(txnId, Edges.AddsNym, txn) except pyorient.PyOrientORecordDuplicatedException: logger.debug("The nym {} was already added to graph".format(nym)) except pyorient.PyOrientCommandException as ex: fault( ex, "An exception was raised while adding " "nym {}: {}".format(nym, ex))
def signAndSend(self, msg, signingIdr=None, toRaetStackName=None, linkName=None, origReqId=None): if linkName: assert not (signingIdr or toRaetStackName) link = self.wallet.getLink(linkName, required=True) if not link.localIdentifier: raise LinkNotReady('link is not yet established, ' 'send/accept invitation first') signingIdr = link.localIdentifier try: self.connectTo(link=link) ha = link.getRemoteEndpoint(required=True) params = dict(ha=ha) except RemoteEndpointNotFound as ex: logger.debug('ZStack remote found') if not (isinstance(self.endpoint, ZEndpoint) and self.endpoint. hasRemote(link.remotePubKey.encode() if isinstance( link.remotePubKey, str) else link.remotePubKey)): fault(ex, "Do not know {} {}".format(link.remotePubKey, ha)) return # TODO ensure status is appropriate with code like the following # if link.linkStatus != constant.LINK_STATUS_ACCEPTED: # raise LinkNotReady('link status is {}'.format(link.linkStatus)) params = dict(name=link.remotePubKey) else: params = dict(name=toRaetStackName) # origReqId needs to be supplied when you want to respond to request # so that on receiving end, response can be matched with request # if origReqId: # msg[f.REQ_ID.nm] = origReqId # else: # msg[f.REQ_ID.nm] = getTimeBasedId() msg[f.REQ_ID.nm] = getTimeBasedId() if origReqId: msg[REF_REQUEST_ID] = origReqId msg[IDENTIFIER] = signingIdr signature = self.wallet.signMsg(msg, signingIdr) msg[f.SIG.nm] = signature self.sendMessage(msg, **params) return msg[f.REQ_ID.nm]
def postReplyRecvd(self, reqId, frm, result, numReplies): reply = super().postReplyRecvd(reqId, frm, result, numReplies) if reply: for name in self._observers: try: self._observers[name](name, reqId, frm, result, numReplies) except Exception as ex: logger.error("Observer threw an exception", exc_info=ex) if isinstance(self.reqRepStore, ClientReqRepStoreOrientDB): self.reqRepStore.setConsensus(reqId) if result[TXN_TYPE] == NYM: if self.graphStore: self.addNymToGraph(result) elif result[TXN_TYPE] == ATTRIB: if self.graphStore: self.graphStore.addAttribTxnToGraph(result) elif result[TXN_TYPE] == GET_NYM: if self.graphStore: if DATA in result and result[DATA]: self.addNymToGraph(json.loads(result[DATA])) elif result[TXN_TYPE] == GET_TXNS: if DATA in result and result[DATA]: data = json.loads(result[DATA]) self.reqRepStore.setLastTxnForIdentifier( result[f.IDENTIFIER.nm], data[LAST_TXN]) if self.graphStore: for txn in data[TXNS]: if txn[TXN_TYPE] == NYM: self.addNymToGraph(txn) elif txn[TXN_TYPE] == ATTRIB: try: self.graphStore.addAttribTxnToGraph(txn) except pyorient.PyOrientCommandException as ex: fault( ex, "An exception was raised while adding " "attribute {}".format(ex)) elif result[TXN_TYPE] == CRED_DEF: if self.graphStore: self.graphStore.addCredDefTxnToGraph(result) elif result[TXN_TYPE] == ISSUER_KEY: if self.graphStore: self.graphStore.addIssuerKeyTxnToGraph(result) else: logger.debug("Unknown type {}".format(result[TXN_TYPE]))
def addClaimDefTxnToGraph(self, txn): origin = txn.get(f.IDENTIFIER.nm) txnId = txn[TXN_ID] data = txn.get(DATA) signatureType = txn[SIGNATURE_TYPE] if isinstance(data, str): data = self.parseTxnData(data) if not data: return try: self.addClaimDef(frm=origin, txnId=txnId, data=data, reference=txn.get(REF), signatureType=signatureType) self._updateTxnIdEdgeWithTxn(txnId, Edges.HasClaimDef, txn) except Exception as ex: fault(ex, "Error adding issuer key to orientdb") pass