示例#1
0
 async def seed_to_did(self, seed):
     """
 Resolve a DID and verkey from a seed
 """
     wallet = Wallet(seed, seed + '-wallet')
     async with _BaseAnchor(await wallet.create(), self.pool) as new_agent:
         did = new_agent.did
         verkey = new_agent.verkey
         return (did, verkey)
示例#2
0
async def get_wallets(wallet_data, open_all, auto_remove=False):
    rv = {}
    for (name, seed) in wallet_data.items():
        w = Wallet(name, storage_type=None, config={'auto-remove': True} if auto_remove else None)
        try:
            if seed:
                await w.create(seed)
        except ExtantWallet:
            pass
        if open_all:
            await w.open()
        rv[name] = w
    return rv
示例#3
0
    async def create(self,
                     config: dict = None,
                     access: str = None,
                     replace: bool = False) -> Wallet:
        """
        Create wallet on input name with given configuration and access credential value.

        Raise ExtantWallet if wallet on input name exists already and replace parameter is False.
        Raise BadAccess on replacement for bad access credentials value.

        FAIR WARNING: specifying replace=True attempts to remove any matching wallet before proceeding; to
        succeed, the existing wallet must use the same access credentials that the input configuration has.

        :param config: configuration data for both indy-sdk and VON anchor wallet:

            - 'name' or 'id': wallet name
            - 'storage_type': storage type
            - 'freshness_time': freshness time
            - 'did': (optional) DID to use
            - 'seed': (optional) seed to use
            - 'auto_create': whether to create the wallet on first open (persists past close, can work with auto_remove)
            - 'auto_remove': whether to remove the wallet on next close
            - 'link_secret_label': (optional) link secret label to use to create link secret

        :param access: indy wallet access credential ('key') value, if different than default
        :param replace: whether to replace old wallet if it exists
        :return: wallet created
        """

        LOGGER.debug(
            'WalletManager.create >>> config %s, access %s, replace %s',
            config, access, replace)

        assert {'name', 'id'} & {k for k in config}
        wallet_name = config.get('name', config.get('id'))
        if replace:
            von_wallet = self.get(config, access)
            if not await von_wallet.remove():
                LOGGER.debug(
                    'WalletManager.create <!< Failed to remove wallet %s for replacement',
                    wallet_name)
                raise ExtantWallet(
                    'Failed to remove wallet {} for replacement'.format(
                        wallet_name))

        indy_config = self._config2indy(config)
        von_config = self._config2von(config, access)
        rv = Wallet(indy_config, von_config)
        await rv.create()
        LOGGER.debug('WalletManager.create <<< %s', rv)
        return rv
示例#4
0
  def __init__(self):
    self._cache = None
    self._instance = None
    self._ready = False
    self._sync_lock = None

    pool_cfg = None # {'protocol': protocol_version}
    self._pool = NodePool(
      'nodepool',
      '/home/indy/.indy-cli/networks/sandbox/pool_transactions_genesis',
      pool_cfg,
    )
    self._wallet = Wallet(
      '000000000000000000000000Trustee1',
      'trustee_wallet',
    )
示例#5
0
    def __init__(self):
        self._cache = None
        self._instance = None
        self._ready = False
        self._ledger_lock = None
        self._sync_lock = None

        pool_cfg = None  # {'protocol': protocol_version}
        self._pool = NodePool(
            'nodepool',
            get_genesis_file(),
            pool_cfg,
        )
        self._wallet = Wallet(
            LEDGER_SEED,
            'trustee_wallet',
        )
示例#6
0
async def test_wallet(path_home):

    seed = '00000000000000000000000000000000'
    name = 'my-wallet'
    path = Path(path_home, 'wallet', name)
    path_seed2did = path.with_name('{}.seed2did'.format(path.name))

    # 1. Configuration with auto-remove set
    w = Wallet(seed, name, None, {'auto-remove': True})
    await w.create()
    assert path.exists(), 'Wallet path {} not present'.format(path)
    await w.open()
    assert w.did
    assert w.verkey
    await w.close()
    assert not path.exists(), 'Wallet path {} still present'.format(path)
    assert not path_seed2did.exists(), 'Wallet path {} still present'.format(path_seed2did)
    print('\n\n== 1 == New wallet with auto-remove OK')

    # 2. Default configuration (auto-remove=False)
    w = Wallet(seed, name)
    await w.create()
    assert path.exists(), 'Wallet path {} not present'.format(path)
    assert not path_seed2did.exists(), 'Wallet path {} still present'.format(path_seed2did)

    await w.open()
    assert w.did
    assert w.verkey
    (w_did, w_verkey) = (w.did, w.verkey)
    await w.close()
    assert path.exists(), 'Wallet path {} not present'.format(path)
    assert not path_seed2did.exists(), 'Wallet path {} still present'.format(path_seed2did)
    print('\n\n== 2 == New wallet with default config (no auto-remove) OK')

    # 3. Make sure wallet opens from extant file
    x = Wallet(seed, name, None, {'auto-remove': True})
    await x.create()

    async with x:
        assert x.did == w_did
        assert x.verkey == w_verkey

    assert not path.exists(), 'Wallet path {} still present'.format(path)
    assert not path_seed2did.exists(), 'Wallet path {} still present'.format(path_seed2did)
    print('\n\n== 3 == Re-use extant wallet OK')

    # 4. Double-open
    try:
        async with await Wallet(seed, name, None, {'auto-remove': True}).create() as w:
            async with w:
                assert False
    except IndyError as e:
        assert e.error_code == ErrorCode.WalletAlreadyOpenedError

    assert not path.exists(), 'Wallet path {} still present'.format(path)
    assert not path_seed2did.exists(), 'Wallet path {} still present'.format(path_seed2did)

    # 5. Bad config
    try:
        Wallet(seed, name, None, {'auto-remove': 'a suffusion of yellow'})
    except JSONValidation:
        pass
    print('\n\n== 4 == Error cases error as expected')
示例#7
0
async def setnym(ini_path: str) -> int:
    """
    Set configuration. Open pool, trustee anchor, and wallet of anchor whose nym to send.
    Register exit hooks to close pool and trustee anchor.

    Engage trustee anchor to send nym for VON anchor, if it differs on the ledger from configuration.

    :param ini_path: path to configuration file
    :return: 0 for OK, 1 for failure
    """

    config = inis2dict(ini_path)
    cfg_van_role = config['VON Anchor'].get(
        'role', None) or None  # nudge empty value from '' to None
    if not ok_role(cfg_van_role):
        raise BadRole('Configured role {} is not valid'.format(cfg_van_role))

    if config['Trustee Anchor']['wallet.name'] == config['VON Anchor'][
            'wallet.name']:
        raise ExtantWallet(
            'Wallet names must differ between VON Anchor and Trustee Anchor')

    pool_data = NodePoolData(
        config['Node Pool']['name'],
        config['Node Pool'].get('genesis.txn.path', None) or None)
    an_data = {
        'tan':
        AnchorData(Role.TRUSTEE, config['Trustee Anchor'].get('seed', None)
                   or None, config['Trustee Anchor']['wallet.name'],
                   config['Trustee Anchor'].get('wallet.type', None) or None,
                   config['Trustee Anchor'].get('wallet.key', None) or None),
        'van':
        AnchorData(Role.get(cfg_van_role),
                   config['VON Anchor'].get('seed', None) or None,
                   config['VON Anchor']['wallet.name'],
                   config['VON Anchor'].get('wallet.type', None) or None,
                   config['VON Anchor'].get('wallet.key', None) or None)
    }
    an_wallet = {
        an: Wallet(an_data[an].wallet_name, an_data[an].wallet_type, None,
                   {'key': an_data[an].wallet_key}
                   if an_data[an].wallet_key else None)
        for an in an_data
    }

    for anchor in an_data:  # create wallet if seed configured, silently continue if extant
        if an_data[anchor].seed:
            try:
                await an_wallet[anchor].create(an_data[anchor].seed)
            except ExtantWallet:
                pass

    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:
            raise AbsentPool(
                'Node pool {} has no ledger configuration, but {} specifies no genesis txn path'
                .format(pool_data.name, ini_path))

    async with an_wallet['tan'] as w_tan, (an_wallet['van']) as w_van, (
            manager.get(pool_data.name)) as pool, (TrusteeAnchor(
                w_tan, pool)) as tan, (NominalAnchor(w_van, pool)) as van:

        send_verkey = van.verkey
        try:
            nym_role = await tan.get_nym_role(van.did)
            if an_data['van'].role == nym_role:
                return 0  # ledger is as per configuration
            send_verkey = None  # only owner can touch verkey
            await tan.send_nym(van.did, send_verkey, van.wallet.name,
                               Role.ROLE_REMOVE)
        except AbsentNym:
            pass  # cryptonym not there yet, fall through

        await tan.send_nym(van.did, send_verkey, van.wallet.name,
                           an_data['van'].role)

    return 0
示例#8
0
async def test_anchors_tails_load(pool_ip, 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"))

    WALLET_NAME = 'superstar'
    await RevRegBuilder.stop(WALLET_NAME)  # in case of re-run

    # Set up node pool ledger config and wallets, open pool, init anchors
    manager = NodePoolManager()
    if pool_name not in await manager.list():
        await manager.add_config(pool_name, pool_genesis_txn_data)
    pool = manager.get(pool_name)
    await pool.open()

    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():
        wdata['wallet'] = Wallet(name, None, wdata['config'],
                                 wdata['access_creds'])
        try:
            await wdata['wallet'].create(wdata['seed'])
        except ExtantWallet:
            pass
        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), 5)
        assert rrbx_prox() == no_prox + 1
        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)
            assert rrbx_prox() == no_prox + 1

    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)))
    '''
    # wait for rev reg builder to spin up?
    if rrbx:
        while not isfile(join(san._dir_tails_sentinel, '.pid')):
            await asyncio.sleep(1)
    '''

    # 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, revocation=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'])
    cred_offer = json.loads(cred_offer_json)
    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)
    cred_req = json.loads(cred_req_json)
    print(
        '\n\n== 4 == Credential request [{} v{}]: metadata {}, cred {}'.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('\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()
示例#9
0
async def test_wallet(path_home):

    print(Ink.YELLOW('\n\n== Testing Wallet Configuration + Context =='))

    seed = '00000000000000000000000000000000'
    name = 'my-wallet'
    access_creds = {'key': 'secret-squirrel'}
    path = Path(path_home, 'wallet', name)

    # 1. Configuration with auto-remove set
    w = Wallet(name, None, {'auto-remove': True}, access_creds=access_creds)
    await w.create(seed)
    assert path.exists(), 'Wallet path {} not present'.format(path)
    await w.open()
    assert w.did
    assert w.verkey
    await w.close()
    assert not path.exists(), 'Wallet path {} still present'.format(path)
    print('\n\n== 1 == New wallet with auto-remove OK')

    # 2. Default configuration (auto-remove=False)
    w = Wallet(name, access_creds=access_creds)
    await w.create(seed)
    assert path.exists(), 'Wallet path {} not present'.format(path)

    await w.open()
    assert w.did
    assert w.verkey
    (w_did, w_verkey) = (w.did, w.verkey)
    await w.close()
    assert path.exists(), 'Wallet path {} not present'.format(path)
    print('\n\n== 2 == New wallet with default config (no auto-remove) OK')

    # 3. Make sure wallet opens from extant file, only on correct access credentials
    x = Wallet(name, None, {'auto-remove': True})
    try:
        await x.create(seed)
    except ExtantWallet:
        pass

    try:
        async with x:
            assert False
    except IndyError as x_indy:
        assert x_indy.error_code == ErrorCode.WalletAccessFailed

    ww = Wallet(name, None, {'auto-remove': True}, access_creds=access_creds)
    async with ww:
        assert ww.did == w_did
        assert ww.verkey == w_verkey

    assert not path.exists(), 'Wallet path {} still present'.format(path)
    print('\n\n== 3 == Re-use extant wallet on good access creds OK, wrong access creds fails as expected')

    # 4. Double-open
    try:
        w = await Wallet(name, None, {'auto-remove': True}).create(seed)
        async with w:
            async with w:
                assert False
    except WalletState:
        pass

    assert not path.exists(), 'Wallet path {} still present'.format(path)

    # 5. Bad config
    try:
        Wallet(name, None, {'auto-remove': 'a suffusion of yellow'})
    except JSONValidation:
        pass
    print('\n\n== 4 == Error cases error as expected')