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

Use class length for random TryteString generation #286

Merged
merged 1 commit into from
Jan 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions iota/crypto/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ class Seed(TryteString):
- https://iota.stackexchange.com/q/249
"""

LEN = 81
"""
Length of a Seed.
"""

def __init__(self, trytes=None):
# type: (Optional[TrytesCompatible]) -> None
if trytes and len(trytes) > Hash.LEN:
Expand Down
15 changes: 12 additions & 3 deletions iota/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,19 +68,28 @@ class TryteString(JsonSerializable):
"""

@classmethod
def random(cls, length):
# type: (int) -> TryteString
def random(cls, length=None):
# type: (Optional[int]) -> TryteString
"""
Generates a random sequence of trytes.

:param int length:
:param Optional[int] length:
Number of trytes to generate.

:return:
:py:class:`TryteString` object.
"""
alphabet = list(itervalues(AsciiTrytesCodec.alphabet))
generator = SystemRandom()
try:
if length is None:
length = cls.LEN

if length <= 0:
raise TypeError("length parameter needs to be greater than zero")
except AttributeError: # class has no LEN attribute
if length is None:
raise TypeError("{class_name} does not define a length property".format(class_name=cls.__name__))

# :py:meth:`SystemRandom.choices` wasn't added until Python 3.6;
# for compatibility, we will continue to use ``choice`` in a
Expand Down
13 changes: 13 additions & 0 deletions test/crypto/types_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ def test_init_error_too_short(self):
with self.assertRaises(ValueError):
Digest(b'9' * (2 * Hash.LEN - 1))

def test_random(self):
"""
Generating a random Digest should fail.
"""
with self.assertRaises(TypeError):
random_digest = Digest.random()

# noinspection SpellCheckingInspection
class PrivateKeyTestCase(TestCase):
Expand Down Expand Up @@ -152,3 +158,10 @@ def test_get_digest_multiple_fragments(self):
#
# Each fragment is processed independently, which is critical for
# multisig to work correctly.

def test_random(self):
"""
Generating a random PrivateKey should fail.
"""
with self.assertRaises(TypeError):
random_digest = PrivateKey.random()
42 changes: 41 additions & 1 deletion test/transaction/types_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

from six import binary_type

from iota import TransactionHash
from iota import TransactionHash, BundleHash, Fragment, TransactionTrytes, \
Nonce


class TransactionHashTestCase(TestCase):
Expand Down Expand Up @@ -39,3 +40,42 @@ def test_init_error_too_long(self):
b'JVMTDGDPDFYHMZPMWEKKANBQSLSDTIIHAYQUMZOK'
b'HXXXGJHJDQPOMDOMNRDKYCZRUFZROZDADTHZC99999'
)

def test_random(self):
"""
Creating a random TransactionHash object.
"""
random_tx_hash = TransactionHash.random()
self.assertEqual(len(random_tx_hash), TransactionHash.LEN)

class BundleHashTestCase(TestCase):
def test_random(self):
"""
Creating a random BundleHash object.
"""
random_bundle_hash = BundleHash.random()
self.assertEqual(len(random_bundle_hash), BundleHash.LEN)

class FragmentTestCase(TestCase):
def test_random(self):
"""
Creating a random Fragment object.
"""
random_fragment = Fragment.random()
self.assertEqual(len(random_fragment), Fragment.LEN)

class TransactionTrytesTestCase(TestCase):
def test_random(self):
"""
Creating a random TransactionTrytes object.
"""
random_tx_trytes = TransactionTrytes.random()
self.assertEqual(len(random_tx_trytes), TransactionTrytes.LEN)

class NonceTestCase(TestCase):
def test_random(self):
"""
Creating a random Nonce object.
"""
random_nonce = Nonce.random()
self.assertEqual(len(random_nonce), Nonce.LEN)
42 changes: 42 additions & 0 deletions test/types_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,20 @@ def test_random(self):
# generated.
self.assertEqual(len(trytes), Hash.LEN)

def test_random_no_length(self):
"""
Trying to create a random TryteString without specifying length.
"""
with self.assertRaises(TypeError):
trytes = TryteString.random()

def test_random_wrong_length(self):
"""
Generating random Trytestring with negative length.
"""
with self.assertRaises(TypeError):
trytes = TryteString.random(length=-5)

def test_from_bytes(self):
"""
Converting a sequence of bytes into a TryteString.
Expand Down Expand Up @@ -883,6 +897,14 @@ def test_from_trits_wrong_length_padded(self):
b'RBTC',
)

class HashTestCase(TestCase):
def test_random(self):
"""
Generating a random Hash.
"""
rand = Hash.random()
self.assertEqual(len(rand), Hash.LEN)


# noinspection SpellCheckingInspection
class AddressTestCase(TestCase):
Expand Down Expand Up @@ -1124,6 +1146,12 @@ def test_remove_checksum_second_time(self):
self.assertFalse(addy.is_checksum_valid())
self.assertTrue(len(addy) == Address.LEN)

def test_random(self):
"""
Creating a random Address object.
"""
addy = Address.random()
self.assertEqual(len(addy), Address.LEN)

# noinspection SpellCheckingInspection
class AddressChecksumTestCase(TestCase):
Expand All @@ -1149,6 +1177,13 @@ def test_init_error_too_long(self):
# If it's an address checksum, it must be 9 trytes exactly.
AddressChecksum(b'FOXM9MUBX9')

def test_random(self):
"""
Creating a random AddressChecksum object.
"""
checksum = AddressChecksum.random()
self.assertEqual(len(checksum), AddressChecksum.LEN)


# noinspection SpellCheckingInspection
class TagTestCase(TestCase):
Expand All @@ -1167,3 +1202,10 @@ def test_init_error_too_long(self):
with self.assertRaises(ValueError):
# 28 chars = no va.
Tag(b'COLOREDCOINS9999999999999999')

def test_random(self):
"""
Creating a random Tag object.
"""
tag = Tag.random()
self.assertEqual(len(tag), Tag.LEN)