Пример #1
0
async def _get_secret(ctx: wire.Context, cache_entry: int) -> bytes:
    secret = cache.get(cache_entry)
    if secret is None:
        await derive_and_store_roots(ctx)
        secret = cache.get(cache_entry)
        assert secret is not None
    return secret
Пример #2
0
    def test_Initialize(self):
        def call_Initialize(**kwargs):
            msg = Initialize(**kwargs)
            return await_result(handle_Initialize(DUMMY_CONTEXT, msg))

        # calling Initialize without an ID allocates a new one
        session_id = cache.start_session()
        features = call_Initialize()
        self.assertNotEqual(session_id, features.session_id)

        # calling Initialize with the current ID does not allocate a new one
        features = call_Initialize(session_id=session_id)
        self.assertEqual(session_id, features.session_id)

        # store "hello"
        cache.set(KEY, b"hello")
        # check that it is cleared
        features = call_Initialize()
        session_id = features.session_id
        self.assertIsNone(cache.get(KEY))
        # store "hello" again
        cache.set(KEY, b"hello")
        self.assertEqual(cache.get(KEY), b"hello")

        # supplying a different session ID starts a new cache
        call_Initialize(session_id=b"A" * cache._SESSION_ID_LENGTH)
        self.assertIsNone(cache.get(KEY))

        # but resuming a session loads the previous one
        call_Initialize(session_id=session_id)
        self.assertEqual(cache.get(KEY), b"hello")
Пример #3
0
    def test_start_session(self):
        session_id_a = cache.start_session()
        self.assertIsNotNone(session_id_a)
        session_id_b = cache.start_session()
        self.assertNotEqual(session_id_a, session_id_b)

        cache.clear_all()
        with self.assertRaises(cache.InvalidSessionError):
            cache.set(KEY, "something")
        with self.assertRaises(cache.InvalidSessionError):
            cache.get(KEY)
Пример #4
0
    def test_end_session(self):
        session_id = cache.start_session()
        self.assertTrue(cache.is_session_started())
        cache.set(KEY, b"A")
        cache.end_current_session()
        self.assertFalse(cache.is_session_started())
        self.assertRaises(cache.InvalidSessionError, cache.get, KEY)

        # ending an ended session should be a no-op
        cache.end_current_session()
        self.assertFalse(cache.is_session_started())

        session_id_a = cache.start_session(session_id)
        # original session no longer exists
        self.assertNotEqual(session_id_a, session_id)
        # original session data no longer exists
        self.assertIsNone(cache.get(KEY))

        # create a new session
        session_id_b = cache.start_session()
        # switch back to original session
        session_id = cache.start_session(session_id_a)
        self.assertEqual(session_id, session_id_a)
        # end original session
        cache.end_current_session()
        # switch back to B
        session_id = cache.start_session(session_id_b)
        self.assertEqual(session_id, session_id_b)
Пример #5
0
 def test_EndSession(self):
     self.assertRaises(cache.InvalidSessionError, cache.get, KEY)
     session_id = cache.start_session()
     self.assertTrue(cache.is_session_started())
     self.assertIsNone(cache.get(KEY))
     await_result(handle_EndSession(DUMMY_CONTEXT, EndSession()))
     self.assertFalse(cache.is_session_started())
     self.assertRaises(cache.InvalidSessionError, cache.get, KEY)
Пример #6
0
 def test_session_queue(self):
     session_id = cache.start_session()
     self.assertEqual(cache.start_session(session_id), session_id)
     cache.set(KEY, b"A")
     for i in range(cache._MAX_SESSIONS_COUNT):
         cache.start_session()
     self.assertNotEqual(cache.start_session(session_id), session_id)
     self.assertIsNone(cache.get(KEY))
Пример #7
0
async def get_keychain(ctx: wire.Context, namespaces: list) -> Keychain:
    if not storage.is_initialized():
        raise wire.NotInitialized("Device is not initialized")
    seed = cache.get(cache.APP_COMMON_SEED)
    if seed is None:
        passphrase = await get_passphrase(ctx)
        seed = mnemonic.get_seed(passphrase)
        cache.set(cache.APP_COMMON_SEED, seed)
    keychain = Keychain(seed, namespaces)
    return keychain
Пример #8
0
def derive_slip21_node_without_passphrase(path: list) -> Slip21Node:
    if not storage.is_initialized():
        raise Exception("Device is not initialized")
    seed = cache.get(cache.APP_COMMON_SEED_WITHOUT_PASSPHRASE)
    if seed is None:
        seed = mnemonic.get_seed(progress_bar=False)
        cache.set(cache.APP_COMMON_SEED_WITHOUT_PASSPHRASE, seed)
    node = Slip21Node(seed)
    node.derive_path(path)
    return node
Пример #9
0
def derive_node_without_passphrase(
    path: list, curve_name: str = "secp256k1"
) -> bip32.HDNode:
    if not storage.is_initialized():
        raise Exception("Device is not initialized")
    seed = cache.get(cache.APP_COMMON_SEED_WITHOUT_PASSPHRASE)
    if seed is None:
        seed = mnemonic.get_seed(progress_bar=False)
        cache.set(cache.APP_COMMON_SEED_WITHOUT_PASSPHRASE, seed)
    node = bip32.from_seed(seed, curve_name)
    node.derive_path(path)
    return node
Пример #10
0
    def test_empty_value(self):
        cache.start_session()

        self.assertIsNone(cache.get(KEY))
        cache.set(KEY, b"")
        self.assertEqual(cache.get(KEY), b"")

        cache.delete(KEY)
        run_count = 0

        @cache.stored(KEY)
        def func():
            nonlocal run_count
            run_count += 1
            return b""

        self.assertEqual(func(), b"")
        # function gets called once
        self.assertEqual(run_count, 1)
        self.assertEqual(func(), b"")
        # function is not called for a second time
        self.assertEqual(run_count, 1)
Пример #11
0
    def test_decorators(self):
        run_count = 0
        cache.start_session()

        @cache.stored(KEY)
        def func():
            nonlocal run_count
            run_count += 1
            return b"foo"

        # cache is empty
        self.assertIsNone(cache.get(KEY))
        self.assertEqual(run_count, 0)
        self.assertEqual(func(), b"foo")
        # function was run
        self.assertEqual(run_count, 1)
        self.assertEqual(cache.get(KEY), b"foo")
        # function does not run again but returns cached value
        self.assertEqual(func(), b"foo")
        self.assertEqual(run_count, 1)

        @cache.stored_async(KEY)
        async def async_func():
            nonlocal run_count
            run_count += 1
            return b"bar"

        # cache is still full
        self.assertEqual(await_result(async_func()), b"foo")
        self.assertEqual(run_count, 1)

        cache.start_session()
        self.assertEqual(await_result(async_func()), b"bar")
        self.assertEqual(run_count, 2)
        # awaitable is also run only once
        self.assertEqual(await_result(async_func()), b"bar")
        self.assertEqual(run_count, 2)
Пример #12
0
    def test_delete(self):
        session_id1 = cache.start_session()
        self.assertIsNone(cache.get(KEY))
        cache.set(KEY, b"hello")
        self.assertEqual(cache.get(KEY), b"hello")
        cache.delete(KEY)
        self.assertIsNone(cache.get(KEY))

        cache.set(KEY, b"hello")
        session_id2 = cache.start_session()
        self.assertIsNone(cache.get(KEY))
        cache.set(KEY, b"hello")
        self.assertEqual(cache.get(KEY), b"hello")
        cache.delete(KEY)
        self.assertIsNone(cache.get(KEY))

        cache.start_session(session_id1)
        self.assertEqual(cache.get(KEY), b"hello")
Пример #13
0
async def _get_keychain_bip39(
        ctx: wire.Context, derivation_type: CardanoDerivationType) -> Keychain:
    if not device.is_initialized():
        raise wire.NotInitialized("Device is not initialized")

    if derivation_type == CardanoDerivationType.LEDGER:
        seed = await get_seed(ctx)
        return Keychain(cardano.from_seed_ledger(seed))

    if not cache.get(cache.APP_COMMON_DERIVE_CARDANO):
        raise wire.ProcessError(
            "Cardano derivation is not enabled for this session")

    if derivation_type == CardanoDerivationType.ICARUS:
        cache_entry = cache.APP_CARDANO_ICARUS_SECRET
    else:
        cache_entry = cache.APP_CARDANO_ICARUS_TREZOR_SECRET

    secret = await _get_secret(ctx, cache_entry)
    root = cardano.from_secret(secret)
    return Keychain(root)
Пример #14
0
    async def derive_and_store_roots(ctx: wire.Context) -> None:
        if not device.is_initialized():
            raise wire.NotInitialized("Device is not initialized")

        need_seed = not cache.is_set(cache.APP_COMMON_SEED)
        need_cardano_secret = cache.get(
            cache.APP_COMMON_DERIVE_CARDANO
        ) and not cache.is_set(cache.APP_CARDANO_ICARUS_SECRET)

        if not need_seed and not need_cardano_secret:
            return

        passphrase = await get_passphrase(ctx)

        if need_seed:
            common_seed = mnemonic.get_seed(passphrase)
            cache.set(cache.APP_COMMON_SEED, common_seed)

        if need_cardano_secret:
            from apps.cardano.seed import derive_and_store_secrets

            derive_and_store_secrets(passphrase)
Пример #15
0
    def test_get_set(self):
        session_id1 = cache.start_session()
        cache.set(KEY, b"hello")
        self.assertEqual(cache.get(KEY), b"hello")

        session_id2 = cache.start_session()
        cache.set(KEY, b"world")
        self.assertEqual(cache.get(KEY), b"world")

        cache.start_session(session_id2)
        self.assertEqual(cache.get(KEY), b"world")
        cache.start_session(session_id1)
        self.assertEqual(cache.get(KEY), b"hello")

        cache.clear_all()
        with self.assertRaises(cache.InvalidSessionError):
            cache.get(KEY)
Пример #16
0
async def get_keychain(ctx: wire.Context) -> Keychain:
    root = cache.get(cache.APP_CARDANO_ROOT)

    if not storage.is_initialized():
        raise wire.NotInitialized("Device is not initialized")

    if root is None:
        passphrase = await get_passphrase(ctx)
        if mnemonic.is_bip39():
            # derive the root node from mnemonic and passphrase
            root = bip32.from_mnemonic_cardano(mnemonic.get_secret().decode(),
                                               passphrase)
        else:
            seed = mnemonic.get_seed(passphrase)
            root = bip32.from_seed(seed, "ed25519 cardano seed")

        # derive the namespaced root node
        for i in SEED_NAMESPACE:
            root.derive_cardano(i)
        storage.cache.set(cache.APP_CARDANO_ROOT, root)

    keychain = Keychain(SEED_NAMESPACE, root)
    return keychain
Пример #17
0
def derive_and_store_secrets(passphrase: str) -> None:
    assert device.is_initialized()
    assert cache.get(cache.APP_COMMON_DERIVE_CARDANO)

    if not mnemonic.is_bip39():
        # nothing to do for SLIP-39, where we can derive the root from the main seed
        return

    icarus_secret = mnemonic.derive_cardano_icarus(passphrase,
                                                   trezor_derivation=False)

    words = mnemonic.get_secret()
    assert words is not None, "Mnemonic is not set"
    # count ASCII spaces, add 1 to get number of words
    words_count = sum(c == 0x20 for c in words) + 1

    if words_count == 24:
        icarus_trezor_secret = mnemonic.derive_cardano_icarus(
            passphrase, trezor_derivation=True)
    else:
        icarus_trezor_secret = icarus_secret

    cache.set(cache.APP_CARDANO_ICARUS_SECRET, icarus_secret)
    cache.set(cache.APP_CARDANO_ICARUS_TREZOR_SECRET, icarus_trezor_secret)
Пример #18
0
    def test_lru_cache(self):
        class Deletable:
            def __init__(self):
                self.deleted = False

            def __del__(self):
                self.deleted = True

        cache = LRUCache(10)

        obj_a = Deletable()
        self.assertIsNone(cache.get("a"))
        cache.insert("a", obj_a)

        self.assertIs(cache.get("a"), obj_a)

        # test eviction
        objects = [(i, Deletable()) for i in range(10)]
        for key, obj in objects:
            cache.insert(key, obj)

        # object A should have been evicted
        self.assertIsNone(cache.get("a"))
        self.assertTrue(obj_a.deleted)

        cache.insert("a", obj_a)
        for key, obj in objects[:-1]:
            # objects should have been evicted in insertion order
            self.assertIsNone(cache.get(key))
            self.assertTrue(obj.deleted)
            cache.insert(key, obj)

        # use "a" object
        self.assertIs(cache.get("a"), obj_a)
        # insert last object
        key, obj = objects[-1]
        cache.insert(key, obj)

        # "a" is recently used so should not be evicted now
        self.assertIs(cache.get("a"), obj_a)
Пример #19
0
 async def get_seed(ctx: wire.Context) -> bytes:
     await derive_and_store_roots(ctx)
     common_seed = cache.get(cache.APP_COMMON_SEED)
     assert common_seed is not None
     return common_seed
Пример #20
0
  def train(self, docs_train, y_train, extra = {}, useCrossValidation = False, vect_options={}):

    options = dict(self.options.items() + extra.items())
    cv = StratifiedKFold(y_train, n_folds=10) if useCrossValidation else None

    pipeline = Pipeline([
        ('vect', TfidfVectorizer(charset_error='ignore', tokenizer=t.tokenize, **vect_options)),
        ('clf', self.clf),
    ])

    useGrid = sys.flags.optimize

    if useGrid:
        self.grid = GridSearchCV(
                pipeline, 
                options,
                cv=cv,
                refit=True,
                n_jobs=-1,
                verbose=1
              )
    else:
        self.grid = pipeline

    cache_key = str(self.grid) + str(docs_train)
    cached = cache.get(cache_key)
    
    if cached and sys.flags.debug == 0: 
        logging.debug("# Fetched cached version of %s " % self.clf.__class__.__name__)
        self.best_estimator = cached['est']
        self.best_score = cached['scr']
        self.best_params = cached['parm']

    else:
      logging.debug("# Training new instance of %s " % self.clf.__class__.__name__)

      self.grid.fit(docs_train, y_train)

      if useGrid:
          self.best_estimator = self.grid.best_estimator_
          self.best_params = self.grid.best_params_
          self.best_score = self.grid.best_score_
      else:
          self.best_estimator = self.grid
          self.best_params = self.grid.get_params(False)
          self.best_score = 1

          logging.debug("Saving to cache for %s " % self.clf.__class__.__name__)
          cache.save(cache_key, {
              "est": self.best_estimator,
              "scr": self.best_score,
              "parm": self.best_params
            })

    self.steps = self.best_estimator.named_steps

    logging.debug("# Best params for  %s :" % self.clf.__class__.__name__)
    logging.debug(self.best_params)

    logging.debug("# Best score for  %s :" % self.clf.__class__.__name__)
    logging.debug(self.best_score)

    return self.grid
Пример #21
0
    def train(self,
              docs_train,
              y_train,
              extra={},
              useCrossValidation=False,
              vect_options={}):

        options = dict(self.options.items() + extra.items())
        cv = StratifiedKFold(y_train,
                             n_folds=10) if useCrossValidation else None

        pipeline = Pipeline([
            ('vect',
             TfidfVectorizer(charset_error='ignore',
                             tokenizer=t.tokenize,
                             **vect_options)),
            ('clf', self.clf),
        ])

        useGrid = sys.flags.optimize

        if useGrid:
            self.grid = GridSearchCV(pipeline,
                                     options,
                                     cv=cv,
                                     refit=True,
                                     n_jobs=-1,
                                     verbose=1)
        else:
            self.grid = pipeline

        cache_key = str(self.grid) + str(docs_train)
        cached = cache.get(cache_key)

        if cached and sys.flags.debug == 0:
            logging.debug("# Fetched cached version of %s " %
                          self.clf.__class__.__name__)
            self.best_estimator = cached['est']
            self.best_score = cached['scr']
            self.best_params = cached['parm']

        else:
            logging.debug("# Training new instance of %s " %
                          self.clf.__class__.__name__)

            self.grid.fit(docs_train, y_train)

            if useGrid:
                self.best_estimator = self.grid.best_estimator_
                self.best_params = self.grid.best_params_
                self.best_score = self.grid.best_score_
            else:
                self.best_estimator = self.grid
                self.best_params = self.grid.get_params(False)
                self.best_score = 1

                logging.debug("Saving to cache for %s " %
                              self.clf.__class__.__name__)
                cache.save(
                    cache_key, {
                        "est": self.best_estimator,
                        "scr": self.best_score,
                        "parm": self.best_params
                    })

        self.steps = self.best_estimator.named_steps

        logging.debug("# Best params for  %s :" % self.clf.__class__.__name__)
        logging.debug(self.best_params)

        logging.debug("# Best score for  %s :" % self.clf.__class__.__name__)
        logging.debug(self.best_score)

        return self.grid