예제 #1
0
 def __init__(self, name, initBal=100):
     self.name = name
     self.bal = initBal
     self.seed = iota.crypto.types.Seed.random(
     )  # Generates official random 81 tryte seed
     generator = AddressGenerator(
         self.seed, security_level=1)  # Generates IOTA address from seed
     self.address = generator.get_addresses(start=0)
     self.address = self.address[0].address
     keyGen = KeyGenerator(self.seed)
     self.privKey = keyGen.get_key(
         index=0, iterations=1)  # Generate IOTA key from seed
예제 #2
0
    def _execute(self, request):
        count = request['count']  # type: Optional[int]
        index = request['index']  # type: int
        seed = request['seed']  # type: Seed
        security_level = request['securityLevel']  # type: int

        generator = KeyGenerator(seed)

        return {
            'keys':
                generator.get_keys(start=index, count=count, iterations=security_level),
        }
예제 #3
0
    async def _execute(self, request: dict) -> dict:
        count: Optional[int] = request['count']
        index: int = request['index']
        seed: Seed = request['seed']
        security_level: int = request['securityLevel']

        generator = KeyGenerator(seed)

        return {
            'keys': generator.get_keys(
                start=index,
                count=count,
                iterations=security_level,
            ),
        }
예제 #4
0
    def create_iterator(self, start=0, step=1):
        # type: (int, int) -> Generator[Address]
        """
    Creates an iterator that can be used to progressively generate new
    addresses.

    :param start:
      Starting index.

      Warning: This method may take awhile to reset if ``start``
      is a large number!

    :param step:
      Number of indexes to advance after each address.

      Warning: The generator may take awhile to advance between
      iterations if ``step`` is a large number!
    """
        key_iterator = (KeyGenerator(self.seed).create_iterator(
            start, step, iterations=self.DIGEST_ITERATIONS))

        while True:
            if self.cache:
                with self.cache.acquire_lock():
                    address = self.cache.get(self.seed, key_iterator.current)

                    if not address:
                        address = self._generate_address(key_iterator)
                        self.cache.set(self.seed, address.key_index, address)
            else:
                address = self._generate_address(key_iterator)

            yield address
예제 #5
0
  def test_sign_input_at_error_index_not_input(self):
    """
    The specified index references a transaction that is not an input.
    """
    # Add a transaction so that we can finalize the bundle.
    # noinspection SpellCheckingInspection
    self.bundle.add_transaction(ProposedTransaction(
      address =
        Address(
          b'TESTVALUE9DONTUSEINPRODUCTION99999QARFLF'
          b'TDVATBVFTFCGEHLFJBMHPBOBOHFBSGAGWCM9PG9GX'
        ),

      value = 42,
    ))

    self.bundle.add_inputs([self.input_0_bal_eq_42])
    self.bundle.finalize()

    private_key =\
      KeyGenerator(self.seed).get_key_for(self.input_0_bal_eq_42)

    with self.assertRaises(ValueError):
      # You can't sign the spend transaction, silly!
      self.bundle.sign_input_at(0, private_key)
예제 #6
0
    def create_iterator(self, start=0, step=1):
        # type: (int, int) -> Generator[Address, None, None]
        """
        Creates an iterator that can be used to progressively generate new
        addresses.

        :param start:
            Starting index.

            Warning: This method may take awhile to reset if ``start``
            is a large number!

        :param step:
            Number of indexes to advance after each address.

            Warning: The generator may take awhile to advance between
            iterations if ``step`` is a large number!
        """
        key_iterator = (KeyGenerator(self.seed).create_iterator(
            start,
            step,
            self.security_level,
        ))

        while True:
            yield self._generate_address(key_iterator)
예제 #7
0
  def test_sign_input_at_error_not_finalized(self):
    """
    Cannot sign inputs because the bundle isn't finalized yet.
    """
    # Add a transaction so that we can finalize the bundle.
    self.bundle.add_transaction(ProposedTransaction(
      address =
        Address(
          b'TESTVALUE9DONTUSEINPRODUCTION99999QARFLF'
          b'TDVATBVFTFCGEHLFJBMHPBOBOHFBSGAGWCM9PG9GX'
        ),

      value = 42,
    ))

    self.bundle.add_inputs([self.input_0_bal_eq_42])

    # Oops; did we forget something?
    # self.bundle.finalize()

    private_key =\
      KeyGenerator(self.seed).get_key_for(self.input_0_bal_eq_42)

    with self.assertRaises(RuntimeError):
      self.bundle.sign_input_at(1, private_key)
예제 #8
0
    def test_sign_input_at_error_already_signed(self):
        """
    Attempting to sign an input that is already signed.
    """
        # Add a transaction so that we can finalize the bundle.
        # noinspection SpellCheckingInspection
        self.bundle.add_transaction(
            ProposedTransaction(
                address=Address(b'TESTVALUE9DONTUSEINPRODUCTION99999QARFLF'
                                b'TDVATBVFTFCGEHLFJBMHPBOBOHFBSGAGWCM9PG9GX'),
                value=42,
            ))

        self.bundle.add_inputs([self.input_0_bal_eq_42])
        self.bundle.finalize()

        # The existing signature fragment doesn't have to be valid; it just
        # has to be not empty.
        self.bundle[1].signature_message_fragment = Fragment(b'A')

        private_key =\
          KeyGenerator(self.seed).get_key_for(self.input_0_bal_eq_42)

        with self.assertRaises(ValueError):
            self.bundle.sign_input_at(1, private_key)
예제 #9
0
  def test_sign_inputs_security_level(self):
    """
    You may include inputs with different security levels in the same
    bundle.
    """
    # noinspection SpellCheckingInspection
    self.bundle.add_transaction(
      ProposedTransaction(
        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999XE9IVG'
            b'EFNDOCQCMERGUATCIEGGOHPHGFIAQEZGNHQ9W99CH',
          ),

        value = 84,
      ),
    )

    self.bundle.add_inputs([
      self.input_4_bal_eq_42_sl_2,
      self.input_5_bal_eq_42_sl_3,
    ])

    self.bundle.finalize()

    self.bundle.sign_inputs(KeyGenerator(self.seed))

    # Quick sanity check.
    self.assertEqual(len(self.bundle), 6)

    # The spending transaction does not have a signature.
    self.assertEqual(
      self.bundle[0].signature_message_fragment,
      Fragment(b''),
    )

    # The signature fragments are really long, and we already have unit
    # tests for the signature fragment generator, so to keep this test
    # focused, we are only interested in whether a signature fragment
    # gets applied.
    #
    # References:
    #   - :py:class:`test.crypto.signing_test.SignatureFragmentGeneratorTestCase`
    for i in range(1, len(self.bundle)):
      if self.bundle[i].signature_message_fragment == Fragment(b''):
        self.fail(
          "Transaction {i}'s signature fragment is unexpectedly empty!".format(
            i = i,
          ),
        )
예제 #10
0
  def test_sign_inputs(self):
    """
    Signing inputs in a finalized bundle, using a key generator.
    """
    # noinspection SpellCheckingInspection
    self.bundle.add_transaction(ProposedTransaction(
      address =
        Address(
          b'TESTVALUE9DONTUSEINPRODUCTION99999QARFLF'
          b'TDVATBVFTFCGEHLFJBMHPBOBOHFBSGAGWCM9PG9GX'
        ),

      value = 42,
    ))

    self.bundle.add_inputs([self.input_1_bal_eq_40, self.input_2_bal_eq_2])
    self.bundle.finalize()

    self.bundle.sign_inputs(KeyGenerator(self.seed))

    # Quick sanity check:
    # 1 spend + 2 inputs (security level 1) = 3 transactions.
    # Applying signatures should not introduce any new transactions
    # into the bundle.
    #
    # Note: we will see what happens when we use inputs with different
    # security levels in the next test.
    self.assertEqual(len(self.bundle), 3)

    # The spending transaction does not have a signature.
    self.assertEqual(
      self.bundle[0].signature_message_fragment,
      Fragment(b''),
    )

    # The signature fragments are really long, and we already have unit
    # tests for the signature fragment generator, so to keep this test
    # focused, we are only interested in whether a signature fragment
    # gets applied.
    #
    # References:
    #   - :py:class:`test.crypto.signing_test.SignatureFragmentGeneratorTestCase`
    for i in range(1, len(self.bundle)):
      if self.bundle[i].signature_message_fragment == Fragment(b''):
        self.fail(
          "Transaction {i}'s signature fragment is unexpectedly empty!".format(
            i = i,
          ),
        )
예제 #11
0
  def test_sign_input_at_single_fragment(self):
    """
    Signing an input at the specified index, only 1 fragment needed.
    """
    # Add a transaction so that we can finalize the bundle.
    # noinspection SpellCheckingInspection
    self.bundle.add_transaction(ProposedTransaction(
      address =
        Address(
          b'TESTVALUE9DONTUSEINPRODUCTION99999QARFLF'
          b'TDVATBVFTFCGEHLFJBMHPBOBOHFBSGAGWCM9PG9GX'
        ),

      value = 42,
    ))

    self.bundle.add_inputs([self.input_0_bal_eq_42])
    self.bundle.finalize()

    private_key =\
      KeyGenerator(self.seed).get_key_for(self.input_0_bal_eq_42)

    self.bundle.sign_input_at(1, private_key)

    # Only 2 transactions are needed for this bundle:
    # 1 spend + 1 input (security level = 1).
    self.assertEqual(len(self.bundle), 2)

    # The spending transaction does not have a signature.
    self.assertEqual(
      self.bundle[0].signature_message_fragment,
      Fragment(b''),
    )

    # The signature fragments are really long, and we already have unit
    # tests for the signature fragment generator, so to keep this test
    # focused, we are only interested in whether a signature fragment
    # gets applied.
    #
    # References:
    #   - :py:class:`test.crypto.signing_test.SignatureFragmentGeneratorTestCase`
    for i in range(1, len(self.bundle)):
      if self.bundle[i].signature_message_fragment == Fragment(b''):
        self.fail(
          "Transaction {i}'s signature fragment is unexpectedly empty!".format(
            i = i,
          ),
        )
예제 #12
0
  def _create_digest_generator(self, start, step):
    # type: (int, int) -> Generator[List[int]]
    """
    Initializes a generator to create PrivateKey digests.

    Implemented as a separate method so that it can be mocked during
    unit tests.
    """
    key_generator = (
      KeyGenerator(self.seed)
        .create_generator(start, step, iterations=self.DIGEST_ITERATIONS)
    )

    while True:
      signing_key = next(key_generator) # type: PrivateKey
      yield signing_key.get_digest_trits()
예제 #13
0
    def test_sign_input_at_error_index_invalid(self):
        """
    The specified index doesn't exist in the bundle.
    """
        # Add a transaction so that we can finalize the bundle.
        # noinspection SpellCheckingInspection
        self.bundle.add_transaction(
            ProposedTransaction(
                address=Address(b'TESTVALUE9DONTUSEINPRODUCTION99999QARFLF'
                                b'TDVATBVFTFCGEHLFJBMHPBOBOHFBSGAGWCM9PG9GX'),
                value=42,
            ))

        self.bundle.add_inputs([self.input_0_bal_eq_42])
        self.bundle.finalize()

        private_key =\
          KeyGenerator(self.seed).get_key_for(self.input_0_bal_eq_42)

        with self.assertRaises(IndexError):
            self.bundle.sign_input_at(2, private_key)
예제 #14
0
    def test_sign_inputs_error_not_finalized(self):
        """
    Attempting to sign inputs in a bundle that hasn't been finalized
    yet.
    """
        # Add a transaction so that we can finalize the bundle.
        # noinspection SpellCheckingInspection
        self.bundle.add_transaction(
            ProposedTransaction(
                address=Address(b'TESTVALUE9DONTUSEINPRODUCTION99999QARFLF'
                                b'TDVATBVFTFCGEHLFJBMHPBOBOHFBSGAGWCM9PG9GX'),
                value=42,
            ))

        self.bundle.add_inputs([self.input_0_bal_eq_42])

        # Oops; did we forget something?
        # self.bundle.finalize()

        with self.assertRaises(RuntimeError):
            self.bundle.sign_inputs(KeyGenerator(b''))
예제 #15
0
    def create_iterator(self,
                        start: int = 0,
                        step: int = 1) -> Generator[Address, None, None]:
        """
        Creates an iterator that can be used to progressively generate new
        addresses.

        Returns an iterator that will create addresses endlessly.
        Use this if you have a feature that needs to generate addresses
        “on demand”.

        :param int start:
            Starting index.

            .. warning::
                This method may take awhile to reset if ``start`` is a large
                number!

        :param int step:
            Number of indexes to advance after each address.

            .. warning::
                The generator may take awhile to advance between
                iterations if ``step`` is a large number!

        :return:
            ``Generator[Address, None, None]`` object that you can iterate to
            generate addresses.
        """
        key_iterator = (KeyGenerator(self.seed).create_iterator(
            start,
            step,
            self.security_level,
        ))

        while True:
            yield self._generate_address(key_iterator)
예제 #16
0
    def _execute(self, request):
        # Required parameters.
        seed = request['seed']  # type: Seed
        bundle = ProposedBundle(request['transfers'])

        # Optional parameters.
        change_address = request.get(
            'changeAddress')  # type: Optional[Address]
        proposed_inputs = request.get(
            'inputs')  # type: Optional[List[Address]]

        want_to_spend = bundle.balance
        if want_to_spend > 0:
            # We are spending inputs, so we need to gather and sign them.
            if proposed_inputs is None:
                # No inputs provided.  Scan addresses for unspent inputs.
                gi_response = GetInputsCommand(self.adapter)(
                    seed=seed,
                    threshold=want_to_spend,
                )

                confirmed_inputs = gi_response['inputs']
            else:
                # Inputs provided.  Check to make sure we have sufficient
                # balance.
                available_to_spend = 0
                confirmed_inputs = []  # type: List[Address]

                gb_response = GetBalancesCommand(self.adapter)(
                    addresses=[i.address for i in proposed_inputs], )

                for i, balance in enumerate(gb_response.get('balances') or []):
                    input_ = proposed_inputs[i]

                    if balance > 0:
                        available_to_spend += balance

                        # Update the address balance from the API response, just in
                        # case somebody tried to cheat.
                        input_.balance = balance
                        confirmed_inputs.append(input_)

                if available_to_spend < want_to_spend:
                    raise with_context(
                        exc=BadApiResponse(
                            'Insufficient balance; found {found}, need {need} '
                            '(``exc.context`` has more info).'.format(
                                found=available_to_spend,
                                need=want_to_spend,
                            ), ),
                        context={
                            'available_to_spend': available_to_spend,
                            'confirmed_inputs': confirmed_inputs,
                            'request': request,
                            'want_to_spend': want_to_spend,
                        },
                    )

            bundle.add_inputs(confirmed_inputs)

            if bundle.balance < 0:
                if not change_address:
                    change_address =\
                      GetNewAddressesCommand(self.adapter)(seed=seed)['addresses'][0]

                bundle.send_unspent_inputs_to(change_address)

            bundle.finalize()

            if confirmed_inputs:
                bundle.sign_inputs(KeyGenerator(seed))
        else:
            bundle.finalize()

        return {
            'trytes': bundle.as_tryte_strings(),
        }
bundle.add_transaction(pt)

addy = gna_result["addresses"][0]
addy.balance = 0
addy.key_index = 0
bundle.add_inputs([
    addy
])

bundle.send_unspent_inputs_to(
    gna_result["addresses"][0]
)

bundle.finalize()
bundle.sign_inputs(KeyGenerator(b'BXOM9LUNLPSEXBRJV9UUNLHSUHABEOGHQOGNBNBUEYSGOFZOEPYKEYRSFTXBOEJLUODUQXXGQ9NWQBSGH'))

tips = json.loads(call_iota_api(getTips))
print("llsdldld")
for x in tips['hashes']:
    getTransactionsToApprove = {"command": "getTransactionsToApprove", "depth": 15, "reference": x}
    result = json.loads(call_iota_api(getTransactionsToApprove))
    if "exception" in result:
        print(result)
        continue
    elif "error" in result:
        print(result)
        continue
    else:
        print(result)
        trunk_hash = result['trunkTransaction']
예제 #18
0
    def sign_inputs(self, key_generator: KeyGenerator) -> None:
        """
        Sign inputs in a finalized bundle.

        Generates the necessary cryptographic signatures to authorize spending
        the inputs.

        .. note::
            You do not need to invoke this method if the bundle does
            not contain any transactions that spend iotas.

        :param KeyGenerator key_generator:
            Generator to create private keys for signing.

        :raises RuntimeError: if bundle is not yet finalized.
        :raises ValueError:
            - if the input transaction specifies an address that doesn't have
              ``key_index`` attribute defined.
            - if the input transaction specifies an address that doesn't have
              ``security_level`` attribute defined.
        """
        if not self.hash:
            raise RuntimeError('Cannot sign inputs until bundle is finalized.')

        # Use a counter for the loop so that we can skip ahead as we go.
        i = 0
        while i < len(self):
            txn = self[i]

            if txn.value < 0:
                # In order to sign the input, we need to know the index
                # of the private key used to generate it.
                if txn.address.key_index is None:
                    raise with_context(
                        exc=ValueError(
                            'Unable to sign input {input}; '
                            '``key_index`` is None '
                            '(``exc.context`` has more info).'.format(
                                input=txn.address,
                            ),
                        ),

                        context={
                            'transaction': txn,
                        },
                    )

                if txn.address.security_level is None:
                    raise with_context(
                        exc=ValueError(
                            'Unable to sign input {input}; '
                            '``security_level`` is None '
                            '(``exc.context`` has more info).'.format(
                                input=txn.address,
                            ),
                        ),

                        context={
                            'transaction': txn,
                        },
                    )

                self.sign_input_at(i, key_generator.get_key_for(txn.address))

                i += txn.address.security_level
            else:
                # No signature needed (nor even possible, in some
                # cases); skip this transaction.
                i += 1