Ejemplo n.º 1
0
  def test_stop_threshold_zero(self):
    """
    ``stop`` provided, ``threshold`` is 0.
    """
    # Note that the first address has a zero balance.
    self.adapter.seed_response('getBalances', {
      'balances': [0, 1],
    })

    # To keep the unit test nice and speedy, we will mock the address
    # generator.  We already have plenty of unit tests for that
    # functionality, so we can get away with mocking it here.
    mock_address_generator = mock.Mock(return_value=[self.addy0, self.addy1])

    with mock.patch(
        'iota.crypto.addresses.AddressGenerator.get_addresses',
        mock_address_generator,
    ):
      response = self.command(
        seed      = Seed.random(),
        stop      = 2,
        threshold = 0,
      )

    self.assertEqual(response['totalBalance'], 1)
    self.assertEqual(len(response['inputs']), 1)

    # Address 0 was skipped because it has a zero balance.
    input0 = response['inputs'][0]
    self.assertIsInstance(input0, Address)

    self.assertEqual(input0, self.addy1)
    self.assertEqual(input0.balance, 1)
    self.assertEqual(input0.key_index, 1)
Ejemplo n.º 2
0
  def test_no_stop_threshold_not_met(self):
    """
    No ``stop`` provided, balance does not meet ``threshold``.
    """
    self.adapter.seed_response('getBalances', {
      'balances': [42, 29, 0],
    })

    # To keep the unit test nice and speedy, we will mock the address
    # generator.  We already have plenty of unit tests for that
    # functionality, so we can get away with mocking it here.
    # noinspection PyUnusedLocal
    def mock_address_generator(ag, start, step=1):
      for addy in [self.addy0, self.addy1, self.addy2][start::step]:
        yield addy

    # When ``stop`` is None, the command uses a generator internally.
    with mock.patch(
        'iota.crypto.addresses.AddressGenerator.create_iterator',
        mock_address_generator,
    ):
      with self.assertRaises(BadApiResponse):
        self.command(
          seed      = Seed.random(),
          threshold = 72,
        )
Ejemplo n.º 3
0
  def test_no_transactions(self):
    """
    There are no transactions for the specified seed.
    """
    # To speed up the test, we will mock the address generator.
    # :py:class:`iota.crypto.addresses.AddressGenerator` already has
    # its own test case, so this does not impact the stability of the
    # codebase.
    # noinspection PyUnusedLocal
    def create_generator(ag, start, step=1):
      for addy in [self.addy1][start::step]:
        yield addy

    self.adapter.seed_response(
      'findTransactions',

      {
        'duration': 1,
        'hashes':   [],
      },
    )

    with mock.patch(
        'iota.crypto.addresses.AddressGenerator.create_iterator',
        create_generator,
    ):
      response = self.command(seed=Seed.random())

    self.assertDictEqual(response, {'bundles': []})
Ejemplo n.º 4
0
  def test_generate_multiple_digests(self):
    """
    Generating multiple digests.
    """
    seed = Seed.random()

    mock_get_private_keys =\
      mock.Mock(return_value={'keys': [self.key1, self.key2]})

    with mock.patch(
        'iota.multisig.commands.get_private_keys.GetPrivateKeysCommand._execute',
        mock_get_private_keys
    ):
      # noinspection PyUnresolvedReferences
      with mock.patch.object(self.key1, 'get_digest') as mock_get_digest_1: # type: mock.MagicMock
        mock_get_digest_1.return_value = self.digest1

        # noinspection PyUnresolvedReferences
        with mock.patch.object(self.key2, 'get_digest') as mock_get_digest_2: # type: mock.MagicMock
          mock_get_digest_2.return_value = self.digest2

          result = self.command(seed=seed, index=0, count=2, securityLevel=1)

    self.assertDictEqual(result, {'digests': [self.digest1, self.digest2]})

    mock_get_private_keys.assert_called_once_with({
      'count':          2,
      'index':          0,
      'securityLevel':  1,
      'seed':           seed,
    })
Ejemplo n.º 5
0
  def test_start(self):
    """
    Using ``start`` to offset the key range.
    """
    self.adapter.seed_response('getBalances', {
      'balances': [86],
    })

    # ``getInputs`` uses ``findTransactions`` to identify unused
    # addresses.
    # noinspection SpellCheckingInspection
    self.adapter.seed_response('findTransactions', {
      'hashes': [
        TransactionHash(
          b'TESTVALUE9DONTUSEINPRODUCTION99999YFXGOD'
          b'GISBJAX9PDJIRDMDV9DCRDCAEG9FN9KECCBDDFZ9H'
        ),
      ],
    })

    self.adapter.seed_response('findTransactions', {
      'hashes': [],
    })

    # To keep the unit test nice and speedy, we will mock the address
    # generator.  We already have plenty of unit tests for that
    # functionality, so we can get away with mocking it here.
    # noinspection PyUnusedLocal
    def mock_address_generator(ag, start, step=1):
      # If ``start`` has the wrong value, return garbage to make the
      # test asplode.
      for addy in [None, self.addy1, self.addy2][start::step]:
        yield addy

    # When ``stop`` is None, the command uses a generator internally.
    with mock.patch(
        'iota.crypto.addresses.AddressGenerator.create_iterator',
        mock_address_generator,
    ):
      response = self.command(
        seed  = Seed.random(),
        start = 1,
      )

    self.assertEqual(response['totalBalance'], 86)
    self.assertEqual(len(response['inputs']), 1)

    input0 = response['inputs'][0]
    self.assertIsInstance(input0, Address)

    self.assertEqual(input0, self.addy1)
    self.assertEqual(input0.balance, 86)
    self.assertEqual(input0.key_index, 1)
Ejemplo n.º 6
0
  def __init__(self, adapter, seed=None, testnet=False):
    # type: (AdapterSpec, Optional[TrytesCompatible], bool) -> None
    """
    :param seed:
      Seed used to generate new addresses.
      If not provided, a random one will be generated.

      Note: This value is never transferred to the node/network.
    """
    super(Iota, self).__init__(adapter, testnet)

    self.seed = Seed(seed) if seed else Seed.random()
Ejemplo n.º 7
0
 def test_fail_index_too_small(self):
     """
 ``index`` is less than 0.
 """
     self.assertFilterErrors(
         {
             'index': -1,
             'seed': Seed(self.seed),
         },
         {
             'index': [f.Min.CODE_TOO_SMALL],
         },
     )
Ejemplo n.º 8
0
 def test_fail_count_too_small(self):
     """
 ``count`` is less than 1.
 """
     self.assertFilterErrors(
         {
             'count': 0,
             'seed': Seed(self.seed),
         },
         {
             'count': [f.Min.CODE_TOO_SMALL],
         },
     )
Ejemplo n.º 9
0
 def test_fail_inclusion_states_wrong_type(self):
     """
 ``inclusionStates`` is not a boolean.
 """
     self.assertFilterErrors(
         {
             'inclusionStates': '1',
             'seed': Seed(self.seed),
         },
         {
             'inclusionStates': [f.Type.CODE_WRONG_TYPE],
         },
     )
Ejemplo n.º 10
0
 def test_fail_index_float(self):
     """
 ``index`` is a float value.
 """
     self.assertFilterErrors(
         {
             # Not valid, even with an empty fpart; it must be an int.
             'index': 42.0,
             'seed': Seed(self.seed),
         },
         {
             'index': [f.Type.CODE_WRONG_TYPE],
         },
     )
Ejemplo n.º 11
0
    def test_fail_securityLevel_float(self):
        """
    ``securityLevel`` is a float value.
    """
        self.assertFilterErrors(
            {
                'securityLevel': 1.0,
                'seed': Seed(self.seed),
            },

            {
                'securityLevel': [f.Type.CODE_WRONG_TYPE],
            },
        )
Ejemplo n.º 12
0
    def test_fail_checksum_wrong_type(self):
        """
    ``checksum`` is not a boolean.
    """
        self.assertFilterErrors(
            {
                'checksum': '2',
                'seed': Seed(self.seed),
            },

            {
                'checksum': [f.Type.CODE_WRONG_TYPE],
            },
        )
Ejemplo n.º 13
0
 def test_fail_stop_occurs_before_start(self):
     """
 ``stop`` is less than ``start``.
 """
     self.assertFilterErrors(
         {
             'start': 1,
             'stop': 0,
             'seed': Seed(self.seed),
         },
         {
             'start': [GetAccountDataRequestFilter.CODE_INTERVAL_INVALID],
         },
     )
Ejemplo n.º 14
0
 def test_fail_interval_too_large(self):
     """
 ``stop`` is way more than ``start``.
 """
     self.assertFilterErrors(
         {
             'start': 0,
             'stop': GetAccountDataRequestFilter.MAX_INTERVAL + 1,
             'seed': Seed(self.seed),
         },
         {
             'stop': [GetAccountDataRequestFilter.CODE_INTERVAL_TOO_BIG],
         },
     )
Ejemplo n.º 15
0
    def test_pass_happy_path(self):
        """
    Request is valid.
    """
        request = {
            'seed': Seed(self.seed),
            'index': 1,
            'count': 1,
        }

        filter_ = self._filter(request)

        self.assertFilterPasses(filter_)
        self.assertDictEqual(filter_.cleaned_data, request)
Ejemplo n.º 16
0
 def test_fail_index_string(self):
     """
 ``index`` is a string value.
 """
     self.assertFilterErrors(
         {
             # Not valid; it must be an int.
             'index': '42',
             'seed': Seed(self.seed),
         },
         {
             'index': [f.Type.CODE_WRONG_TYPE],
         },
     )
Ejemplo n.º 17
0
 def test_fail_stop_string(self):
     """
 ``stop`` is a string.
 """
     self.assertFilterErrors(
         {
             # Not valid; it must be an int.
             'stop': '0',
             'seed': Seed(self.seed),
         },
         {
             'stop': [f.Type.CODE_WRONG_TYPE],
         },
     )
Ejemplo n.º 18
0
    def test_pass_optional_parameters_omitted(self):
        """
    Request omits optional parameters.
    """
        filter_ = self._filter({
            'depth': 100,
            'minWeightMagnitude': 13,
            'seed': Seed(self.trytes2),
            'transfers': [self.transfer1, self.transfer2],
        })

        self.assertFilterPasses(filter_)
        self.assertDictEqual(
            filter_.cleaned_data, {
                'changeAddress': None,
                'inputs': None,
                'reference': None,
                'depth': 100,
                'minWeightMagnitude': 13,
                'securityLevel': AddressGenerator.DEFAULT_SECURITY_LEVEL,
                'seed': Seed(self.trytes2),
                'transfers': [self.transfer1, self.transfer2],
            })
Ejemplo n.º 19
0
  def test_fail_security_level_too_big(self):
    """
    ``securityLevel`` is > 3.
    """
    self.assertFilterErrors(
      {
        'securityLevel':  4,
        'seed':           Seed(self.seed),
      },

      {
        'securityLevel': [f.Max.CODE_TOO_BIG],
      },
    )
Ejemplo n.º 20
0
  def test_fail_security_level_wrong_type(self):
    """
    ``securityLevel`` is not an int.
    """
    self.assertFilterErrors(
      {
        'securityLevel':  '2',
        'seed':           Seed(self.seed),
      },

      {
        'securityLevel': [f.Type.CODE_WRONG_TYPE],
      },
    )
Ejemplo n.º 21
0
  def prompt_for_seed():
    # type: () -> Seed
    """
    Prompts the user to enter their seed via stdin.
    """
    seed = secure_input(
      'Enter seed and press return (typing will not be shown).\n'
      'If no seed is specified, a random one will be used instead.\n'
    )

    if isinstance(seed, text_type):
      seed = seed.encode('ascii')

    return Seed(seed) if seed else Seed.random()
Ejemplo n.º 22
0
    def test_fail_securityLevel_too_small(self):
        """
    ``securityLevel`` is less than 1.
    """
        self.assertFilterErrors(
            {
                'securityLevel': 0,
                'seed': Seed(self.seed),
            },

            {
                'securityLevel': [f.Min.CODE_TOO_SMALL],
            },
        )
Ejemplo n.º 23
0
    def test_fail_securityLevel_string(self):
        """
    ``securityLevel`` is a string value.
    """
        self.assertFilterErrors(
            {
                'securityLevel': '1',
                'seed': Seed(self.seed),
            },

            {
                'securityLevel': [f.Type.CODE_WRONG_TYPE],
            },
        )
Ejemplo n.º 24
0
    def test_thread_safety(self):
        """
    Address cache is thread-safe, eliminating invalid cache misses when
    multiple threads attempt to access the cache concurrently.
    """
        AddressGenerator.cache = MemoryAddressCache()

        seed = Seed.random()

        generated = []

        def get_address():
            generator = AddressGenerator(seed)
            generated.extend(generator.get_addresses(0))

        # noinspection PyUnusedLocal
        def mock_generate_address(address_generator, key_iterator):
            # type: (AddressGenerator, KeyIterator) -> Address
            # Insert a teensy delay, to make it more likely that multiple
            # threads hit the cache concurrently.
            sleep(0.01)

            # Note that in this test, the address generator always returns a
            # new instance.
            return Address(self.addy, key_index=key_iterator.current)

        with patch(
                'iota.crypto.addresses.AddressGenerator._generate_address',
                mock_generate_address,
        ):
            threads = [Thread(target=get_address) for _ in range(100)]

            for t in threads:
                t.start()

            for t in threads:
                t.join()

        # Quick sanity check.
        self.assertEqual(len(generated), len(threads))

        # If the cache is operating in a thread-safe manner, then it will
        # always return the exact same instance, given the same seed and
        # key index.
        expected = generated[0]
        for actual in generated[1:]:
            # Compare `id` values instead of using ``self.assertIs`` because
            # the failure message is a bit easier to understand.
            self.assertEqual(id(actual), id(expected))
Ejemplo n.º 25
0
 def test_fail_min_weight_magnitude_too_small(self):
     """
 ``minWeightMagnitude`` is < 1.
 """
     self.assertFilterErrors(
         {
             'minWeightMagnitude': 0,
             'depth': 100,
             'seed': Seed(self.trytes1),
             'transfers': [self.transfer1],
         },
         {
             'minWeightMagnitude': [f.Min.CODE_TOO_SMALL],
         },
     )
Ejemplo n.º 26
0
  def test_fail_threshold_too_small(self):
    """
    ``threshold`` is less than 0.
    """
    self.assertFilterErrors(
      {
        'threshold': -1,

        'seed': Seed(self.seed),
      },

      {
        'threshold': [f.Min.CODE_TOO_SMALL],
      },
    )
Ejemplo n.º 27
0
 def test_fail_transfers_empty(self):
     """
 ``transfers`` is an array, but it is empty.
 """
     self.assertFilterErrors(
         {
             'transfers': [],
             'depth': 100,
             'minWeightMagnitude': 18,
             'seed': Seed(self.trytes1),
         },
         {
             'transfers': [f.Required.CODE_EMPTY],
         },
     )
Ejemplo n.º 28
0
 def test_fail_transfers_wrong_type(self):
     """
 ``transfers`` is not an array.
 """
     self.assertFilterErrors(
         {
             'transfers': self.transfer1,
             'depth': 100,
             'minWeightMagnitude': 18,
             'seed': Seed(self.trytes1),
         },
         {
             'transfers': [f.Type.CODE_WRONG_TYPE],
         },
     )
Ejemplo n.º 29
0
 def test_fail_min_weight_magnitude_null(self):
     """
 ``minWeightMagnitude`` is null.
 """
     self.assertFilterErrors(
         {
             'minWeightMagnitude': None,
             'depth': 100,
             'seed': Seed(self.trytes1),
             'transfers': [self.transfer1],
         },
         {
             'minWeightMagnitude': [f.Required.CODE_EMPTY],
         },
     )
Ejemplo n.º 30
0
 def test_fail_stop_float(self):
     """
 ``stop`` is a float.
 """
     self.assertFilterErrors(
         {
             # Even with an empty fpart, floats are not valid.
             # It's gotta be an int.
             'stop': 8.0,
             'seed': Seed(self.seed),
         },
         {
             'stop': [f.Type.CODE_WRONG_TYPE],
         },
     )
Ejemplo n.º 31
0
    def test_fail_unexpected_parameters(self):
        """
    The request contains unexpected parameters.
    """
        self.assertFilterErrors(
            {
                'seed': Seed(self.seed),

                # Your rules are really beginning to annoy me.
                'foo': 'bar',
            },
            {
                'foo': [f.FilterMapper.CODE_EXTRA_KEY],
            },
        )
Ejemplo n.º 32
0
    def test_pass_happy_path(self):
        """
    Request is valid.
    """
        request = {
            'seed': Seed(self.seed),
            'start': 0,
            'stop': 10,
            'inclusionStates': True,
        }

        filter_ = self._filter(request)

        self.assertFilterPasses(filter_)
        self.assertDictEqual(filter_.cleaned_data, request)
Ejemplo n.º 33
0
    def test_fail_unexpected_parameters(self):
        """
    The request contains unexpected parameters.
    """
        self.assertFilterErrors(
            {
                'seed': Seed(self.seed),

                # Told you I did. Reckless is he. Now, matters are worse.
                'foo': 'bar',
            },
            {
                'foo': [f.FilterMapper.CODE_EXTRA_KEY],
            },
        )
Ejemplo n.º 34
0
    def test_happy_path(self):
        """
    Loading account data for an account.
    """

        # noinspection PyUnusedLocal
        def mock_iter_used_addresses(adapter, seed, start):
            """
      Mocks the ``iter_used_addresses`` function, so that we can
      simulate its functionality without actually connecting to the
      Tangle.

      References:
        - :py:func:`iota.commands.extended.utils.iter_used_addresses`
      """
            yield self.addy1, [self.hash1]
            yield self.addy2, [self.hash2]

        mock_get_balances = mock.Mock(return_value={'balances': [42, 0]})

        # Not particularly realistic, but good enough to prove that the
        # mocked function was invoked correctly.
        bundles = [Bundle(), Bundle()]
        mock_get_bundles_from_transaction_hashes = mock.Mock(
            return_value=bundles)

        with mock.patch(
                'iota.commands.extended.get_account_data.iter_used_addresses',
                mock_iter_used_addresses,
        ):
            with mock.patch(
                    'iota.commands.extended.get_account_data.get_bundles_from_transaction_hashes',
                    mock_get_bundles_from_transaction_hashes,
            ):
                with mock.patch(
                        'iota.commands.core.get_balances.GetBalancesCommand._execute',
                        mock_get_balances,
                ):
                    response = self.command(seed=Seed.random())

        self.assertDictEqual(
            response,
            {
                'addresses': [self.addy1, self.addy2],
                'balance': 42,
                'bundles': bundles,
            },
        )
Ejemplo n.º 35
0
    def test_security_level_1_no_stop(self):
        """
    Testing GetInputsCoommand:
      - with security_level = 1 (non default)
      - without `stop` parameter
    """

        # one address with index 0 for selected security levels for the random seed.
        # to check with respective outputs from command
        seed = Seed.random()
        address = AddressGenerator(seed, security_level=1).get_addresses(0)[0]

        # ``getInputs`` uses ``findTransactions`` and
        # ``wereAddressesSpentFrom`` to identify unused addresses.
        # noinspection SpellCheckingInspection
        self.adapter.seed_response(
            'findTransactions', {
                'hashes': [
                    TransactionHash(
                        b'TESTVALUE9DONTUSEINPRODUCTION99999YFXGOD'
                        b'GISBJAX9PDJIRDMDV9DCRDCAEG9FN9KECCBDDFZ9H'),
                ],
            })
        self.adapter.seed_response('findTransactions', {
            'hashes': [],
        })

        self.adapter.seed_response('wereAddressesSpentFrom', {
            'states': [False],
        })

        self.adapter.seed_response('getBalances', {
            'balances': [86],
        })

        response = GetInputsCommand(self.adapter)(
            seed=seed,
            securityLevel=1,
        )

        self.assertEqual(response['totalBalance'], 86)
        self.assertEqual(len(response['inputs']), 1)

        input0 = response['inputs'][0]
        self.assertIsInstance(input0, Address)
        self.assertEqual(input0, address)
        self.assertEqual(input0.balance, 86)
        self.assertEqual(input0.key_index, 0)
Ejemplo n.º 36
0
def create_one_miniwallet():
    sys.stdout = open('wallet.txt', 'wt')
    miniwallet_seed = Seed.random()
    print("This is your new Seed:", file=open("wallet.txt", "a"))
    print(miniwallet_seed, file=open("wallet.txt", "a"))
    api = iota.Iota(NodeURL, seed=miniwallet_seed)
    address_set = api.get_new_addresses(index=0, count=2, security_level=2)
    address_set = address_set['addresses']
    print("This is your new Set of Addresses:", file=open("wallet.txt", "a"))
    address_one = str(address_set[0].with_valid_checksum())
    address_two = str(address_set[1].with_valid_checksum())
    print("Your Brand new Address 1 :", file=open("wallet.txt", "a"))
    print(address_one, file=open("wallet.txt", "a"))
    print("Your Brand new Address 2 :", file=open("wallet.txt", "a"))
    print(address_two, file=open("wallet.txt", "a"))
    return (address_one, address_two, miniwallet_seed)
Ejemplo n.º 37
0
 def test_fail_reference_not_trytes(self):
     """
 ``reference`` contains invalid characters.
 """
     self.assertFilterErrors(
         {
             'reference': b'not valid; must contain only uppercase and "9"',
             'seed': Seed(self.trytes1),
             'depth': 100,
             'minWeightMagnitude': 18,
             'transfers': [self.transfer1],
         },
         {
             'reference': [Trytes.CODE_NOT_TRYTES],
         },
     )
Ejemplo n.º 38
0
  def test_happy_path(self):
    """
    Loading account data for an account.
    """
    # noinspection PyUnusedLocal
    def mock_iter_used_addresses(adapter, seed, start):
      """
      Mocks the ``iter_used_addresses`` function, so that we can
      simulate its functionality without actually connecting to the
      Tangle.

      References:
        - :py:func:`iota.commands.extended.utils.iter_used_addresses`
      """
      yield self.addy1, [self.hash1]
      yield self.addy2, [self.hash2]

    mock_get_balances = mock.Mock(return_value={'balances': [42, 0]})

    # Not particularly realistic, but good enough to prove that the
    # mocked function was invoked correctly.
    bundles = [Bundle(), Bundle()]
    mock_get_bundles_from_transaction_hashes = mock.Mock(return_value=bundles)

    with mock.patch(
        'iota.commands.extended.get_account_data.iter_used_addresses',
        mock_iter_used_addresses,
    ):
      with mock.patch(
        'iota.commands.extended.get_account_data.get_bundles_from_transaction_hashes',
        mock_get_bundles_from_transaction_hashes,
      ):
        with mock.patch(
          'iota.commands.core.get_balances.GetBalancesCommand._execute',
          mock_get_balances,
        ):
          response = self.command(seed=Seed.random())

    self.assertDictEqual(
      response,

      {
        'addresses':  [self.addy1, self.addy2],
        'balance':    42,
        'bundles':    bundles,
      },
    )
Ejemplo n.º 39
0
  def test_no_transactions(self):
    """
    Loading account data for a seed that hasn't been used yet.
    """
    with mock.patch(
        'iota.commands.extended.get_account_data.iter_used_addresses',
        mock.Mock(return_value=[]),
    ):
      response = self.command(seed=Seed.random())

    self.assertDictEqual(
      response,

      {
        'addresses':  [],
        'balance':    0,
        'bundles':    [],
      },
    )
Ejemplo n.º 40
0
  def test_random(self):
    """
    Generating a random seed.
    """

    with warnings.catch_warnings(record=True) as catched_warnings:

      # all warnings should be triggered
      warnings.simplefilter("always")

      seed = Seed.random()

      self.assertEqual(len(catched_warnings), 0)

    # Regression test: ``random`` MUST return a :py:class:`Seed`, NOT a
    # :py:class:`TryteString`!
    self.assertIsInstance(seed, Seed)

    # Regression test: Random seed must be exactly 81 trytes long.
    # https://github.com/iotaledger/iota.lib.py/issues/44
    self.assertEqual(len(seed), Hash.LEN)
Ejemplo n.º 41
0
  def test_random_seed_too_long(self):
    """
    Generating a random seed, which is too long.
    """

    with warnings.catch_warnings(record=True) as catched_warnings:

      # Cause seed related warnings to be triggered
      warnings.simplefilter("always", category=SeedWarning)

      seed = Seed.random(length=Hash.LEN + 1)

      # check attributes of warning
      self.assertEqual(len(catched_warnings), 1)
      self.assertIs(catched_warnings[-1].category, SeedWarning)
      self.assertIn(
        "inappropriate length",
        text_type(catched_warnings[-1].message),
      )

      self.assertEqual(len(seed), Hash.LEN + 1)
Ejemplo n.º 42
0
  def test_stop_no_threshold(self):
    """
    ``stop`` provided, no ``threshold``.
    """
    self.adapter.seed_response('getBalances', {
      'balances': [42, 29],
    })

    # To keep the unit test nice and speedy, we will mock the address
    # generator.  We already have plenty of unit tests for that
    # functionality, so we can get away with mocking it here.
    mock_address_generator = mock.Mock(return_value=[self.addy0, self.addy1])

    with mock.patch(
        'iota.crypto.addresses.AddressGenerator.get_addresses',
        mock_address_generator,
    ):
      response = self.command(
        seed      = Seed.random(),
        start     = 0,
        stop      = 2,
      )

    self.assertEqual(response['totalBalance'], 71)
    self.assertEqual(len(response['inputs']), 2)

    input0 = response['inputs'][0]
    self.assertIsInstance(input0, Address)

    self.assertEqual(input0, self.addy0)
    self.assertEqual(input0.balance, 42)
    self.assertEqual(input0.key_index, 0)

    input1 = response['inputs'][1]
    self.assertIsInstance(input1, Address)

    self.assertEqual(input1, self.addy1)
    self.assertEqual(input1.balance, 29)
    self.assertEqual(input1.key_index, 1)
Ejemplo n.º 43
0
  def test_stop_threshold_not_met(self):
    """
    ``stop`` provided, balance does not meet ``threshold``.
    """
    self.adapter.seed_response('getBalances', {
      'balances': [42, 29],
    })

    # To keep the unit test nice and speedy, we will mock the address
    # generator.  We already have plenty of unit tests for that
    # functionality, so we can get away with mocking it here.
    mock_address_generator = mock.Mock(return_value=[self.addy0, self.addy1])

    with mock.patch(
        'iota.crypto.addresses.AddressGenerator.get_addresses',
        mock_address_generator,
    ):
      with self.assertRaises(BadApiResponse):
        self.command(
          seed      = Seed.random(),
          stop      = 2,
          threshold = 72,
        )
Ejemplo n.º 44
0
  def test_full_scan(self):
    """
    Scanning the Tangle for all transfers.
    """
    # To speed up the test, we will mock the address generator.
    # :py:class:`iota.crypto.addresses.AddressGenerator` already has
    # its own test case, so this does not impact the stability of the
    # codebase.
    # noinspection PyUnusedLocal
    def create_generator(ag, start, step=1):
      for addy in [self.addy1, self.addy2][start::step]:
        yield addy

    # The first address received IOTA.
    self.adapter.seed_response(
      'findTransactions',

      {
        'duration': 42,

        'hashes': [
          'TESTVALUEFIVE9DONTUSEINPRODUCTION99999VH'
          'YHRHJETGYCAFZGABTEUBWCWAS9WF99UHBHRHLIOFJ',
        ],
      },
    )

    # The second address is unused.
    self.adapter.seed_response(
      'findTransactions',

      {
        'duration': 1,
        'hashes':   [],
      },
    )

    self.adapter.seed_response(
      'getTrytes',

      {
        'duration': 99,

        # Thankfully, we do not have to seed a realistic response for
        # ``getTrytes``, as we will be mocking the ``getBundles``
        # command that uses on it.
        'trytes': [''],
      },
    )

    bundle = Bundle([
      Transaction(
        address = self.addy1,
        timestamp = 1483033814,

        # These values are not relevant to the test.
        hash_ = None,
        signature_message_fragment = None,
        value = 42,
        tag = Tag(b''),
        current_index = 0,
        last_index = 0,
        bundle_hash = None,
        trunk_transaction_hash = None,
        branch_transaction_hash = None,
        attachment_timestamp = 1483033814,
        attachment_timestamp_lower_bound = 12,
        attachment_timestamp_upper_bound = 0,
        nonce = None,
      )
    ])

    mock_get_bundles =\
      mock.Mock(return_value={
        'bundles': [bundle],
      })

    with mock.patch(
        'iota.crypto.addresses.AddressGenerator.create_iterator',
        create_generator,
    ):
      with mock.patch(
          'iota.commands.extended.get_bundles.GetBundlesCommand._execute',
          mock_get_bundles,
      ):
        response = self.command(seed=Seed.random())

    self.assertDictEqual(
      response,

      {
        'bundles': [bundle],
      },
    )
Ejemplo n.º 45
0
  def test_stop(self):
    """
    Scanning the Tangle for all transfers, with stop index.
    """
    # noinspection PyUnusedLocal
    def create_generator(ag, start, step=1):
      # Inject an invalid value into the generator, to ensure it is
      # skipped.
      for addy in [self.addy1, None][start::step]:
        yield addy

    # The first address received IOTA.
    self.adapter.seed_response(
      'findTransactions',

      {
        'duration': 42,

        'hashes': [
          'TESTVALUEFIVE9DONTUSEINPRODUCTION99999VH'
          'YHRHJETGYCAFZGABTEUBWCWAS9WF99UHBHRHLIOFJ',
        ],
      },
    )

    self.adapter.seed_response(
      'getTrytes',

      {
        'duration': 99,
        'trytes':   [''],
      },
    )

    bundle = Bundle([
      Transaction(
        address = self.addy1,
        timestamp = 1483033814,

        # These values are not relevant to the test.
        hash_ = None,
        signature_message_fragment = None,
        value = 42,
        tag = Tag(b''),
        current_index = 0,
        last_index = 0,
        bundle_hash = None,
        trunk_transaction_hash = None,
        branch_transaction_hash = None,
        attachment_timestamp = 1483033814,
        attachment_timestamp_lower_bound = 12,
        attachment_timestamp_upper_bound = 0,
        nonce = None,
      )
    ])

    mock_get_bundles = mock.Mock(return_value={
      'bundles': [bundle],
    })

    with mock.patch(
        'iota.crypto.addresses.AddressGenerator.create_iterator',
        create_generator,
    ):
      with mock.patch(
          'iota.commands.extended.get_bundles.GetBundlesCommand._execute',
          mock_get_bundles,
      ):
        response = self.command(seed=Seed.random(), stop=1)

    self.assertDictEqual(
      response,

      {
        'bundles': [bundle],
      },
    )
Ejemplo n.º 46
0
  def test_happy_path(self):
    """
    Sending a transfer successfully.
    """
    # noinspection SpellCheckingInspection
    transaction1 =\
      TransactionTrytes(
          b'GYPRVHBEZOOFXSHQBLCYW9ICTCISLHDBNMMVYD9JJHQMPQCTIQAQTJNNNJ9IDXLRCC'
          b'OYOXYPCLR9PBEY9ORZIEPPDNTI9CQWYZUOTAVBXPSBOFEQAPFLWXSWUIUSJMSJIIIZ'
          b'WIKIRH9GCOEVZFKNXEVCUCIIWZQCQEUVRZOCMEL9AMGXJNMLJCIA9UWGRPPHCEOPTS'
          b'VPKPPPCMQXYBHMSODTWUOABPKWFFFQJHCBVYXLHEWPD9YUDFTGNCYAKQKVEZYRBQRB'
          b'XIAUX9SVEDUKGMTWQIYXRGSWYRK9SRONVGTW9YGHSZRIXWGPCCUCDRMAXBPDFVHSRY'
          b'WHGB9DQSQFQKSNICGPIPTRZINYRXQAFSWSEWIFRMSBMGTNYPRWFSOIIWWT9IDSELM9'
          b'JUOOWFNCCSHUSMGNROBFJX9JQ9XT9PKEGQYQAWAFPRVRRVQPUQBHLSNTEFCDKBWRCD'
          b'X9EYOBB9KPMTLNNQLADBDLZPRVBCKVCYQEOLARJYAGTBFR9QLPKZBOYWZQOVKCVYRG'
          b'YI9ZEFIQRKYXLJBZJDBJDJVQZCGYQMROVHNDBLGNLQODPUXFNTADDVYNZJUVPGB9LV'
          b'PJIYLAPBOEHPMRWUIAJXVQOEM9ROEYUOTNLXVVQEYRQWDTQGDLEYFIYNDPRAIXOZEB'
          b'CS9P99AZTQQLKEILEVXMSHBIDHLXKUOMMNFKPYHONKEYDCHMUNTTNRYVMMEYHPGASP'
          b'ZXASKRUPWQSHDMU9VPS99ZZ9SJJYFUJFFMFORBYDILBXCAVJDPDFHTTTIYOVGLRDYR'
          b'TKHXJORJVYRPTDH9ZCPZ9ZADXZFRSFPIQKWLBRNTWJHXTOAUOL9FVGTUMMPYGYICJD'
          b'XMOESEVDJWLMCVTJLPIEKBE9JTHDQWV9MRMEWFLPWGJFLUXI9BXPSVWCMUWLZSEWHB'
          b'DZKXOLYNOZAPOYLQVZAQMOHGTTQEUAOVKVRRGAHNGPUEKHFVPVCOYSJAWHZU9DRROH'
          b'BETBAFTATVAUGOEGCAYUXACLSSHHVYDHMDGJP9AUCLWLNTFEVGQGHQXSKEMVOVSKQE'
          b'EWHWZUDTYOBGCURRZSJZLFVQQAAYQO9TRLFFN9HTDQXBSPPJYXMNGLLBHOMNVXNOWE'
          b'IDMJVCLLDFHBDONQJCJVLBLCSMDOUQCKKCQJMGTSTHBXPXAMLMSXRIPUBMBAWBFNLH'
          b'LUJTRJLDERLZFUBUSMF999XNHLEEXEENQJNOFFPNPQ9PQICHSATPLZVMVIWLRTKYPI'
          b'XNFGYWOJSQDAXGFHKZPFLPXQEHCYEAGTIWIJEZTAVLNUMAFWGGLXMBNUQTOFCNLJTC'
          b'DMWVVZGVBSEBCPFSM99FLOIDTCLUGPSEDLOKZUAEVBLWNMODGZBWOVQT9DPFOTSKRA'
          b'BQAVOQ9RXWBMAKFYNDCZOJGTCIDMQSQQSODKDXTPFLNOKSIZEOY9HFUTLQRXQMEPGO'
          b'XQGLLPNSXAUCYPGZMNWMQWSWCKAQYKXJTWINSGPPZG9HLDLEAWUWEVCTVRCBDFOXKU'
          b'ROXH9HXXAXVPEJFRSLOGRVGYZASTEBAQNXJJROCYRTDPYFUIQJVDHAKEG9YACV9HCP'
          b'JUEUKOYFNWDXCCJBIFQKYOXGRDHVTHEQUMHO999999999999999999999999999999'
          b'999999999999999999999999999999999999999999999999999999999999999999'
          b'999999999999999999999999999999999999999999999999999999999999999999'
          b'999999999999999999999999999999999999999999999999999999999999999999'
          b'999999999999999999999999999999999999999999999999999999999999999999'
          b'999999999999999999999999999999999999999999999999999999999999999999'
          b'999999999999999999999999999999999999999999999999999999999999999999'
          b'999999999999999999999999999999999999999999999999999999999999999999'
          b'999999999999999999999999999999999999999999999999999999999999999999'
          b'999999999999999999999999999999999999999999999999999999999999999999'
          b'999999999999999999999999999999999999999999999999999999999999999999'
          b'999999999999RKWEEVD99A99999999A99999999NFDPEEZCWVYLKZGSLCQNOFUSENI'
          b'XRHWWTZFBXMPSQHEDFWZULBZFEOMNLRNIDQKDNNIELAOXOVMYEI9PGTKORV9IKTJZQ'
          b'UBQAWTKBKZ9NEZHBFIMCLV9TTNJNQZUIJDFPTTCTKBJRHAITVSKUCUEMD9M9SQJ999'
          b'999TKORV9IKTJZQUBQAWTKBKZ9NEZHBFIMCLV9TTNJNQZUIJDFPTTCTKBJRHAITVSK'
          b'UCUEMD9M9SQJ999999999999999999999999999999999999999999999999999999'
          b'999999999999999999999999999999999'
        )

    mock_prepare_transfer =\
      mock.Mock(return_value={
        'trytes': [transaction1],
      })

    mock_send_trytes =\
      mock.Mock(return_value={
        'trytes': [transaction1],
      })

    with mock.patch(
        'iota.commands.extended.prepare_transfer.PrepareTransferCommand._execute',
        mock_prepare_transfer,
    ):
      with mock.patch(
          'iota.commands.extended.send_trytes.SendTrytesCommand._execute',
          mock_send_trytes,
      ):
        response = self.command(
          depth               = 100,
          minWeightMagnitude  = 18,
          seed                = Seed.random(),

          transfers = [
            ProposedTransaction(
              address =
                Address(
                  b'9999999999999999999999999999999999999999'
                  b'99999999999999999999999999999999999999999'
                ),

              value = 0,
            ),
          ],
        )

    bundle = response['bundle'] # type: Bundle
    self.assertEqual(len(bundle), 1)
    self.assertEqual(bundle[0].as_tryte_string(), transaction1)
Ejemplo n.º 47
0
  def test_get_inclusion_states(self):
    """
    Fetching inclusion states with transactions.
    """
    # noinspection PyUnusedLocal
    def create_generator(ag, start, step=1):
      for addy in [self.addy1][start::step]:
        yield addy

    # The first address received IOTA.
    self.adapter.seed_response(
      'findTransactions',

      {
        'duration': 42,

        'hashes': [
          'TESTVALUEFIVE9DONTUSEINPRODUCTION99999VH'
          'YHRHJETGYCAFZGABTEUBWCWAS9WF99UHBHRHLIOFJ',
        ],
      },
    )

    # For this test, we have to generate a real TryteString.
    transaction_trytes =\
      TryteString(
        b'KMYUMNEUAYODAQSNGWTAERRRHNZBZCOLMVVOBTVWLOFYCJKYMGRAMH9RQ9MTZOSZMH'
        b'QNZFHFEJEDFQ99HSUNVOTULDJGXEDULS9ZHABVDZODJUMCNWVCPNSCUVKVYWCEXBHW'
        b'RBZBSWFPQLWZWMUPGQIGAEGOVE9DDXBVCIPKQYCFZFBELTSMVFSIXLPTACTKAFMCTK'
        b'CPYD9BWDJMLKWAOBDSJNQYAHS9GFIQKZCROLFZJVUEIVXVNBRRLEIWTYVHURUXHSCG'
        b'DKEIEGPOCXKCYWIBUG9ABYCALYJVFLBNGMS9ARHGTQXBZFLENXCJVKHPVKD9KSAEOL'
        b'FFVAJCNKLDVHOCDARWUNKARDYMVKFKRSMUTYOUXSBFFYTKRREBDJZTLVUROQFCBXQN'
        b'SXDDYTZTEBRSXOBMLXHJKSJAVOOVCXATOWNQDWHT9CCUAAJUJKDOQLMAEZACSNFKXZ'
        b'IGWDQEUEFRZYAOSDNVMSXWYLVDAUXZSHNHAIBEMNPFUGORYUETNJK9UCEMSUJYBBDK'
        b'BHIPKEINQCGOVYCPKUPJMUCUVZOJSIWYRFMFXYUVSMOUALAQBWIMXBUBXSAETGKJRP'
        b'AHVAXHQJDMEVSRFYEXUSIEBKMGYCUKFD9JPGUV9AIYUVCRUURKMYUHMVE9OJCYYWTQ'
        b'WUWFMTBZYFXASHHVCMSWXKBRQFHHQVEQMEULJRWZKLWFFSGGKEHUZZFNDNITSRAUH9'
        b'PQK9OGLYMVBSHXQLLZHOBBIM9KVUWDLHZRDKQQVLQXGWYXEEVQPDZUO9PVXMALOMRQ'
        b'VCTHGIZLILSCFKTBRESYZGBZKHXEODNDJZ9GK9ROWYXNGFHZCCBHHZEYEOGWXRGSUD'
        b'SUZFUAUBXVXZHCUVJSYBWTCYCEDYKZNGWFZYKSQLW9FUYMWDVXKZEWT9SCVMQCODZK'
        b'DRNKTINTPNOJOLGQJDAJMFWRFSWZJLYZGSTSIDSXLUJBZRZNLEDNBKAUNGTCYUPDRW'
        b'JOCEBQ9YG9IZLLRMJITISJOTLQMOGXVQIZXHMTJVMMWM9FOIOT9KFZMANEPOEOV9HX'
        b'JNEGURUKRWDGYNPVGAWMWQVABIJNL9MDXKONEPMYACOZ9BE9UZMAFTKYWPFWIQWAPK'
        b'GUXQTOQVWYYVZYGQDLBIQDVOZIWGOMGOBAUARICQZVNXD9UVEFBBAJKQBHRHXTBUOW'
        b'VBFKYQWZWTMMXVKZRIZUBVPQ9XHLJHFHWFZUIZVSNAKBDHDFGJCYQETOMEDTOXIUT9'
        b'OAJVIHWAGTCNPEZTERMMN9EZEWSJHKQAUMXPBZTNQOEQCVXIMAAYO9NIUFLTCFIMK9'
        b'9AFAGWJFA9VOFPUDJLRAMORGSUDBLWWKXEDZ9XPQUZSGANGESHKKGGQSGSYDCRLHZD'
        b'PKA9HKYBKLKKCXYRQQIPXCFETJJDZYPCLUNHGBKEJDRCIHEXKCQQNOV9QFHLGFXOCR'
        b'HPAFCUTPMY9NOZVQHROYJSCMGRSVMOBWADAZNFIAHWGIQUUZBOVODSFAUNRTXSDU9W'
        b'EIRBXQNRSJXFRAQGHA9DYOQJGLVZUJKAQ9CTUOTT9ZKQOQNNLJDUPDXZJYPRCVLRZT'
        b'UCZPNBREYCCKHK9FUWGITAJATFPUOFLZDHPNJYUTXFGNYJOBRD9BVHKZENFXIUYDTL'
        b'CE9JYIIYMXMCXMWTHOLTQFKFHDLVPGMQNITEUXSYLAQULCZOJVBIPYP9M9X9QCNKBX'
        b'W9DVJEQFFY9KQVMKNVTAHQVRXUKEM9FZOJLHAGEECZBUHOQFZOSPRXKZOCCKAOHMSV'
        b'QCFG9CWAHKVWNA9QTLYQI9NKOSHWJCNGPJBLEQPUIWJBIOAWKLBXUCERTSL9FVCLYN'
        b'ADPYTPKJOIEMAQGWBVGSRCZINXEJODUDCT9FHOUMQM9ZHRMBJYSOMPNMEAJGEHICJI'
        b'PVXRKCYX9RZVT9TDZIMXGZJAIYJRGIVMSOICSUINRBQILMJOUQYXCYNJ9WGGJFHYTU'
        b'LWOIPUXXFNTIFNOJRZFSQQNAWBQZOLHHLVGHEPWTKKQEVIPVWZUN9ZBICZ9DZZBVII'
        b'BF9EPHARZJUFJGBQXQFQIBUECAWRSEKYJNYKNSVBCOWTFBZ9NAHFSAMRBPEYGPRGKW'
        b'WTWACZOAPEOECUO9OTMGABJVAIICIPXGSXACVINSYEQFTRCQPCEJXZCY9XZWVWVJRZ'
        b'CYEYNFUUBKPWCHICGJZXKE9GSUDXZYUAPLHAKAHYHDXNPHENTERYMMBQOPSQIDENXK'
        b'LKCEYCPVTZQLEEJVYJZV9BWU999999999999999999999999999FFL999999999999'
        b'9999999999999RJQGVD99999999999A99999999USGBXHGJUEWAUAKNPPRHJXDDMQV'
        b'YDSYZJSDWFYLOQVFGBOSLE9KHFDLDYHUYTXVSFAFCOCLQUHJXTEIQRNBTLHEGJFGVF'
        b'DJCE9IKAOCSYHLCLWPVVNWNESKLYAJG9FGGZOFXCEYOTWLVIJUHGY9QCU9FMZJY999'
        b'9999HYBUYQKKRNAVDPVGYBTVDZ9SVQBLCCVLJTPEQWWOIG9CQZIFQKCROH9YHUCNJT'
        b'SYPBVZVBNESX999999D9TARGPQTNIYRZURQGVHCAWEDRBJIIEJIUZYENVE9LLJQMXH'
        b'GSUUYUCPSOWBCXVFDCHHAZUDC9LUODYWO'
      )

    self.adapter.seed_response(
      'getTrytes',

      {
        'duration': 99,
        'trytes':   [binary_type(transaction_trytes)],
      },
    )

    transaction = Transaction.from_tryte_string(transaction_trytes)

    mock_get_bundles = mock.Mock(return_value={
      'bundles': [Bundle([transaction])],
    })

    mock_get_latest_inclusion = mock.Mock(return_value={
      'states': {
        transaction.hash: True,
      },
    })

    with mock.patch(
        'iota.crypto.addresses.AddressGenerator.create_iterator',
        create_generator,
    ):
      with mock.patch(
          'iota.commands.extended.get_bundles.GetBundlesCommand._execute',
          mock_get_bundles,
      ):
        with mock.patch(
          'iota.commands.extended.get_latest_inclusion.GetLatestInclusionCommand._execute',
          mock_get_latest_inclusion,
        ):
          response = self.command(
            seed = Seed.random(),

            inclusionStates = True,

            # To keep the test focused, only retrieve a single
            # transaction.
            start = 0,
            stop  = 1,
          )

    bundle = response['bundles'][0] # type: Bundle
    self.assertTrue(bundle[0].is_confirmed)
Ejemplo n.º 48
0
  def test_no_stop_no_threshold(self):
    """
    No ``stop`` provided, no ``threshold``.
    """
    self.adapter.seed_response('getBalances', {
      'balances': [42, 29],
    })

    # ``getInputs`` uses ``findTransactions`` to identify unused
    # addresses.
    # noinspection SpellCheckingInspection
    self.adapter.seed_response('findTransactions', {
      'hashes': [
        TransactionHash(
          b'TESTVALUE9DONTUSEINPRODUCTION99999WBL9KD'
          b'EIZDMEDFPEYDIIA9LEMEUCC9MFPBY9TEVCUGSEGGN'
        ),
      ],
    })

    # noinspection SpellCheckingInspection
    self.adapter.seed_response('findTransactions', {
      'hashes': [
        TransactionHash(
          b'TESTVALUE9DONTUSEINPRODUCTION99999YFXGOD'
          b'GISBJAX9PDJIRDMDV9DCRDCAEG9FN9KECCBDDFZ9H'
        ),
      ],
    })

    self.adapter.seed_response('findTransactions', {
      'hashes': [],
    })

    # To keep the unit test nice and speedy, we will mock the address
    # generator.  We already have plenty of unit tests for that
    # functionality, so we can get away with mocking it here.
    # noinspection PyUnusedLocal
    def mock_address_generator(ag, start, step=1):
      for addy in [self.addy0, self.addy1, self.addy2][start::step]:
        yield addy

    # When ``stop`` is None, the command uses a generator internally.
    with mock.patch(
        'iota.crypto.addresses.AddressGenerator.create_iterator',
        mock_address_generator,
    ):
      response = self.command(
        seed = Seed.random(),
      )

    self.assertEqual(response['totalBalance'], 71)
    self.assertEqual(len(response['inputs']), 2)

    input0 = response['inputs'][0]
    self.assertIsInstance(input0, Address)

    self.assertEqual(input0, self.addy0)
    self.assertEqual(input0.balance, 42)
    self.assertEqual(input0.key_index, 0)

    input1 = response['inputs'][1]
    self.assertIsInstance(input1, Address)

    self.assertEqual(input1, self.addy1)
    self.assertEqual(input1.balance, 29)
    self.assertEqual(input1.key_index, 1)