async def _set_wallets(an_data: dict) -> dict: """ Set wallets as configured for setnym operation. :param an_data: dict mapping profiles to anchor data :return: dict mapping anchor names to wallet objects """ w_mgr = WalletManager() rv = {} for profile in an_data: w_cfg = {'id': an_data[profile].name} if an_data[profile].wallet_type: w_cfg['storage_type'] = an_data[profile].wallet_type if an_data[profile].seed: w_cfg['seed'] = an_data[profile].seed if an_data[profile].did: w_cfg['did'] = an_data[profile].did if an_data[profile].wallet_create: try: await w_mgr.create(w_cfg, access=an_data[profile].wallet_access) except ExtantWallet: pass rv[profile] = w_mgr.get(w_cfg, access=an_data[profile].wallet_access) return rv
async def get_wallet(tsan_data: AnchorData): """ Get wallet given configuration data for Tails Server Anchor :param tsan_data: Tails Server Anchor data """ w_mgr = WalletManager() rv = None wallet_config = { 'id': tsan_data.name } if tsan_data.wallet_type: wallet_config['storage_type'] = tsan_data.wallet_type if tsan_data.wallet_create: if tsan_data.seed: wallet_config['seed'] = tsan_data.seed try: rv = await w_mgr.create(wallet_config, access=tsan_data.wallet_access) logging.info('Created wallet %s', tsan_data.name) except ExtantWallet: rv = w_mgr.get(wallet_config, access=tsan_data.wallet_access) logging.warning( 'Wallet %s already exists: remove seed and wallet.create from config file', tsan_data.name) else: rv = w_mgr.get(wallet_config, access=tsan_data.wallet_access) return rv
async def get_wallets(wallet_data, open_all, auto_remove=False): rv = {} w_mgr = WalletManager() for name in wallet_data: w = None creation_data = {'seed', 'did'} & { n for n in wallet_data[name] } # create for tests when seed or did specifies if creation_data: config = { 'id': name, **{k: wallet_data[name][k] for k in creation_data}, 'auto_remove': auto_remove } w = await w_mgr.create(config, access=wallet_data[name]['wallet.access'], replace=True) else: w = await w_mgr.get({ 'id': name, 'auto_remove': auto_remove }, access=wallet_data[name]['wallet.access']) if open_all: await w.open() assert w.did assert w.verkey rv[name] = w return rv
async def main(wallet_name: str) -> None: """ Main line for revocation registry builder operating in external process on behalf of issuer agent. :param wallet_name: wallet name - must match that of issuer with existing wallet """ logging.basicConfig(level=logging.WARN, format='%(levelname)-8s | %(name)-12s | %(message)s') logging.getLogger('indy').setLevel(logging.ERROR) path_start = join(RevRegBuilder.dir_tails_sentinel(wallet_name), '.start') with open(path_start, 'r') as fh_start: start_data = json.loads(fh_start.read()) remove(path_start) logging.getLogger(__name__).setLevel(start_data['logging']['level']) for path_log in start_data['logging']['paths']: logging.getLogger(__name__).addHandler(logging.FileHandler(path_log)) wallet = WalletManager().get( { 'id': wallet_name, 'storage_type': start_data['wallet']['storage_type'], **start_data['wallet']['config'], }, access=start_data['wallet']['access_creds'].get('key', None)) async with wallet, RevRegBuilder(wallet, rrbx=True) as rrban: await rrban.serve()
async def get_wallets(wallet_data, open_all, auto_remove=False): rv = {} w_mgr = WalletManager() for name in wallet_data: w = None creation_data = {'seed', 'did'} & {n for n in wallet_data[name]} if creation_data: w = await w_mgr.create( { 'id': name, **{k: wallet_data[name][k] for k in creation_data}, 'auto_remove': auto_remove }, replace=True) else: w = w_mgr.get({'id': name, 'auto_remove': auto_remove}) if open_all: await w.open() assert w.did assert w.verkey rv[name] = w return rv
async def test_anchors_tails_load( pool_name, pool_genesis_txn_data, seed_trustee1): rrbx = True print(Ink.YELLOW('\n\n== Load-testing tails on {}ternal rev reg builder ==').format("ex" if rrbx else "in")) await RevRegBuilder.stop(WALLET_NAME) # in case of re-run # Set up node pool ledger config and wallets, open pool, init anchors p_mgr = NodePoolManager() if pool_name not in await p_mgr.list(): await p_mgr.add_config(pool_name, pool_genesis_txn_data) pool = p_mgr.get(pool_name) await pool.open() w_mgr = WalletManager() wallets = { 'trustee-anchor': { 'seed': seed_trustee1, 'storage_type': None, 'config': None, 'access_creds': None }, WALLET_NAME: { 'seed': 'Superstar-Anchor-000000000000000', 'storage_type': None, 'config': None, 'access_creds': { 'key': 'rrbx-test' } } } for (name, wdata) in wallets.items(): try: wdata['wallet'] = await w_mgr.create({ 'id': name, 'seed': wdata['seed'] }) except ExtantWallet: wdata['wallet'] = w_mgr.get({'id': name}) finally: await wdata['wallet'].open() tan = TrusteeAnchor(wallets['trustee-anchor']['wallet'], pool) no_prox = rrbx_prox() san = OrgHubAnchor(wallets[WALLET_NAME]['wallet'], pool, rrbx=rrbx) if rrbx: await beep('external rev reg builder process on {}'.format(WALLET_NAME), 15) if rrbx_prox() != no_prox + 1: await RevRegBuilder.stop(WALLET_NAME) assert False, "External rev reg builder process did not start" async with OrgHubAnchor( wallets[WALLET_NAME]['wallet'], pool, rrbx=rrbx): # check for exactly 1 external rev reg builder process await beep('external rev reg builder process uniqueness test on {}'.format(WALLET_NAME), 5) if rrbx_prox() != no_prox + 1: await RevRegBuilder.stop(WALLET_NAME) assert False, "External rev reg builder process was not unique" assert pool.handle await tan.open() await san.open() # Publish anchor particulars to ledger if not yet present for an in (tan, san): if not json.loads(await tan.get_nym(an.did)): await tan.send_nym(an.did, an.verkey, an.wallet.name, an.least_role()) nyms = { 'tan': json.loads(await tan.get_nym(tan.did)), 'san': json.loads(await tan.get_nym(san.did)) } print('\n\n== 1 == nyms: {}'.format(ppjson(nyms))) for k in nyms: assert 'dest' in nyms[k] # Publish schema to ledger if not yet present; get from ledger S_ID = schema_id(san.did, 'tails_load', '{}.0'.format(int(time.time()))) S_KEY = schema_key(S_ID) schema_data = { 'name': schema_key(S_ID).name, 'version': schema_key(S_ID).version, 'attr_names': [ 'number', 'remainder' ] } try: await san.get_schema(S_KEY) # may exist (almost certainly not) except AbsentSchema: await san.send_schema(json.dumps(schema_data)) schema_json = await san.get_schema(S_KEY) schema = json.loads(schema_json) assert schema # should exist now print('\n\n== 2 == SCHEMA [{} v{}]: {}'.format(S_KEY.name, S_KEY.version, ppjson(schema))) # Setup link secret for creation of cred req or proof await san.create_link_secret('LinkSecret') # SRI anchor create, store, publish cred definitions to ledger; create cred offers await san.send_cred_def(S_ID, revo=True) cd_id = cred_def_id(S_KEY.origin_did, schema['seqNo'], pool.protocol) assert ((not Tails.unlinked(san.dir_tails)) and [f for f in Tails.links(san.dir_tails, san.did) if cd_id in f]) cred_def_json = await san.get_cred_def(cd_id) # ought to exist now cred_def = json.loads(cred_def_json) print('\n\n== 3.0 == Cred def [{} v{}]: {}'.format( S_KEY.name, S_KEY.version, ppjson(json.loads(cred_def_json)))) assert cred_def.get('schemaId', None) == str(schema['seqNo']) cred_offer_json = await san.create_cred_offer(schema['seqNo']) print('\n\n== 3.1 == Credential offer [{} v{}]: {}'.format( S_KEY.name, S_KEY.version, ppjson(cred_offer_json))) (cred_req_json, cred_req_metadata_json) = await san.create_cred_req(cred_offer_json, cd_id) print('\n\n== 4 == Credential request [{} v{}]: metadata {}, cred-req {}'.format( S_KEY.name, S_KEY.version, ppjson(cred_req_metadata_json), ppjson(cred_req_json))) assert json.loads(cred_req_json) # BC Reg anchor (as Issuer) issues creds and stores at HolderProver: get cred req, create cred, store cred CREDS = 4034 # enough to kick off rev reg on size 4096 and issue two creds in it: 1 needing set-rev-reg, 1 not print('\n\n== 5 == creating {} credentials'.format(CREDS)) swatch = Stopwatch(2) optima = {} # per rev-reg, fastest/slowest pairs for number in range(CREDS): swatch.mark() (cred_json, _) = await san.create_cred( cred_offer_json, cred_req_json, { 'number': str(number), 'remainder': str(number % 100) }) elapsed = swatch.mark() tag = rev_reg_id2tag(Tails.current_rev_reg_id(san.dir_tails, cd_id)) if tag not in optima: optima[tag] = (elapsed, elapsed) else: optima[tag] = (min(optima[tag][0], elapsed), max(optima[tag][1], elapsed)) print('.', end='', flush=True) if ((number + 1) % 100) == 0: print('{}: #{}: {:.2f}-{:.2f}s'.format(number + 1, tag, *optima[tag]), flush=True) assert json.loads(cred_json) print('{}: #{}: {:.2f}-{:.2f}s'.format(number + 1, tag, *optima[tag]), flush=True) print('\n\n== 6 == best, worst times by revocation registry: {}'.format(ppjson(optima))) assert (not rrbx) or (max(optima[tag][1] for tag in optima) < 4 * min(optima[tag][1] for tag in optima if int(tag) > 0)) # if waiting on rr beyond #0, sizes increase as 2^n await san.close() if rrbx: await RevRegBuilder.stop(WALLET_NAME) await tan.close() for (name, wdata) in wallets.items(): await wdata['wallet'].close() await pool.close()
def boot() -> None: """ Boot the service: instantiate tails server anchor. Raise AbsentPool if node pool ledger configuration neither present nor sufficiently specified; raise AbsentNym if tails server anchor nym is not on the ledger. """ config = do_wait(MEM_CACHE.get('config')) # setup pool and wallet pool_data = NodePoolData(config['Node Pool']['name'], config['Node Pool'].get('genesis.txn.path', None) or None) # nudge empty value from '' to None p_mgr = NodePoolManager() if pool_data.name not in do_wait(p_mgr.list()): if pool_data.genesis_txn_path: do_wait( p_mgr.add_config(pool_data.name, pool_data.genesis_txn_path)) else: LOGGER.debug( 'Node pool %s has no ledger configuration but %s specifies no genesis txn path', pool_data.name, do_wait(MEM_CACHE.get('config.ini'))) raise AbsentPool( 'Node pool {} has no ledger configuration but {} specifies no genesis txn path' .format(pool_data.name, do_wait(MEM_CACHE.get('config.ini')))) pool = p_mgr.get(pool_data.name) do_wait(pool.open()) do_wait(MEM_CACHE.set('pool', pool)) # instantiate tails server anchor tsan_data = AnchorData( Role.USER, config['VON Anchor']['name'], config['VON Anchor'].get('seed', None) or None, None, config['VON Anchor'].get('wallet.create', '0').lower() in ['1', 'true', 'yes'], config['VON Anchor'].get('wallet.type', None) or None, config['VON Anchor'].get('wallet.access', None) or None) w_mgr = WalletManager() wallet = None wallet_config = {'id': tsan_data.name} if tsan_data.wallet_type: wallet_config['storage_type'] = tsan_data.wallet_type if tsan_data.wallet_create: if tsan_data.seed: wallet_config['seed'] = tsan_data.seed try: wallet = do_wait( w_mgr.create(wallet_config, access=tsan_data.wallet_access)) LOGGER.info('Created wallet %s', tsan_data.name) except ExtantWallet: wallet = w_mgr.get(wallet_config, access=tsan_data.wallet_access) LOGGER.warning( 'Wallet %s already exists: remove seed and wallet.create from config file', tsan_data.name) else: wallet = w_mgr.get(wallet_config, access=tsan_data.wallet_access) do_wait(wallet.open()) tsan = NominalAnchor(wallet, pool) do_wait(tsan.open()) if not json.loads(do_wait(tsan.get_nym())): LOGGER.debug('Anchor %s has no cryptonym on ledger %s', tsan_data.wallet_name, pool_data.name) raise AbsentNym('Anchor {} has no cryptonym on ledger {}'.format( tsan_data.wallet_name, pool_data.name)) do_wait(MEM_CACHE.set('tsan', tsan))
async def setup(ini_path: str) -> tuple: """ Set configuration from file. If configured profile is issuer, open and return node pool and anchor, then register both for shutdown at program exit. :param ini_path: path to configuration file :return: tuple (profile, issuer anchor) for issuer or (profile, None) for prover. """ global CONFIG CONFIG = inis2dict(ini_path) profile = Profile.get(CONFIG['Tails Client']['profile']) if profile != Profile.ISSUER: return (profile, None) pool_data = NodePoolData(CONFIG['Node Pool']['name'], CONFIG['Node Pool'].get('genesis.txn.path', None) or None) # nudge empty value from '' to None # Set up node pool ledger config and wallet manager = NodePoolManager() if pool_data.name not in await manager.list(): if pool_data.genesis_txn_path: await manager.add_config(pool_data.name, pool_data.genesis_txn_path) else: logging.error( 'Node pool %s has no ledger configuration but %s specifies no genesis txn path', pool_data.name, ini_path) return (None, None) pool = manager.get(pool_data.name) await pool.open() atexit.register(close_pool, pool) noman_data = AnchorData( Role.USER, CONFIG['VON Anchor']['name'], CONFIG['VON Anchor'].get('seed', None) or None, None, CONFIG['VON Anchor'].get('wallet.create', '0').lower() in ['1', 'true', 'yes'], CONFIG['VON Anchor'].get('wallet.type', None) or None, CONFIG['VON Anchor'].get('wallet.access', None) or None) w_mgr = WalletManager() wallet = None wallet_config = {'id': noman_data.name} if noman_data.wallet_type: wallet_config['storage_type'] = noman_data.wallet_type if noman_data.wallet_create: if noman_data.seed: wallet_config['seed'] = noman_data.seed try: wallet = await w_mgr.create(wallet_config, access=noman_data.wallet_access) logging.info('Created wallet %s', noman_data.name) except ExtantWallet: wallet = w_mgr.get(wallet_config, access=noman_data.wallet_access) logging.warning( 'Wallet %s already exists: remove seed and wallet.create from config file', noman_data.name) else: wallet = w_mgr.get(wallet_config, access=noman_data.wallet_access) await wallet.open() noman = NominalAnchor(wallet, pool) await noman.open() atexit.register(close_anchor, noman) return (profile, noman)