示例#1
0
  def test_happy_path(self):
    """
    Typical use case.
    """
    # noinspection SpellCheckingInspection
    input_ = (
      'EMIDYNHBWMBCXVDEFOFWINXTERALUKYYPPHKP9JJ'
      'FGJEIUY9MUDVNFZHMMWZUYUSWAIOWEVTHNWMHANBH'
    )

    trits = TryteString(input_).as_trits()
    

    curl = Curl()
    curl.absorb(trits)
    trits_out = []
    curl.squeeze(trits_out)

    trits_out = TryteString.from_trits(trits_out)
    # print('trits_out: ', trits_out)
    # # AQBOPUMJMGVHFOXSMUAGZNACKUTISDPBSILMRAGIGRXXS9JJTLIKZUW9BCJWKSTFBDSBLNVEEGVGAMSSM

    # noinspection SpellCheckingInspection
    self.assertEqual(
      trits_out,

      'AQBOPUMJMGVHFOXSMUAGZNACKUTISDPBSILMRAGI'
      'GRXXS9JJTLIKZUW9BCJWKSTFBDSBLNVEEGVGAMSSM',
    )
示例#2
0
  def test_length_greater_than_243(self):
    """
    The input is longer than 1 hash.
    """
    # noinspection SpellCheckingInspection
    input_ = (
      'G9JYBOMPUXHYHKSNRNMMSSZCSHOFYOYNZRSZMAAYWDYEIMVVOGKPJB'
      'VBM9TDPULSFUNMTVXRKFIDOHUXXVYDLFSZYZTWQYTE9SPYYWYTXJYQ'
      '9IFGYOLZXWZBKWZN9QOOTBQMWMUBLEWUEEASRHRTNIQWJQNDWRYLCA'
    )

    trits = TryteString(input_).as_trits()

    curl = Curl()
    curl.absorb(trits)
    trits_out = []
    curl.squeeze(trits_out)

    trits_out = TryteString.from_trits(trits_out)

    # noinspection SpellCheckingInspection
    self.assertEqual(
      trits_out,

      'RWCBOLRFANOAYQWXXTFQJYQFAUTEEBSZWTIRSSDR'
      'EYGCNFRLHQVDZXYXSJKCQFQLJMMRHYAZKRRLQZDKR',
    )
示例#3
0
    def from_tryte_string(cls, trytes):
        # type: (TrytesCompatible) -> Transaction
        """
    Creates a Transaction object from a sequence of trytes.
    """
        tryte_string = TransactionTrytes(trytes)

        hash_ = [0] * HASH_LENGTH  # type: MutableSequence[int]

        sponge = Curl()
        sponge.absorb(tryte_string.as_trits())
        sponge.squeeze(hash_)

        return cls(
            hash_=TransactionHash.from_trits(hash_),
            signature_message_fragment=Fragment(tryte_string[0:2187]),
            address=Address(tryte_string[2187:2268]),
            value=int_from_trits(tryte_string[2268:2295].as_trits()),
            tag=Tag(tryte_string[2295:2322]),
            timestamp=int_from_trits(tryte_string[2322:2331].as_trits()),
            current_index=int_from_trits(tryte_string[2331:2340].as_trits()),
            last_index=int_from_trits(tryte_string[2340:2349].as_trits()),
            bundle_hash=BundleHash(tryte_string[2349:2430]),
            trunk_transaction_hash=TransactionHash(tryte_string[2430:2511]),
            branch_transaction_hash=TransactionHash(tryte_string[2511:2592]),
            nonce=Hash(tryte_string[2592:2673]),
        )
示例#4
0
    def test_squeeze_multiple_hashes(self):
        """
    Squeezing more than 1 hash from the sponge.
    """
        # noinspection SpellCheckingInspection
        input_ = ('EMIDYNHBWMBCXVDEFOFWINXTERALUKYYPPHKP9JJ'
                  'FGJEIUY9MUDVNFZHMMWZUYUSWAIOWEVTHNWMHANBH')

        trits = TryteString(input_).as_trits()

        curl = Curl()
        curl.absorb(trits)
        trits_out = []
        curl.squeeze(trits_out, length=486)

        trits_out = TryteString.from_trits(trits_out)

        # noinspection SpellCheckingInspection
        self.assertEqual(
            trits_out,
            'AQBOPUMJMGVHFOXSMUAGZNACKUTISDPBSILMRAGIG'
            'RXXS9JJTLIKZUW9BCJWKSTFBDSBLNVEEGVGAMSSMQ'
            'GSJWCCFQRHWKTSMVPWWCEGOMCNWFYWDZBEDBLXIFB'
            'HOTCKUMCANLSXXTNKSYNBMOSDDEYFTDOYIKDRJM',
        )
示例#5
0
    def test_length(self):
        """
    Specifying different values for the ``length`` argument.
    """
        # noinspection SpellCheckingInspection
        input_ = ('G9JYBOMPUXHYHKSNRNMMSSZCSHOFYOYNZRSZMAAYWDYEIMVVOGKPJB'
                  'VBM9TDPULSFUNMTVXRKFIDOHUXXVYDLFSZYZTWQYTE9SPYYWYTXJYQ'
                  '9IFGYOLZXWZBKWZN9QOOTBQMWMUBLEWUEEASRHRTNIQWJQNDWRYLCA')

        trits = TryteString(input_).as_trits()

        curl = Curl()
        curl.absorb(trits, offset=0, length=486)
        curl.absorb(trits, offset=0, length=243)
        trits_out = []
        curl.squeeze(trits_out)

        trits_out = TryteString.from_trits(trits_out)

        # noinspection SpellCheckingInspection
        self.assertEqual(
            trits_out,
            'OTYHXEXJLCSMEY9LYCC9ASJXMORTLAYQEHRS9DAH'
            '9NR9DXLXYDGOVOBEL9LWRITLWPHPYPZDKXVPAPKUA',
        )
示例#6
0
  def _create_sponge(self, index):
    # type: (int) -> Curl
    """
    Prepares the Curl sponge for the generator.
    """
    seed = self.seed.as_trits() # type: MutableSequence[int]

    for i in range(index):
      # Treat ``seed`` like a really big number and add ``index``.
      # Note that addition works a little bit differently in balanced
      # ternary.
      for j in range(len(seed)):
        seed[j] += 1

        if seed[j] > 1:
          seed[j] = -1
        else:
          break

    sponge = Curl()
    sponge.absorb(seed)

    # Squeeze all of the trits out of the sponge and re-absorb them.
    # Note that Curl transforms several times per operation, so this
    # sequence is not as redundant as it looks at first glance.
    sponge.squeeze(seed)
    sponge.reset()
    sponge.absorb(seed)

    return sponge
示例#7
0
    def test_absorb_offset(self):
        """
    Passing an ``offset`` argument to :py:meth:`Curl.absorb`.
    """
        # noinspection SpellCheckingInspection
        input_ = ('G9JYBOMPUXHYHKSNRNMMSSZCSHOFYOYNZRSZMAAYWDYEIMVVOGKPJB'
                  'VBM9TDPULSFUNMTVXRKFIDOHUXXVYDLFSZYZTWQYTE9SPYYWYTXJYQ'
                  '9IFGYOLZXWZBKWZN9QOOTBQMWMUBLEWUEEASRHRTNIQWJQNDWRYLCA')

        trits = TryteString(input_).as_trits()

        curl = Curl()
        curl.absorb(trits, offset=243, length=486)
        curl.absorb(trits, offset=0, length=243)
        trits_out = []
        curl.squeeze(trits_out)

        trits_out = TryteString.from_trits(trits_out)

        # noinspection SpellCheckingInspection
        self.assertEqual(
            trits_out,
            'ZWNF9YOCAKC9CXQFYZDKXSSAZOCAZLEVEB9OZDJQ'
            'GWEULHUDY9RAWAT9GIUXTTUSYJEGNGQDVJCGTQLN9',
        )
示例#8
0
  def finalize(self):
    # type: () -> None
    """
    Finalizes the bundle, preparing it to be attached to the Tangle.
    """
    if self.hash:
      raise RuntimeError('Bundle is already finalized.')

    if not self:
      raise ValueError('Bundle has no transactions.')

    # Quick validation.
    balance = self.balance

    if balance < 0:
      if self.change_address:
        self.add_transaction(ProposedTransaction(
          address = self.change_address,
          value   = -balance,
          tag     = self.tag,
        ))
      else:
        raise ValueError(
          'Bundle has unspent inputs (balance: {balance}); '
          'use ``send_unspent_inputs_to`` to create '
          'change transaction.'.format(
            balance = balance,
          ),
        )
    elif balance > 0:
      raise ValueError(
        'Inputs are insufficient to cover bundle spend '
        '(balance: {balance}).'.format(
          balance = balance,
        ),
      )

    # Generate bundle hash.
    sponge      = Curl()
    last_index  = len(self) - 1

    for (i, txn) in enumerate(self): # type: Tuple[int, ProposedTransaction]
      txn.current_index = i
      txn.last_index    = last_index

      sponge.absorb(txn.get_signature_validation_trytes().as_trits())

    bundle_hash = [0] * HASH_LENGTH # type: MutableSequence[int]
    sponge.squeeze(bundle_hash)
    self.hash = Hash.from_trits(bundle_hash)

    # Copy bundle hash to individual transactions.
    for txn in self:
      txn.bundle_hash = self.hash

      # Initialize signature/message fragment.
      txn.signature_message_fragment = Fragment(txn.message or b'')
示例#9
0
  def get_digest(self):
    # type: () -> Digest
    """
    Generates the digest used to do the actual signing.

    Signing keys can have variable length and tend to be quite long,
    which makes them not-well-suited for use in crypto algorithms.

    The digest is essentially the result of running the signing key
    through a PBKDF, yielding a constant-length hash that can be used
    for crypto.
    """
    hashes_per_fragment = FRAGMENT_LENGTH // Hash.LEN

    key_fragments = self.iter_chunks(FRAGMENT_LENGTH)

    # The digest will contain one hash per key fragment.
    digest = [0] * HASH_LENGTH * len(key_fragments)

    # Iterate over each fragment in the key.
    for (i, fragment) in enumerate(key_fragments): # type: Tuple[int, TryteString]
      fragment_trits = fragment.as_trits()

      key_fragment  = [0] * FRAGMENT_LENGTH
      hash_trits    = []

      # Within each fragment, iterate over one hash at a time.
      for j in range(hashes_per_fragment):
        hash_start  = j * HASH_LENGTH
        hash_end    = hash_start + HASH_LENGTH
        hash_trits  = fragment_trits[hash_start:hash_end] # type: MutableSequence[int]

        for k in range(26):
          sponge = Curl()
          sponge.absorb(hash_trits)
          sponge.squeeze(hash_trits)

        key_fragment[hash_start:hash_end] = hash_trits

      #
      # After processing all of the hashes in the fragment, generate a
      # final hash and append it to the digest.
      #
      # Note that we will do this once per fragment in the key, so the
      # longer the key is, the longer the digest will be.
      #
      sponge = Curl()
      sponge.absorb(key_fragment)
      sponge.squeeze(hash_trits)

      fragment_start  = i * FRAGMENT_LENGTH
      fragment_end    = fragment_start + FRAGMENT_LENGTH

      digest[fragment_start:fragment_end] = hash_trits

    return Digest(TryteString.from_trits(digest), self.key_index)
示例#10
0
    def _generate_checksum(self):
        # type: () -> TryteString
        """
    Generates the correct checksum for this address.
    """
        checksum_trits = []  # type: MutableSequence[int]

        sponge = Curl()
        sponge.absorb(self.address.as_trits())
        sponge.squeeze(checksum_trits)

        checksum_length = AddressChecksum.LEN * TRITS_PER_TRYTE

        return TryteString.from_trits(checksum_trits[:checksum_length])
示例#11
0
  def address_from_digest(digest_trits, key_index):
    # type: (Iterable[int], int) -> Address
    """
    Generates an address from a private key digest.
    """
    address_trits = [0] * (Address.LEN * TRITS_PER_TRYTE) # type: MutableSequence[int]

    sponge = Curl()
    sponge.absorb(digest_trits)
    sponge.squeeze(address_trits)

    address = Address.from_trits(address_trits)
    address.key_index = key_index
    return address
示例#12
0
    def get_digest_trits(self):
        # type: () -> List[int]
        """
    Generates the digest used to do the actual signing.

    Signing keys can have variable length and tend to be quite long,
    which makes them not-well-suited for use in crypto algorithms.

    The digest is essentially the result of running the signing key
    through a PBKDF, yielding a constant-length hash that can be used
    for crypto.
    """
        hashes_per_fragment = FRAGMENT_LENGTH // Hash.LEN

        key_chunks = self.iter_chunks(FRAGMENT_LENGTH)

        # The digest will contain one hash per key fragment.
        digest = [0] * HASH_LENGTH * len(key_chunks)

        for (i, fragment
             ) in enumerate(key_chunks):  # type: Tuple[int, TryteString]
            fragment_trits = fragment.as_trits()

            key_fragment = [0] * FRAGMENT_LENGTH
            hash_trits = []

            for j in range(hashes_per_fragment):
                hash_start = j * HASH_LENGTH
                hash_end = hash_start + HASH_LENGTH
                hash_trits = fragment_trits[
                    hash_start:hash_end]  # type: MutableSequence[int]

                for k in range(26):
                    sponge = Curl()
                    sponge.absorb(hash_trits)
                    sponge.squeeze(hash_trits)

                key_fragment[hash_start:hash_end] = hash_trits

            sponge = Curl()
            sponge.absorb(key_fragment)
            sponge.squeeze(hash_trits)

            fragment_start = i * FRAGMENT_LENGTH
            fragment_end = fragment_start + FRAGMENT_LENGTH

            digest[fragment_start:fragment_end] = hash_trits

        return digest
示例#13
0
    def address_from_digest(digest):
        # type: (Digest) -> Address
        """
    Generates an address from a private key digest.
    """
        address_trits = [0] * (Address.LEN * TRITS_PER_TRYTE
                               )  # type: MutableSequence[int]

        sponge = Curl()
        sponge.absorb(digest.as_trits())
        sponge.squeeze(address_trits)

        return Address.from_trits(
            trits=address_trits,
            key_index=digest.key_index,
            security_level=digest.security_level,
        )
示例#14
0
    def from_tryte_string(cls, trytes, hash_=None):
        # type: (TrytesCompatible, Optional[TransactionHash]) -> Transaction
        """
        Creates a Transaction object from a sequence of trytes.

        :param trytes:
            Raw trytes.  Should be exactly 2673 trytes long.

        :param hash_:
            The transaction hash, if available.

            If not provided, it will be computed from the transaction
            trytes.
        """
        tryte_string = TransactionTrytes(trytes)

        if not hash_:
            hash_trits = [0] * HASH_LENGTH  # type: MutableSequence[int]

            sponge = Curl()
            sponge.absorb(tryte_string.as_trits())
            sponge.squeeze(hash_trits)

            hash_ = TransactionHash.from_trits(hash_trits)

        return cls(
            hash_=hash_,
            signature_message_fragment=Fragment(tryte_string[0:2187]),
            address=Address(tryte_string[2187:2268]),
            value=int_from_trits(tryte_string[2268:2295].as_trits()),
            legacy_tag=Tag(tryte_string[2295:2322]),
            timestamp=int_from_trits(tryte_string[2322:2331].as_trits()),
            current_index=int_from_trits(tryte_string[2331:2340].as_trits()),
            last_index=int_from_trits(tryte_string[2340:2349].as_trits()),
            bundle_hash=BundleHash(tryte_string[2349:2430]),
            trunk_transaction_hash=TransactionHash(tryte_string[2430:2511]),
            branch_transaction_hash=TransactionHash(tryte_string[2511:2592]),
            tag=Tag(tryte_string[2592:2619]),
            attachment_timestamp=int_from_trits(
                tryte_string[2619:2628].as_trits()),
            attachment_timestamp_lower_bound=int_from_trits(
                tryte_string[2628:2637].as_trits()),
            attachment_timestamp_upper_bound=int_from_trits(
                tryte_string[2637:2646].as_trits()),
            nonce=Nonce(tryte_string[2646:2673]),
        )
示例#15
0
  def test_squeeze_offset(self):
    """
    Passing an ``offset`` argument to :py:meth:`Curl.squeeze`.

    Example use case:
    https://github.com/iotaledger/iri/blob/v1.4.1.6/src/main/java/com/iota/iri/hash/ISS.java#L83
    """
    # noinspection SpellCheckingInspection
    input_ = (
      'CDLFODMOGMQAWXDURDXTUAOO9BFESHYGZLBUWIIHPTLNZCUNHZAAXSUPUIBW'
      'IRLOVKCVWJSWEKRJQZUVRDZGZRNANUNCSGANCJWVHMZMVNJVUAZNFZKDAIVV'
      'LSMIM9SVGUHYECTGGIXTAMXXO9FIXUMQFZCGRQWAOWJPBTXNNQIRSTZEEAJV'
      'FSXWTHWBQJCWQNYYMHSPCYRA99ITVILYJPMFGOGOUOZUVABK9HMGABSORCVD'
      'FNGLMPJ9NFKBWCZMFPIWEAGRWPRNLLG9VYUUVLCTEWKGWQIRIJKERZWC9LVR'
      'XJEXNHBNUGEGGLMWGERKYFB9YEZCLXLKKMCGLRKQOGASDOUDYEDJLMV9BHPG'
      'GCXQIUVUOFFXKEIIINLVWLRYHHLKXPLSTWKIKNEJWEDFQQFXQVEHGRCIJC9T'
      'GVQNPPKGCFGPJNWSCPQZDDSIGAVZEIVYJDVPUOCTEMKTZFGXNGPQCOIBD9MX'
      'YTHJTX'
    )

    trits = TryteString(input_).as_trits()
    curl = Curl()

    trits_out = [0] * 243
    for i in range(6):
      curl.reset()
      curl.absorb(trits, i * 243, (i + 1) * 243)
      curl.squeeze(trits, i * 243)

    curl.reset()
    curl.absorb(trits)
    curl.squeeze(trits_out)

    trits_out = TryteString.from_trits(trits_out)

    # noinspection SpellCheckingInspection
    self.assertEqual(
      trits_out,

      'TAWDGNSEAD9ZRGBBVRVEKQYYVDOKHYQ9KEIYJKFT'
      'BQEYZDWZVMRFJQQGTMPHBZOGPIJCCVWLZVDKLAQVI',
    )
示例#16
0
  def from_tryte_string(cls, trytes, hash_=None):
    # type: (TrytesCompatible, Optional[TransactionHash]) -> Transaction
    """
    Creates a Transaction object from a sequence of trytes.

    :param trytes:
      Raw trytes.  Should be exactly 2673 trytes long.

    :param hash_:
      The transaction hash, if available.
      If not provided, it will be computed from the transaction trytes.
    """
    tryte_string = TransactionTrytes(trytes)

    if not hash_:
      hash_trits = [0] * HASH_LENGTH # type: MutableSequence[int]

      sponge = Curl()
      sponge.absorb(tryte_string.as_trits())
      sponge.squeeze(hash_trits)

      hash_ = TransactionHash.from_trits(hash_trits)

    return cls(
      hash_ = hash_,
      signature_message_fragment = Fragment(tryte_string[0:2187]),
      address = Address(tryte_string[2187:2268]),
      value = int_from_trits(tryte_string[2268:2295].as_trits()),
      legacy_tag = Tag(tryte_string[2295:2322]),
      timestamp = int_from_trits(tryte_string[2322:2331].as_trits()),
      current_index = int_from_trits(tryte_string[2331:2340].as_trits()),
      last_index = int_from_trits(tryte_string[2340:2349].as_trits()),
      bundle_hash = BundleHash(tryte_string[2349:2430]),
      trunk_transaction_hash = TransactionHash(tryte_string[2430:2511]),
      branch_transaction_hash = TransactionHash(tryte_string[2511:2592]),
      tag = Tag(tryte_string[2592:2619]),
      attachment_timestamp = int_from_trits(tryte_string[2619:2628].as_trits()),
      attachment_timestamp_lower_bound = int_from_trits(tryte_string[2628:2637].as_trits()),
      attachment_timestamp_upper_bound = int_from_trits(tryte_string[2637:2646].as_trits()),
      nonce = Nonce(tryte_string[2646:2673]),
    )
示例#17
0
def validate_signature_fragments(fragments, hash_, public_key):
    # type: (Sequence[TryteString], Hash, TryteString) -> bool
    """
  Returns whether a sequence of signature fragments is valid.

  :param fragments:
    Sequence of signature fragments (usually
    :py:class:`iota.transaction.Fragment` instances).

  :param hash_:
    Hash used to generate the signature fragments (usually a
    :py:class:`iota.transaction.BundleHash` instance).

  :param public_key:
    The public key value used to verify the signature digest (usually a
    :py:class:`iota.types.Address` instance).
  """
    checksum = [0] * (HASH_LENGTH * len(fragments))
    normalized_hash = normalize(hash_)

    for (i, fragment) in enumerate(fragments):  # type: Tuple[int, TryteString]
        outer_sponge = Curl()

        # If there are more than 3 iterations, loop back around to the
        # start.
        normalized_chunk = normalized_hash[i % len(normalized_hash)]

        buffer = []
        for (j, hash_trytes) in enumerate(fragment.iter_chunks(
                Hash.LEN)):  # type: Tuple[int, TryteString]
            buffer = hash_trytes.as_trits()  # type: MutableSequence[int]
            inner_sponge = Curl()

            # Note the sign flip compared to ``SignatureFragmentGenerator``.
            for _ in range(13 + normalized_chunk[j]):
                inner_sponge.reset()
                inner_sponge.absorb(buffer)
                inner_sponge.squeeze(buffer)

            outer_sponge.absorb(buffer)

        outer_sponge.squeeze(buffer)
        checksum[i * HASH_LENGTH:(i + 1) * HASH_LENGTH] = buffer

    actual_public_key = [0] * HASH_LENGTH  # type: MutableSequence[int]
    addy_sponge = Curl()
    addy_sponge.absorb(checksum)
    addy_sponge.squeeze(actual_public_key)

    return actual_public_key == public_key.as_trits()
示例#18
0
class MultisigAddressBuilder(object):
    """
  Creates multisig addresses.

  Note that this class generates a single address from multiple inputs,
  (digests) unlike :py:class:`iota.crypto.addresses.AddressGenerator`
  which generates multiple addresses from a single input (seed).
  """
    def __init__(self):
        super(MultisigAddressBuilder, self).__init__()

        self._digests = []  # type: List[Digest]
        """
    Keeps track of digests that were added, so that we can attach them
    to the final :py:class:`MultisigAddress` object.
    """

        self._address = None  # type: Optional[MultisigAddress]
        """
    Caches the generated address.

    Generating the address modifies the internal state of the curl
    sponge, so each :py:class:`MultisigAddressBuilder` instance can
    only generate a single address.
    """

        self._sponge = Curl()

    def add_digest(self, digest):
        # type: (Digest) -> None
        """
    Absorbs a digest into the sponge.

    IMPORTANT: Keep track of the order that digests are added!
    To spend inputs from a multisig address, you must provide the
    private keys in the same order!

    References:
      - https://github.com/iotaledger/wiki/blob/master/multisigs.md#spending-inputs
    """
        if self._address:
            raise ValueError(
                'Cannot add digests once an address is extracted.')

        self._sponge.absorb(digest.as_trits())
        self._digests.append(digest)

    def get_address(self):
        # type: () -> MultisigAddress
        """
    Returns the new multisig address.

    Note that you can continue to add digests after extracting an
    address; the next address will use *all* of the digests that have
    been added so far.
    """
        if not self._digests:
            raise ValueError(
                'Must call ``add_digest`` at least once '
                'before calling ``get_address``.', )

        if not self._address:
            address_trits = [0] * HASH_LENGTH
            self._sponge.squeeze(address_trits)

            self._address =\
              MultisigAddress.from_trits(address_trits, digests=self._digests[:])

        return self._address
示例#19
0
class SignatureFragmentGenerator(Iterator[TryteString]):
  """
  Used to generate signature fragments progressively.

  Each instance can generate 1 signature per fragment in the private
  key.
  """
  def __init__(self, private_key, hash_):
    # type: (PrivateKey, TryteString) -> None
    super(SignatureFragmentGenerator, self).__init__()

    self._key_chunks      = private_key.iter_chunks(FRAGMENT_LENGTH)
    self._iteration       = -1
    self._normalized_hash = normalize(hash_)
    self._sponge          = Curl()

  def __iter__(self):
    # type: () -> SignatureFragmentGenerator
    return self

  def __len__(self):
    # type: () -> int
    """
    Returns the number of fragments this generator can create.

    Note: This method always returns the same result, no matter how
    many iterations have been completed.
    """
    return len(self._key_chunks)

  def __next__(self):
    # type: () -> TryteString
    """
    Returns the next signature fragment.
    """
    key_trytes = next(self._key_chunks) # type: TryteString
    self._iteration += 1

    # If the key is long enough, loop back around to the start.
    normalized_chunk =\
      self._normalized_hash[self._iteration % len(self._normalized_hash)]

    signature_fragment = key_trytes.as_trits()

    # Build the signature, one hash at a time.
    for i in range(key_trytes.count_chunks(Hash.LEN)):
      hash_start  = i * HASH_LENGTH
      hash_end    = hash_start + HASH_LENGTH

      buffer = signature_fragment[hash_start:hash_end] # type: MutableSequence[int]

      for _ in range(13 - normalized_chunk[i]):
        self._sponge.reset()
        self._sponge.absorb(buffer)
        self._sponge.squeeze(buffer)

      signature_fragment[hash_start:hash_end] = buffer

    return TryteString.from_trits(signature_fragment)

  if PY2:
    next = __next__
示例#20
0
def hash(trytes):
    curl = Curl()
    curl.absorb(trytes.as_trits())
    trits_out = []
    curl.squeeze(trits_out)
    return TryteString.from_trits(trits_out)
示例#21
0
    def conductPOW(self, bundle):
        HASH_LENGTH = 243
        mwm = 14  # minimum weight on mainnet tangle (expected 1 minute for iot device at this level)
        trailing_zeros = [0] * mwm  # For checking transaction hash
        previoustx = None
        max_iter = 5
        i = 0

        branch_transaction_hash = bundle.branchObj.bundle_hash
        trunk_transaction_hash = bundle.trunkObj.bundle_hash

        for trxn in reversed(bundle.trxns):
            startTime = time.time()
            trxn.attachment_timestamp = int(round(time.time() * 1000))

            while i != max_iter:
                if (not previoustx):
                    if trxn.current_index == trxn.last_index:
                        trxn.branch_transaction_hash = branch_transaction_hash
                        trxn.trunk_transaction_hash = trunk_transaction_hash
                    else:
                        raise ValueError(
                            'Head transaction is inconsistent in bundle')

                else:  # It is not the head transaction (For clarity, see bundle figure in report)
                    trxn.branch_transaction_hash = trunk_transaction_hash
                    trxn.trunk_transaction_hash = previoustx

                # Let's do the pow locally
                trxn_string = trxn.as_tryte_string().__str__()
                # returns a python unicode string
                powed_trytes = _libccurl.ccurl_pow(trxn_string.encode('utf-8'),
                                                   mwm)
                # construct trytestring from python string
                powed_trytes_bytes = powed_trytes[:2673]
                # Let's decode into unicode
                powed_txn_trytes = powed_trytes_bytes.decode('utf-8')
                powed_txn_trytes = TryteString(powed_txn_trytes)

                # Create powed txn hash
                hash_trits: MutableSequence[int] = [0] * HASH_LENGTH
                sponge = Curl()
                sponge.absorb(powed_txn_trytes.as_trits())
                sponge.squeeze(hash_trits)
                hash = TransactionHash.from_trits(hash_trits)
                trxn.hash = hash
                previoustx = hash

                if hash_trits[-mwm:] == trailing_zeros:
                    # We are good to go, exit from while loop
                    totalTime = time.time() - startTime
                    logger.info("Successfully conducted PoW for trxn " +
                                str(trxn.current_index) +
                                "! Time: {:.4g}".format(totalTime) + " sec")
                    break
                else:
                    i = i + 1
                    logger.info(
                        'Oops, wrong hash detected in try'
                        ' #{rounds}. Recalculating PoW... '.format(rounds=i))

        # Tail transactions represent bundles in the tangle
        return bundle.tail_transaction.hash
示例#22
0
    def from_tryte_string(cls: Type[T],
                          trytes: TrytesCompatible,
                          hash_: Optional[TransactionHash] = None) -> T:
        """
        Creates a Transaction object from a sequence of trytes.

        :param TrytesCompatible trytes:
            Raw trytes.  Should be exactly 2673 trytes long.

        :param Optional[TransactionHash] hash_:
            The transaction hash, if available.

            If not provided, it will be computed from the transaction
            trytes.

        :return:
            :py:class:`Transaction` object.

        Example usage::

            from iota import Transaction

            txn =\\
              Transaction.from_tryte_string(
                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'
              )

        """
        tryte_string = TransactionTrytes(trytes)

        if not hash_:
            hash_trits: MutableSequence[int] = [0] * HASH_LENGTH

            sponge = Curl()
            sponge.absorb(tryte_string.as_trits())
            sponge.squeeze(hash_trits)

            hash_ = TransactionHash.from_trits(hash_trits)

        return cls(
            hash_=hash_,
            signature_message_fragment=Fragment(tryte_string[0:2187]),
            address=Address(tryte_string[2187:2268]),
            value=int_from_trits(tryte_string[2268:2295].as_trits()),
            legacy_tag=Tag(tryte_string[2295:2322]),
            timestamp=int_from_trits(tryte_string[2322:2331].as_trits()),
            current_index=int_from_trits(tryte_string[2331:2340].as_trits()),
            last_index=int_from_trits(tryte_string[2340:2349].as_trits()),
            bundle_hash=BundleHash(tryte_string[2349:2430]),
            trunk_transaction_hash=TransactionHash(tryte_string[2430:2511]),
            branch_transaction_hash=TransactionHash(tryte_string[2511:2592]),
            tag=Tag(tryte_string[2592:2619]),
            attachment_timestamp=int_from_trits(
                tryte_string[2619:2628].as_trits()),
            attachment_timestamp_lower_bound=int_from_trits(
                tryte_string[2628:2637].as_trits()),
            attachment_timestamp_upper_bound=int_from_trits(
                tryte_string[2637:2646].as_trits()),
            nonce=Nonce(tryte_string[2646:2673]),
        )