Example #1
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()
Example #2
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()
        self.helpers = Helpers(self)
    def setUp(self):
        super(AddressGeneratorTestCase, self).setUp()

        self.seed_1 =\
          Seed(
            b'TESTVALUE9DONTUSEINPRODUCTION999999GFDDC'
            b'PFIIEHBCWFN9KHRBEIHHREFCKBVGUGEDXCFHDFPAL',
          )

        self.seed_2 =\
          Seed(
            b'TESTVALUE9DONTUSEINPRODUCTION99999DCZGVE'
            b'JIZEKEGEEHYE9DOHCHLHMGAFDGEEQFUDVGGDGHRDR',
          )
Example #4
0
  def test_pass_compatible_types(self):
    """
    Request contains values that can be converted to the expected
    types.
    """
    filter_ = self._filter({
      # ``seed`` can be any TrytesCompatible value.
      'seed': bytearray(self.seed.encode('ascii')),

      # These values must be integers, however.
      'index':          100,
      'count':          8,
      'securityLevel':  2,

      # ``checksum`` must be boolean.
      'checksum':       False,
    })

    self.assertFilterPasses(filter_)
    self.assertDictEqual(
      filter_.cleaned_data,

      {
        'seed':           Seed(self.seed),
        'index':          100,
        'count':          8,
        'securityLevel':  2,
        'checksum':       False,
      },
    )
Example #5
0
  def setUp(self):
    super(GetNewAddressesCommandTestCase, self).setUp()

    self.adapter = MockAdapter()
    self.command = GetNewAddressesCommand(self.adapter)

    self.seed =\
      Seed(
        b'TESTVALUE9DONTUSEINPRODUCTION99999ZDCCUF'
        b'CBBIQCLGMEXAVFQEOF9DRAB9VCEBAGXAF9VF9FLHP',
      )

    self.addy_1 =\
      Address(
        b'NYMWLBUJEISSACZZBRENC9HEHYQXHCGQHSNHVCEA'
        b'ZDCTEVNGSDUEKTSYBSQGMVJRIEDHWDYSEYCFAZAH9',
      )

    self.addy_2 =\
      Address(
        b'NTPSEVZHQITARYWHIRTSIFSERINLRYVXLGIQKKHY'
        b'IWYTLQUUHDWSOVXLIKVJTYZBFKLABWRBFYVSMD9NB',
      )

    self.addy_1_checksum =\
      Address(
        b'NYMWLBUJEISSACZZBRENC9HEHYQXHCGQHSNHVCEA'
        b'ZDCTEVNGSDUEKTSYBSQGMVJRIEDHWDYSEYCFAZAH'
        b'9T9FPJROTW',
      )
    def test_pass_compatible_types(self):
        """
    The request contains values that can be converted to the expected
    types.
    """
        filter_ = self._filter({
            # ``seed`` can be any value that is convertible into a
            # TryteString.
            'seed': binary_type(self.seed),

            # These values must still be integers/bools, however.
            'start': 42,
            'stop': 86,
            'inclusionStates': True,
            'security_level': 2
        })

        self.assertFilterPasses(filter_)
        self.assertDictEqual(
            filter_.cleaned_data,
            {
                'seed': Seed(self.seed),
                'start': 42,
                'stop': 86,
                'inclusionStates': True,
                'security_level': 2
            },
        )
Example #7
0
    def test_pass_optional_parameters_excluded(self):
        """
    The request contains only required parameters.
    """
        filter_ = self._filter({
            'seed': Seed(self.seed),
        })

        self.assertFilterPasses(filter_)
        self.assertDictEqual(
            filter_.cleaned_data, {
                'seed': Seed(self.seed),
                'start': 0,
                'stop': None,
                'inclusionStates': False,
            })
    def test_pass_compatible_types(self):
        """
    The request contains values that can be converted to the expected
    types.
    """
        filter_ = self._filter({
            # ``seed`` can be any value that is convertible into an ASCII
            # representation of a TryteString.
            'seed': bytearray(self.seed.encode('ascii')),

            # These values must still be integers, however.
            'start': 42,
            'stop': 86,
            'threshold': 99,
            "securityLevel": 3,
        })

        self.assertFilterPasses(filter_)
        self.assertDictEqual(
            filter_.cleaned_data,
            {
                'seed': Seed(self.seed),
                'start': 42,
                'stop': 86,
                'threshold': 99,
                "securityLevel": 3,
            },
        )
Example #9
0
    def test_fail_inputs_contents_invalid(self):
        """
    ``inputs`` is a non-empty array, but it contains invalid values.
    """
        self.assertFilterErrors(
            {
                'inputs': [
                    b'',
                    True,
                    None,
                    b'not valid trytes',

                    # This is actually valid; I just added it to make sure the
                    #   filter isn't cheating!
                    TryteString(self.trytes4),
                    2130706433,
                    b'9' * 82,
                ],
                'depth':
                100,
                'minWeightMagnitude':
                18,
                'seed':
                Seed(self.trytes1),
                'transfers': [self.transfer1],
            },
            {
                'inputs.0': [f.Required.CODE_EMPTY],
                'inputs.1': [f.Type.CODE_WRONG_TYPE],
                'inputs.2': [f.Required.CODE_EMPTY],
                'inputs.3': [Trytes.CODE_NOT_TRYTES],
                'inputs.5': [f.Type.CODE_WRONG_TYPE],
                'inputs.6': [Trytes.CODE_WRONG_FORMAT],
            },
        )
    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_async.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)
    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_async.crypto.addresses.AddressGenerator.create_iterator',
                mock_address_generator,
        ):
            with self.assertRaises(BadApiResponse):
                self.command(
                    seed=Seed.random(),
                    threshold=72,
                )
Example #12
0
  def test_pass_compatible_types(self):
    """
    Request contains values that can be converted to the expected
    types.
    """
    filter_ = self._filter({
      # ``seed`` can be any value that is convertible to TryteString.
      'seed': binary_type(self.seed),

      # These values must be integers, however.
      'index':          100,
      'count':          8,
      'securityLevel':  1,
    })

    self.assertFilterPasses(filter_)
    self.assertDictEqual(
      filter_.cleaned_data,

      {
        'seed':           Seed(self.seed),
        'index':          100,
        'count':          8,
        'securityLevel':  1,
      },
    )
Example #13
0
    def test_pass_compatible_types(self):
        """
    The request contains values that can be converted to the expected
    types.
    """
        filter_ = self._filter({
            # ``seed`` can be any TrytesCompatible value.
            'seed': bytearray(self.seed.encode('ascii')),

            # These values must still be integers/bools, however.
            'start': 42,
            'stop': 86,
            'inclusionStates': True,
        })

        self.assertFilterPasses(filter_)
        self.assertDictEqual(
            filter_.cleaned_data,
            {
                'seed': Seed(self.seed),
                'start': 42,
                'stop': 86,
                'inclusionStates': True,
            },
        )
Example #14
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_async.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,
    })
Example #15
0
    def test_fail_transfers_contents_invalid(self):
        """
    ``transfers`` is a non-empty array, but it contains invalid values.
    """
        self.assertFilterErrors(
            {
                'transfers': [
                    None,

                    # This value is valid; just adding it to make sure the filter
                    # doesn't cheat!
                    ProposedTransaction(address=Address(self.trytes2),
                                        value=42),
                    {
                        'address': Address(self.trytes2),
                        'value': 42
                    },
                ],
                'depth':
                100,
                'minWeightMagnitude':
                18,
                'seed':
                Seed(self.trytes1),
            },
            {
                'transfers.0': [f.Required.CODE_EMPTY],
                'transfers.2': [f.Type.CODE_WRONG_TYPE],
            },
        )
Example #16
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_async.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_async.crypto.addresses.AddressGenerator.create_iterator',
                create_generator,
        ):
            response = self.command(seed=Seed.random())

        self.assertDictEqual(response, {'bundles': []})
    def test_pass_optional_parameters_excluded(self):
        """
    The request contains only required parameters.
    """
        filter_ = self._filter({
            'seed': Seed(self.seed),
        })

        self.assertFilterPasses(filter_)
        self.assertDictEqual(
            filter_.cleaned_data, {
                'seed': Seed(self.seed),
                'start': 0,
                'stop': None,
                'threshold': None,
                "securityLevel": AddressGenerator.DEFAULT_SECURITY_LEVEL,
            })
Example #18
0
    def seed_from_filepath(filepath):
        # type: (Text) -> Seed
        """
        Reads a seed from the first line of a text file.

        Any lines after the first are ignored.
        """
        with open(filepath, 'rb') as f_:
            return Seed(f_.readline().strip())
Example #19
0
  def test_pass_optional_parameters_excluded(self):
    """
    Request omits optional parameters.
    """
    filter_ = self._filter({
      'seed': Seed(self.seed),
    })

    self.assertFilterPasses(filter_)
    self.assertDictEqual(
      filter_.cleaned_data,

      {
        'seed':           Seed(self.seed),
        'index':          0,
        'count':          1,
        'securityLevel':  AddressGenerator.DEFAULT_SECURITY_LEVEL,
      },
    )
    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_async.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)
Example #21
0
    def __init__(
            self,
            seed,
            security_level=DEFAULT_SECURITY_LEVEL,
            checksum=False,
    ):
        # type: (TrytesCompatible, int, bool) -> None
        super(AddressGenerator, self).__init__()

        self.security_level = security_level
        self.checksum = checksum
        self.seed = Seed(seed)
 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],
         },
     )
 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],
         },
     )
 def test_fail_security_level_too_small(self):
     """
 ``securityLevel`` is < 1.
 """
     self.assertFilterErrors(
         {
             'securityLevel': 0,
             'seed': Seed(self.seed),
         },
         {
             'securityLevel': [f.Min.CODE_TOO_SMALL],
         },
     )
 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],
         },
     )
 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],
         },
     )
 def test_fail_stop_too_small(self):
     """
 ``stop`` is less than 0.
 """
     self.assertFilterErrors(
         {
             'stop': -1,
             'seed': Seed(self.seed),
         },
         {
             'stop': [f.Min.CODE_TOO_SMALL],
         },
     )
Example #28
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],
            })
Example #29
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],
      },
    )
Example #30
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],
      },
    )