Skip to content
This repository has been archived by the owner on Jan 13, 2023. It is now read-only.

Commit

Permalink
Merge pull request #133 from iotaledger/feature/90-TryteString_needs_…
Browse files Browse the repository at this point in the history
…a_thesaurus

Give TryteString a thesaurus
  • Loading branch information
todofixthis committed Jan 6, 2018
2 parents 255abb9 + 2e38e0a commit 63b2010
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 101 deletions.
22 changes: 11 additions & 11 deletions docs/multisig.rst
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
Multisignature
==============

Multisignature transactions are transactions which require multiple signatures before execution. In simplest example it means that, if there is token wallet which require 5 signatures from different parties, all 5 parties must sign spent transaction, before it will be processed.
Multisignature transactions are transactions which require multiple signatures before execution. In simplest example it means that, if there is token wallet which require 5 signatures from different parties, all 5 parties must sign spent transaction, before it will be processed.

It is standard functionality in blockchain systems and it is also implemented in IOTA

.. note::

You can read more about IOTA multisignature on the `wiki`_.
You can read more about IOTA multisignature on the `wiki`_.

Generating multisignature address
---------------------------------

In order to use multisignature functionality, a special multisignature address must be created. It is done by adding each key digest in agreed order into digests list. At the end, last participant is converting digests list (Curl state trits) into multisignature address.
In order to use multisignature functionality, a special multisignature address must be created. It is done by adding each key digest in agreed order into digests list. At the end, last participant is converting digests list (Curl state trits) into multisignature address.

.. note::

Expand Down Expand Up @@ -45,8 +45,8 @@ And here is example where digests are converted into multisignature address:
.. code-block:: python
cma_result =\
api_1.create_multisig_address(digests=[digest_1,
digest_2,
api_1.create_multisig_address(digests=[digest_1,
digest_2,
digest_3])
# For consistency, every API command returns a dict, even if it only
Expand Down Expand Up @@ -90,7 +90,7 @@ First signer for multisignature wallet is defining address where tokens should b
# If you'd like, you may include an optional tag and/or
# message.
tag = Tag(b'KITTEHS'),
message = TryteString.from_string('thanx fur cheezburgers'),
message = TryteString.from_unicode('thanx fur cheezburgers'),
),
],
Expand Down Expand Up @@ -142,9 +142,9 @@ When trytes are prepared, round of signing must be performed. Order of signing m
.. note::

After creation, bundle can be optionally validated:

.. code-block:: python
validator = BundleValidator(bundle)
if not validator.is_valid():
raise ValueError(
Expand Down Expand Up @@ -181,11 +181,11 @@ Full code `example`_.

In order to enable a 2 of 3 multisig, the cosigners need to share their private keys with the other parties in such a way that no single party can sign inputs alone, but that still enables an M-of-N multsig. In our example, the sharing of the private keys would look as follows:

Alice -> Bob
Alice -> Bob

Bob -> Carol
Bob -> Carol

Carol -> Alice
Carol -> Alice

Now, each participant holds two private keys that he/she can use to collude with another party to successfully sign the inputs and make a transaction. But no single party holds enough keys (3 of 3) to be able to independently make the transaction.

Expand Down
10 changes: 5 additions & 5 deletions docs/types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -65,21 +65,21 @@ Encoding
from iota import TryteString
message_trytes = TryteString.from_string('Hello, IOTA!')
message_trytes = TryteString.from_unicode('Hello, IOTA!')
To encode character data into trytes, use the
``TryteString.from_string`` method.
``TryteString.from_unicode`` method.

You can also convert a tryte sequence into characters using
``TryteString.as_string``. Note that not every tryte sequence can be
``TryteString.decode``. Note that not every tryte sequence can be
converted; garbage in, garbage out!

.. code:: python
from iota import TryteString
trytes = TryteString(b'RBTC9D9DCDQAEASBYBCCKBFA')
message = trytes.as_string()
message = trytes.decode()
.. note::

Expand Down Expand Up @@ -226,7 +226,7 @@ hasn't been broadcast yet.
b'EFNDOCQCMERGUATCIEGGOHPHGFIAQEZGNHQ9W99CH'
),
message = TryteString.from_string('thx fur cheezburgers'),
message = TryteString.from_unicode('thx fur cheezburgers'),
tag = Tag(b'KITTEHS'),
value = 42,
)
Expand Down
6 changes: 3 additions & 3 deletions iota/transaction/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
from iota.codecs import TrytesDecodeError
from iota.crypto import Curl, HASH_LENGTH
from iota.json import JsonSerializable
from iota.transaction.types import BundleHash, Fragment, Nonce, TransactionHash, \
TransactionTrytes
from iota.transaction.types import BundleHash, Fragment, Nonce, \
TransactionHash, TransactionTrytes
from iota.trits import int_from_trits, trits_from_int
from iota.types import Address, Tag, TryteString, TrytesCompatible

Expand Down Expand Up @@ -485,7 +485,7 @@ def get_messages(self, errors='drop'):

if message_trytes:
try:
messages.append(message_trytes.as_string(decode_errors))
messages.append(message_trytes.decode(decode_errors))
except (TrytesDecodeError, UnicodeDecodeError):
if errors != 'drop':
raise
Expand Down
95 changes: 70 additions & 25 deletions iota/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
from math import ceil
from random import SystemRandom
from typing import Any, AnyStr, Generator, Iterable, Iterator, List, \
MutableSequence, Optional, Text, Union
MutableSequence, Optional, Text, Type, TypeVar, Union
from warnings import warn

from six import PY2, binary_type, itervalues, python_2_unicode_compatible, \
text_type
Expand All @@ -24,15 +25,17 @@
'AddressChecksum',
'Hash',
'Tag',
'TryteString',
'TrytesCompatible',
'TryteString',
]


# Custom types for type hints and docstrings.
TrytesCompatible = Union[AnyStr, bytearray, 'TryteString']


T = TypeVar('T', bound='TryteString')

@python_2_unicode_compatible
class TryteString(JsonSerializable):
"""
Expand Down Expand Up @@ -67,19 +70,18 @@ def random(cls, length):

@classmethod
def from_bytes(cls, bytes_, codec=AsciiTrytesCodec.name, *args, **kwargs):
# type: (Union[binary_type, bytearray], Text, *Any, **Any) -> TryteString
# type: (Type[T], Union[binary_type, bytearray], Text, *Any, **Any) -> T
"""
Creates a TryteString from a sequence of bytes.
:param bytes_:
Source bytes.
:param codec:
Which codec to use:
Reserved for future use.
- 'trytes_binary': Converts each byte into a sequence of trits
with the same value (this is usually what you want).
- 'trytes_ascii': Uses the legacy ASCII codec.
See https://github.com/iotaledger/iota.lib.py/issues/62 for more
information.
:param args:
Additional positional arguments to pass to the initializer.
Expand All @@ -90,8 +92,8 @@ def from_bytes(cls, bytes_, codec=AsciiTrytesCodec.name, *args, **kwargs):
return cls(encode(bytes_, codec), *args, **kwargs)

@classmethod
def from_string(cls, string, *args, **kwargs):
# type: (Text, *Any, **Any) -> TryteString
def from_unicode(cls, string, *args, **kwargs):
# type: (Type[T], Text, *Any, **Any) -> T
"""
Creates a TryteString from a Unicode string.
Expand All @@ -111,9 +113,22 @@ def from_string(cls, string, *args, **kwargs):
**kwargs
)

@classmethod
def from_string(cls, *args, **kwargs):
"""
Deprecated; use :py:meth:`from_unicode` instead.
https://github.com/iotaledger/iota.lib.py/issues/90
"""
warn(
message='`from_string()` is deprecated; use `from_unicode()` instead.',
category=DeprecationWarning,
)
return cls.from_unicode(*args, **kwargs)

@classmethod
def from_trytes(cls, trytes, *args, **kwargs):
# type: (Iterable[Iterable[int]], *Any, **Any) -> TryteString
# type: (Type[T], Iterable[Iterable[int]], *Any, **Any) -> T
"""
Creates a TryteString from a sequence of trytes.
Expand Down Expand Up @@ -145,7 +160,7 @@ def from_trytes(cls, trytes, *args, **kwargs):

@classmethod
def from_trits(cls, trits, *args, **kwargs):
# type: (Iterable[int], *Any, **Any) -> TryteString
# type: (Type[T], Iterable[int], *Any, **Any) -> T
"""
Creates a TryteString from a sequence of trits.
Expand Down Expand Up @@ -234,7 +249,7 @@ def __init__(self, trytes, pad=None):

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

if not isinstance(trytes, bytearray):
trytes = bytearray(trytes)
Expand Down Expand Up @@ -279,8 +294,8 @@ def __bytes__(self):
only returns an ASCII representation of the trytes themselves!
If you want to...
- ... decode trytes into bytes: use :py:meth:`as_bytes`.
- ... decode trytes into Unicode: use :py:meth:`as_string`.
- ... encode trytes into bytes: use :py:meth:`encode`.
- ... decode trytes into Unicode: use :py:meth:`decode`.
"""
return binary_type(self._trytes)

Expand Down Expand Up @@ -444,10 +459,11 @@ def iter_chunks(self, chunk_size):
"""
return ChunkIterator(self, chunk_size)

def as_bytes(self, errors='strict', codec=AsciiTrytesCodec.name):
def encode(self, errors='strict', codec=AsciiTrytesCodec.name):
# type: (Text, Text) -> binary_type
"""
Converts the TryteString into a byte string.
Encodes the TryteString into a lower-level primitive (usually
bytes).
:param errors:
How to handle trytes that can't be converted:
Expand All @@ -456,24 +472,41 @@ def as_bytes(self, errors='strict', codec=AsciiTrytesCodec.name):
- 'ignore': omit the tryte from the result.
:param codec:
Which codec to use:
Reserved for future use.
- 'trytes_binary': Converts each sequence of 5 trits into a byte
with the same value (this is usually what you want).
- 'trytes_ascii': Uses the legacy ASCII codec.
See https://github.com/iotaledger/iota.lib.py/issues/62 for more
information.
:raise:
- :py:class:`iota.codecs.TrytesDecodeError` if the trytes cannot
be decoded into bytes.
"""
# Converting ASCII-encoded trytes into bytes is considered to be a
# *decode* operation according to :py:class:`AsciiTrytesCodec`.
# Once we add more codecs, we may need to revisit this.
# See https://github.com/iotaledger/iota.lib.py/issues/62 for more
# information.
#
# In Python 2, :py:func:`decode` does not accept keyword arguments.
return decode(self._trytes, codec, errors)

def as_string(self, errors='strict', strip_padding=True):
def as_bytes(self, *args, **kwargs):
"""
Deprecated; use :py:meth:`encode` instead.
https://github.com/iotaledger/iota.lib.py/issues/90
"""
warn(
category=DeprecationWarning,
message='`as_bytes()` is deprecated; use `encode()` instead.',
)
return self.encode(*args, **kwargs)

def decode(self, errors='strict', strip_padding=True):
# type: (Text, bool) -> Text
"""
Attempts to interpret the TryteString as a UTF-8 encoded Unicode
string.
Decodes the TryteString into a higher-level abstraction (usually
Unicode characters).
:param errors:
How to handle trytes that can't be converted, or bytes that can't
Expand All @@ -500,6 +533,18 @@ def as_string(self, errors='strict', strip_padding=True):

return decode(trytes, AsciiTrytesCodec.name, errors).decode('utf-8', errors)

def as_string(self, *args, **kwargs):
"""
Deprecated; use :py:meth:`decode` instead.
https://github.com/iotaledger/iota.lib.py/issues/90
"""
warn(
category=DeprecationWarning,
message='`as_string()` is deprecated; use `decode()` instead.',
)
return self.decode(*args, **kwargs)

def as_json_compatible(self):
# type: () -> Text
"""
Expand Down Expand Up @@ -757,7 +802,7 @@ def with_valid_checksum(self):
)

def _generate_checksum(self):
# type: () -> TryteString
# type: () -> AddressChecksum
"""
Generates the correct checksum for this address.
"""
Expand All @@ -769,7 +814,7 @@ def _generate_checksum(self):

checksum_length = AddressChecksum.LEN * TRITS_PER_TRYTE

return TryteString.from_trits(checksum_trits[-checksum_length:])
return AddressChecksum.from_trits(checksum_trits[-checksum_length:])


class AddressChecksum(TryteString):
Expand Down
4 changes: 2 additions & 2 deletions test/commands/extended/prepare_transfer_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1132,7 +1132,7 @@ def test_pass_message_short(self):
'VNDMLXPT9HMVAOWUUZMLSJZFWGKDVGXPSQAWAEBJN'
),

message = TryteString.from_string('สวัสดีชาวโลก!'),
message = TryteString.from_unicode('สวัสดีชาวโลก!'),
tag = Tag('PYOTA9UNIT9TESTS9'),
value = 0,
),
Expand Down Expand Up @@ -1168,7 +1168,7 @@ def test_pass_message_long(self):
),

message =
TryteString.from_string(
TryteString.from_unicode(
'Вы не можете справиться правду! Сын, мы живем в мире, который '
'имеет стены. И эти стены должны быть охраняют люди с оружием. '
'Кто будет это делать? Вы? Вы, лейтенант Weinberg? У меня есть '
Expand Down

0 comments on commit 63b2010

Please sign in to comment.