def __init__(self, identifier, verkey=None, rawVerkey=None): self.abbreviated = None if (verkey is None or verkey == '') and (rawVerkey is None or rawVerkey == ''): if identifier: self._identifier = identifier if (verkey is None and rawVerkey is None): self._verkey = None else: self._verkey = '' return assert (verkey or rawVerkey) and not (verkey and rawVerkey) if identifier: self._identifier = identifier if rawVerkey: self._verkey = rawToFriendly(rawVerkey) self.abbreviated = False else: if verkey.startswith("~"): self._verkey = verkey[1:] self.abbreviated = True else: self._verkey = verkey self.abbreviated = False else: verraw = rawVerkey or friendlyToRaw(verkey) self._identifier = rawToFriendly(verraw[:16]) self._verkey = rawToFriendly(verraw[16:]) self.abbreviated = True
def add_agent_uids(agents: [WalletedAgent]) -> None: """ Add various unique identifiers related to an agent from a list of agents, to the local database mapping those random looking values to friendly names. :param agents: List of instances of the WalletedAgent class. """ logging.info("Start adding unique identifiers from agents {}".format( [agent.name for agent in agents])) for agent in agents: add_uid_to_dictionary(agent.client.name, "{} {}".format(agent.name, "client name"), True) add_uid_to_dictionary(agent.client.alias, "{} {}".format(agent.name, "client alias"), True) # Note that agent.client.nodestack.name == rawToFriendly(agent.client.nodestack.verKeyRaw) add_uid_to_dictionary( agent.client.nodestack.name, "{} {}".format(agent.name, "client nodestack verkey"), True) add_uid_to_dictionary( rawToFriendly(agent.client.nodestack.publicKeyRaw), "{} {}".format(agent.name, "client nodestack pubkey"), True) if agent.endpoint: add_uid_to_dictionary( rawToFriendly(agent.endpoint.verKeyRaw), "{} {}".format(agent.name, "endpoint verkey"), True) add_uid_to_dictionary( rawToFriendly(agent.endpoint.publicKeyRaw), "{} {}".format(agent.name, "endpoint pubkey"), True) add_uid_to_dictionary( rawToFriendly(z85decode(agent.endpoint.sigKey)), "{} {}".format(agent.name, "endpoint sigkey"), True) add_wallet_uids(agent.wallet, agent.name) logging.info("Finished adding unique identifiers from agents {}".format( [agent.name for agent in agents]))
def __init__(self, identifier, verkey=None, rawVerkey=None): self.abbreviated = None if (verkey is None or verkey == '') and (rawVerkey is None or rawVerkey == ''): if identifier: self._identifier = identifier if (verkey is None and rawVerkey is None): self._verkey = None else: self._verkey = '' return if not ((verkey or rawVerkey) and not (verkey and rawVerkey)): raise ValueError( "Both verkey {} and rawVerkey {} can't be specified" .format(verkey, rawVerkey) ) if identifier: self._identifier = identifier if rawVerkey: self._verkey = rawToFriendly(rawVerkey) self.abbreviated = False else: if verkey.startswith("~"): self._verkey = verkey[1:] self.abbreviated = True else: self._verkey = verkey self.abbreviated = False else: verraw = rawVerkey or friendlyToRaw(verkey) self._identifier = rawToFriendly(verraw[:16]) self._verkey = rawToFriendly(verraw[16:]) self.abbreviated = True
def __init__(self, identifier, verkey=None, rawVerkey=None): self.abbreviated = None if (verkey is None or verkey == '') and (rawVerkey is None or rawVerkey == ''): if identifier: self._identifier = identifier if (verkey is None and rawVerkey is None): self._verkey = None else: self._verkey = '' return if not ((verkey or rawVerkey) and not (verkey and rawVerkey)): raise ValueError( "Both verkey {} and rawVerkey {} can't be specified".format( verkey, rawVerkey)) if identifier: self._identifier = identifier if rawVerkey: self._verkey = rawToFriendly(rawVerkey) self.abbreviated = False else: if verkey.startswith("~"): self._verkey = verkey[1:] self.abbreviated = True else: self._verkey = verkey self.abbreviated = False else: verraw = rawVerkey or friendlyToRaw(verkey) self._identifier = rawToFriendly(verraw[:16]) self._verkey = rawToFriendly(verraw[16:]) self.abbreviated = True
def __init__(self, identifier=None, seed=None, alias=None): """ Initialize the signer with an identifier and a seed. :param identifier: some identifier that directly or indirectly references this client :param seed: the seed used to generate a signing key. """ # should be stored securely/privately self.seed = seed if seed else randombytes(32) # generates key pair based on seed self.sk = SigningKey(seed=self.seed) # helper for signing self.naclSigner = NaclSigner(self.sk) verraw = self.naclSigner.verraw if identifier: self._identifier = identifier self._verkey = rawToFriendly(verraw) self.abbreviated = False else: self._identifier = rawToFriendly(verraw[:16]) self._verkey = rawToFriendly(verraw[16:]) self.abbreviated = True self._alias = alias
def __init__(self, identifier, verkey=None, rawVerkey=None): assert (verkey or rawVerkey) and not (verkey and rawVerkey) if identifier: self._identifier = identifier self._verkey = verkey or rawToFriendly(rawVerkey) self.abbreviated = False else: verraw = rawVerkey or friendlyToRaw(verkey) self._identifier = rawToFriendly(verraw[:16]) self._verkey = rawToFriendly(verraw[16:]) self.abbreviated = True
def testSendNymFailsIfAbbrevVerkeySizeIs17Bytes( looper, sdk_pool_handle, txnPoolNodeSet, nym_request, sdk_wallet_trustee): parameters = { 'dest': rawToFriendly(randombytes(16)), 'verkey': '~' + rawToFriendly(randombytes(17)), 'role': TRUST_ANCHOR } nym_request[OPERATION].update(parameters) request_couple = sdk_sign_and_send_prepared_request(looper, sdk_wallet_trustee, sdk_pool_handle, json.dumps(nym_request)) sdk_get_and_check_replies(looper, [request_couple])
def testSendNymFailsIfAbbrevVerkeySizeIs17Bytes( be, do, poolNodesStarted, trusteeCli): parameters = { 'dest': rawToFriendly(randombytes(16)), 'verkey': '~' + rawToFriendly(randombytes(17)), 'role': Roles.TRUST_ANCHOR.name } be(trusteeCli) do('send NYM dest={dest} role={role}', mapper=parameters, expect=ERROR, within=2)
def find_z85_uid_in_record(record: logging.LogRecord) -> [(str, str)]: """ Generate a list of z85 encoded unique identifiers. :param record: Log record to be analysed. :return: List of pairs of the original string with the decoded string. """ matches = [] for (method, search_string) in [ (LedgerManager.processLedgerStatus, "(b'[{}]{{40}}')".format(Z85_CHARACTERS)), (Node.processClientInBox, "processing (b'[{}]{{40}}') request".format(Z85_CHARACTERS)), (Node.handleOneNodeMsg, "'{}': '([{}]{{40}})'".format(f.SENDER_CLIENT.nm, Z85_CHARACTERS)), (Node.send, "'{}': '([{}]+?)'".format(f.SENDER_CLIENT.nm, Z85_CHARACTERS)), (Node.validateNodeMsg, "'{}': '([{}]{{40}})'".format(f.SENDER_CLIENT.nm, Z85_CHARACTERS)), (Node.postToNodeInBox, "'{}': '([{}]{{40}})'".format(f.SENDER_CLIENT.nm, Z85_CHARACTERS)), (Node.processClientInBox, "processing (b'[{}]{{40}}') request".format(Z85_CHARACTERS)), (Node.processRequest, "from (b'[{}]{{40}}')$".format(Z85_CHARACTERS)), (Node.processPropagate, "'{}': '([{}]{{40}})'".format(f.SENDER_CLIENT.nm, Z85_CHARACTERS)), (Node.processPropagate, "from (b'[{}]{{40}}')$".format(f.SENDER_CLIENT.nm, Z85_CHARACTERS)), (Propagator.propagate, "from client ([{}]{{40}})$".format(Z85_CHARACTERS)), (Propagator.propagate, "from client (b'[{}]{{40}}')$".format(Z85_CHARACTERS)), (Walleted.handleEndpointMessage, "(b'[{}]{{40}}')".format(Z85_CHARACTERS)), (ZStack.handlePingPong, "got ping from (b'[{}]{{40}}')".format(Z85_CHARACTERS)), (ZStack.sendPingPong, "(b'[{}]{{40}}')".format(Z85_CHARACTERS)) ]: if match_method(record, method): search_result = re.search(search_string, record.msg) if search_result: if search_result.group(1).startswith("b'"): friendly_public_key = rawToFriendly( z85decode(search_result.group(1)[2:42])) else: friendly_public_key = rawToFriendly( z85decode(search_result.group(1))) assert not friendly_public_key.startswith("b'") matches.append((search_result.group(1), friendly_public_key)) return matches
def full_verkey(self): if self.abbreviated: rtn = friendlyToRaw(self.identifier) rtn += friendlyToRaw(self.verkey[1:]) return rawToFriendly(rtn) else: return self.verkey
def testSendNymFailsIfIdentifierSizeIs17Bytes(looper, sdk_pool_handle, txnPoolNodeSet, nym_request, sdk_wallet_trustee): parameters = {'dest': rawToFriendly(randombytes(17)), 'role': ENDORSER} nym_request[OPERATION].update(parameters) request_couple = sdk_sign_and_send_prepared_request( looper, sdk_wallet_trustee, sdk_pool_handle, json.dumps(nym_request)) sdk_get_and_check_replies(looper, [request_couple])
def testSendNymFailsIfIdentifierSizeIs15Bytes(looper, sdk_pool_handle, txnPoolNodeSet, nym_request, sdk_wallet_trustee): parameters = {'dest': rawToFriendly(randombytes(15)), 'role': TRUST_ANCHOR} nym_request[OPERATION].update(parameters) request_couple = sdk_sign_and_send_prepared_request( looper, sdk_wallet_trustee, sdk_pool_handle, json.dumps(nym_request)) sdk_get_bad_response(looper, [request_couple], RequestNackedException, '')
def testSendNymFailsIfIdentifierSizeIs15Bytes( be, do, poolNodesStarted, trusteeCli): parameters = { 'dest': rawToFriendly(randombytes(15)), 'role': Roles.TRUST_ANCHOR.name } be(trusteeCli) do('send NYM dest={dest} role={role}', mapper=parameters, expect=ERROR, within=2)
def add_steward_uids(steward: Steward) -> None: """ Add various unique identifiers related to a Sovrin steward, to the local database mapping those random looking values to friendly names :param steward: An instance of the Steward class. """ add_uid_to_dictionary(steward.nym, "{} {}".format(steward.name, "NYM"), True) add_wallet_uids(steward.wallet, steward.name) add_uid_to_dictionary(rawToFriendly(unhexlify(steward.node.verkey)), "{} {}".format(steward.node.name, "verkey"), True) # See ZStack.initLocalKeys
def testSendAttribFailsForBase58Hash( looper, sdk_pool_handle, sdk_wallet_trustee): raw = json.dumps({ 'name': 'Alice' }) hash = sha256(raw.encode()).digest() new_wallet = sdk_add_new_nym(looper, sdk_pool_handle, sdk_wallet_trustee) parameters = None with pytest.raises(RequestNackedException) as e: sdk_add_attribute_and_check(looper, sdk_pool_handle, new_wallet, parameters, xhash=rawToFriendly(hash)) e.match('not a valid hash')
def testSendAttribFailsForBase58Hash(be, do, poolNodesStarted, trusteeCli): uuidIdentifier = createUuidIdentifier() addNym(be, do, trusteeCli, idr=uuidIdentifier) raw = json.dumps({'name': 'Alice'}) hash = sha256(raw.encode()).digest() parameters = {'dest': uuidIdentifier, 'hash': rawToFriendly(hash)} be(trusteeCli) do('send ATTRIB dest={dest} hash={hash}', mapper=parameters, expect=INVALID_SYNTAX, within=2)
def testSendAttribFailsForBase58Hash( be, do, poolNodesStarted, trusteeCli): uuidIdentifier = createUuidIdentifier() addNym(be, do, trusteeCli, idr=uuidIdentifier) raw = json.dumps({ 'name': 'Alice' }) hash = sha256(raw.encode()).digest() parameters = { 'dest': uuidIdentifier, 'hash': rawToFriendly(hash) } be(trusteeCli) do('send ATTRIB dest={dest} hash={hash}', mapper=parameters, expect=INVALID_SYNTAX, within=2)
def createUuidIdentifier(): return rawToFriendly(randombytes(16))
def friendlyVerkeyToPubkey(verkey): vkRaw = friendlyToRaw(verkey) pkraw = ed25519PkToCurve25519(vkRaw) return rawToFriendly(pkraw)
def __init__(self, name: str, nodeReg: Dict[str, HA]=None, ha: Union[HA, Tuple[str, int]]=None, basedirpath: str=None, config=None, sighex: str=None): """ Creates a new client. :param name: unique identifier for the client :param nodeReg: names and host addresses of all nodes in the pool :param ha: tuple of host and port """ self.config = config or getConfig() basedirpath = self.config.baseDir if not basedirpath else basedirpath self.basedirpath = basedirpath signer = Signer(sighex) sighex = signer.keyhex verkey = rawToFriendly(signer.verraw) self.name = name self.stackName = verkey cha = None # If client information already exists is RAET then use that if self.exists(self.stackName, basedirpath): cha = getHaFromLocalEstate(self.stackName, basedirpath) if cha: cha = HA(*cha) logger.debug("Client {} ignoring given ha {} and using {}". format(self.name, ha, cha)) if not cha: cha = ha if isinstance(ha, HA) else HA(*ha) self.reqRepStore = self.getReqRepStore() self.txnLog = self.getTxnLogStore() self.dataDir = self.config.clientDataDir or "data/clients" HasFileStorage.__init__(self, self.name, baseDir=self.basedirpath, dataDir=self.dataDir) self._ledger = None if not nodeReg: self.mode = None HasPoolManager.__init__(self) self.ledgerManager = LedgerManager(self, ownedByNode=False) self.ledgerManager.addLedger(0, self.ledger, postCatchupCompleteClbk=self.postPoolLedgerCaughtUp, postTxnAddedToLedgerClbk=self.postTxnFromCatchupAddedToLedger) else: cliNodeReg = OrderedDict() for nm, (ip, port) in nodeReg.items(): cliNodeReg[nm] = HA(ip, port) self.nodeReg = cliNodeReg self.mode = Mode.discovered HasActionQueue.__init__(self) self.setF() stackargs = dict(name=self.stackName, ha=cha, main=False, # stops incoming vacuous joins auto=AutoMode.always) stackargs['basedirpath'] = basedirpath self.created = time.perf_counter() # noinspection PyCallingNonCallable self.nodestack = self.nodeStackClass(stackargs, self.handleOneNodeMsg, self.nodeReg, sighex) self.nodestack.onConnsChanged = self.onConnsChanged if self.nodeReg: logger.info("Client {} initialized with the following node registry:" .format(self.name)) lengths = [max(x) for x in zip(*[ (len(name), len(host), len(str(port))) for name, (host, port) in self.nodeReg.items()])] fmt = " {{:<{}}} listens at {{:<{}}} on port {{:>{}}}".format( *lengths) for name, (host, port) in self.nodeReg.items(): logger.info(fmt.format(name, host, port)) else: logger.info( "Client {} found an empty node registry:".format(self.name)) Motor.__init__(self) self.inBox = deque() self.nodestack.connectNicelyUntil = 0 # don't need to connect # nicely as a client # TODO: Need to have couple of tests around `reqsPendingConnection` # where we check with and without pool ledger # Stores the requests that need to be sent to the nodes when the client # has made sufficient connections to the nodes. self.reqsPendingConnection = deque() # Tuple of identifier and reqId as key and value as tuple of set of # nodes which are expected to send REQACK self.expectingAcksFor = {} # Tuple of identifier and reqId as key and value as tuple of set of # nodes which are expected to send REPLY self.expectingRepliesFor = {} tp = loadPlugins(self.basedirpath) logger.debug("total plugins loaded in client: {}".format(tp))
def __init__(self, name: str, nodeReg: Dict[str, HA] = None, ha: Union[HA, Tuple[str, int]] = None, basedirpath: str = None, genesis_dir: str = None, ledger_dir: str = None, keys_dir: str = None, plugins_dir: str = None, config=None, sighex: str = None): """ Creates a new client. :param name: unique identifier for the client :param nodeReg: names and host addresses of all nodes in the pool :param ha: tuple of host and port """ self.config = config or getConfig() dataDir = self.config.clientDataDir or "data/clients" self.basedirpath = basedirpath or self.config.CLI_BASE_DIR self.basedirpath = os.path.expanduser(self.basedirpath) signer = Signer(sighex) sighex = signer.keyraw verkey = rawToFriendly(signer.verraw) self.stackName = verkey # TODO: Have a way for a client to have a user friendly name. Does it # matter now, it used to matter in some CLI exampples in the past. # self.name = name self.name = self.stackName or 'Client~' + str(id(self)) self.genesis_dir = genesis_dir or self.basedirpath self.ledger_dir = ledger_dir or os.path.join(self.basedirpath, dataDir, self.name) self.plugins_dir = plugins_dir or self.basedirpath _keys_dir = keys_dir or self.basedirpath self.keys_dir = os.path.join(_keys_dir, "keys") cha = None if self.exists(self.stackName, self.keys_dir): cha = self.nodeStackClass.getHaFromLocal( self.stackName, self.keys_dir) if cha: cha = HA(*cha) logger.debug("Client {} ignoring given ha {} and using {}". format(self.name, ha, cha)) if not cha: cha = ha if isinstance(ha, HA) else HA(*ha) self.reqRepStore = self.getReqRepStore() self.txnLog = self.getTxnLogStore() HasFileStorage.__init__(self, self.ledger_dir) # TODO: Find a proper name self.alias = name if not nodeReg: self.mode = None HasPoolManager.__init__(self) self.ledgerManager = LedgerManager(self, ownedByNode=False) self.ledgerManager.addLedger( POOL_LEDGER_ID, self.ledger, preCatchupStartClbk=self.prePoolLedgerCatchup, postCatchupCompleteClbk=self.postPoolLedgerCaughtUp, postTxnAddedToLedgerClbk=self.postTxnFromCatchupAddedToLedger) else: cliNodeReg = OrderedDict() for nm, (ip, port) in nodeReg.items(): cliNodeReg[nm] = HA(ip, port) self.nodeReg = cliNodeReg self.mode = Mode.discovered HasActionQueue.__init__(self) self.setPoolParams() stackargs = dict(name=self.stackName, ha=cha, main=False, # stops incoming vacuous joins auth_mode=AuthMode.ALLOW_ANY.value) stackargs['basedirpath'] = self.keys_dir self.created = time.perf_counter() # noinspection PyCallingNonCallable # TODO I think this is a bug here, sighex is getting passed in the seed # parameter self.nodestack = self.nodeStackClass(stackargs, self.handleOneNodeMsg, self.nodeReg, sighex) self.nodestack.onConnsChanged = self.onConnsChanged if self.nodeReg: logger.info( "Client {} initialized with the following node registry:".format( self.alias)) lengths = [max(x) for x in zip(*[ (len(name), len(host), len(str(port))) for name, (host, port) in self.nodeReg.items()])] fmt = " {{:<{}}} listens at {{:<{}}} on port {{:>{}}}".format( *lengths) for name, (host, port) in self.nodeReg.items(): logger.info(fmt.format(name, host, port)) else: logger.info( "Client {} found an empty node registry:".format(self.alias)) Motor.__init__(self) self.inBox = deque() self.nodestack.connectNicelyUntil = 0 # don't need to connect # nicely as a client # TODO: Need to have couple of tests around `reqsPendingConnection` # where we check with and without pool ledger # Stores the requests that need to be sent to the nodes when the client # has made sufficient connections to the nodes. self.reqsPendingConnection = deque() # Tuple of identifier and reqId as key and value as tuple of set of # nodes which are expected to send REQACK self.expectingAcksFor = {} # Tuple of identifier and reqId as key and value as tuple of set of # nodes which are expected to send REPLY self.expectingRepliesFor = {} self._observers = {} # type Dict[str, Callable] self._observerSet = set() # makes it easier to guard against duplicates plugins_to_load = self.config.PluginsToLoad if hasattr(self.config, "PluginsToLoad") else None tp = loadPlugins(self.plugins_dir, plugins_to_load) logger.debug("total plugins loaded in client: {}".format(tp)) self._multi_sig_verifier = self._create_multi_sig_verifier() self._read_only_requests = set()
def __init__(self, name: str, nodeReg: Dict[str, HA] = None, ha: Union[HA, Tuple[str, int]] = None, basedirpath: str = None, config=None, sighex: str = None): """ Creates a new client. :param name: unique identifier for the client :param nodeReg: names and host addresses of all nodes in the pool :param ha: tuple of host and port """ self.config = config or getConfig() basedirpath = self.config.baseDir if not basedirpath else basedirpath self.basedirpath = basedirpath signer = Signer(sighex) sighex = signer.keyraw verkey = rawToFriendly(signer.verraw) self.stackName = verkey # TODO: Have a way for a client to have a user friendly name. Does it # matter now, it used to matter in some CLI exampples in the past. # self.name = name self.name = self.stackName cha = None # If client information already exists is RAET then use that if self.exists(self.stackName, basedirpath): cha = getHaFromLocalEstate(self.stackName, basedirpath) if cha: cha = HA(*cha) logger.debug( "Client {} ignoring given ha {} and using {}".format( self.name, ha, cha)) if not cha: cha = ha if isinstance(ha, HA) else HA(*ha) self.reqRepStore = self.getReqRepStore() self.txnLog = self.getTxnLogStore() self.dataDir = self.config.clientDataDir or "data/clients" HasFileStorage.__init__(self, self.name, baseDir=self.basedirpath, dataDir=self.dataDir) # TODO: Find a proper name self.alias = name self._ledger = None if not nodeReg: self.mode = None HasPoolManager.__init__(self) self.ledgerManager = LedgerManager(self, ownedByNode=False) self.ledgerManager.addLedger( 0, self.ledger, postCatchupCompleteClbk=self.postPoolLedgerCaughtUp, postTxnAddedToLedgerClbk=self.postTxnFromCatchupAddedToLedger) else: cliNodeReg = OrderedDict() for nm, (ip, port) in nodeReg.items(): cliNodeReg[nm] = HA(ip, port) self.nodeReg = cliNodeReg self.mode = Mode.discovered HasActionQueue.__init__(self) self.setF() stackargs = dict( name=self.stackName, ha=cha, main=False, # stops incoming vacuous joins auto=2) stackargs['basedirpath'] = basedirpath self.created = time.perf_counter() # noinspection PyCallingNonCallable self.nodestack = self.nodeStackClass(stackargs, self.handleOneNodeMsg, self.nodeReg, sighex) self.nodestack.onConnsChanged = self.onConnsChanged if self.nodeReg: logger.info( "Client {} initialized with the following node registry:". format(self.alias)) lengths = [ max(x) for x in zip(*[(len(name), len(host), len(str(port))) for name, (host, port) in self.nodeReg.items()]) ] fmt = " {{:<{}}} listens at {{:<{}}} on port {{:>{}}}".format( *lengths) for name, (host, port) in self.nodeReg.items(): logger.info(fmt.format(name, host, port)) else: logger.info("Client {} found an empty node registry:".format( self.alias)) Motor.__init__(self) self.inBox = deque() self.nodestack.connectNicelyUntil = 0 # don't need to connect # nicely as a client # TODO: Need to have couple of tests around `reqsPendingConnection` # where we check with and without pool ledger # Stores the requests that need to be sent to the nodes when the client # has made sufficient connections to the nodes. self.reqsPendingConnection = deque() # Tuple of identifier and reqId as key and value as tuple of set of # nodes which are expected to send REQACK self.expectingAcksFor = {} # Tuple of identifier and reqId as key and value as tuple of set of # nodes which are expected to send REPLY self.expectingRepliesFor = {} tp = loadPlugins(self.basedirpath) logger.debug("total plugins loaded in client: {}".format(tp))