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

Release/2.0.0 #76

Merged
merged 14 commits into from
Oct 3, 2017
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
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ deploy:
python: '3.6'
tags: true
provider: pypi
distribution: 'bdist_wheel sdist'
distributions: 'bdist_wheel sdist'
skip_upload_docs: true
user: phx
password:
Expand Down
14 changes: 3 additions & 11 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@
=====
PyOTA
=====
.. warning::
⚠️ This is pre-release software; it may have performance or stability issues.
Please do not use this software on mainnet until v2.0.0 stable is released. ⚠️

This is the official Python library for the IOTA Core.

It implements both the `official API`_, as well as newly-proposed functionality
Expand All @@ -32,13 +28,9 @@ PyOTA is compatible with Python 3.6, 3.5 and 2.7.
============
Installation
============
.. warning::
⚠️ This is pre-release software; it may have performance or stability issues.
Please do not use this software on mainnet until v2.0.0 stable is released. ⚠️

To install the latest version::

pip install --pre pyota
pip install pyota

Optional C Extension
====================
Expand All @@ -47,7 +39,7 @@ cryptography features significantly (speedups of **60x** are common!).

To install this extension, use the following command::

pip install --pre pyota[ccurl]
pip install pyota[ccurl]


Installing from Source
Expand Down Expand Up @@ -75,7 +67,7 @@ For the full documentation of this library, please refer to the
`official API`_


.. _Create virtualenv: https://virtualenvwrapper.readthedocs.io/
.. _Create virtualenv: https://realpython.com/blog/python/python-virtual-environments-a-primer/
.. _PyOTA Bug Tracker: https://github.com/iotaledger/iota.lib.py/issues
.. _Slack: https://slack.iota.org/
.. _dedicated forum: https://forum.iota.org/
Expand Down
2 changes: 1 addition & 1 deletion iota/commands/extended/replay_bundle.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def _execute(self, request):
minWeightMagnitude = min_weight_magnitude,


trytes = bundle.as_tryte_strings(head_to_tail=True),
trytes = bundle.as_tryte_strings(),
)


Expand Down
2 changes: 1 addition & 1 deletion iota/json.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from abc import ABCMeta, abstractmethod as abstract_method
from json.encoder import JSONEncoder as BaseJsonEncoder
from typing import Mapping, Iterable
from typing import Iterable, Mapping, Text

from six import with_metaclass

Expand Down
110 changes: 88 additions & 22 deletions iota/transaction/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from iota.crypto import Curl, HASH_LENGTH
from iota.json import JsonSerializable
from iota.transaction.types import BundleHash, Fragment, TransactionHash, \
TransactionTrytes
TransactionTrytes, Nonce
from iota.types import Address, Hash, Tag, TryteString, TrytesCompatible, \
int_from_trits, trits_from_int

Expand Down Expand Up @@ -53,14 +53,18 @@ def from_tryte_string(cls, trytes, hash_=None):
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]),
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]),
nonce = Hash(tryte_string[2592:2673]),
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]),
)

def __init__(
Expand All @@ -69,16 +73,20 @@ def __init__(
signature_message_fragment,
address,
value,
tag,
timestamp,
current_index,
last_index,
bundle_hash,
trunk_transaction_hash,
branch_transaction_hash,
tag,
attachment_timestamp,
attachment_timestamp_lower_bound,
attachment_timestamp_upper_bound,
nonce,
legacy_tag = None
):
# type: (Optional[TransactionHash], Optional[Fragment], Address, int, Optional[Tag], int, Optional[int], Optional[int], Optional[BundleHash], Optional[TransactionHash], Optional[TransactionHash], Optional[Hash]) -> None
# type: (Optional[TransactionHash], Optional[Fragment], Address, int, int, Optional[int], Optional[int], Optional[BundleHash], Optional[TransactionHash], Optional[TransactionHash], Optional[Tag], Optional[int], Optional[int], Optional[int] Optional[Hash]) -> None
self.hash = hash_ # type: Optional[TransactionHash]
"""
Transaction ID, generated by taking a hash of the transaction
Expand All @@ -104,12 +112,12 @@ def __init__(
Can be negative (i.e., for spending inputs).
"""

self.tag = tag # type: Optional[Tag]
self._legacy_tag = legacy_tag # type: Optional[Tag]
"""
Optional classification tag applied to this transaction.
Optional classification legacy_tag applied to this transaction.
"""

self.nonce = nonce # type: Optional[Hash]
self.nonce = nonce # type: Optional[Nonce]
"""
Unique value used to increase security of the transaction hash.
"""
Expand Down Expand Up @@ -154,6 +162,17 @@ def __init__(

The branch transaction generally has no significance.
"""

self.tag = tag # type: Optional[Tag]
"""
Optional classification tag applied to this transaction.
"""

self.attachment_timestamp = attachment_timestamp # type: int

self.attachment_timestamp_lower_bound = attachment_timestamp_lower_bound # type: int

self.attachment_timestamp_upper_bound = attachment_timestamp_upper_bound # type: int

self.signature_message_fragment = signature_message_fragment # type: Optional[Fragment]
"""
Expand Down Expand Up @@ -227,6 +246,36 @@ def last_index_as_trytes(self):
"""
# Note that we are padding to 27 _trits_.
return TryteString.from_trits(trits_from_int(self.last_index, pad=27))

@property
def attachment_timestamp_as_trytes(self):
# type: () -> TryteString
"""
Returns a TryteString representation of the transaction's
attachment timestamp.
"""
#Note that we are padding to 27 _trits_.
return TryteString.from_trits(trits_from_int(self.attachment_timestamp, pad=27))

@property
def attachment_timestamp_lower_bound_as_trytes(self):
# type: () -> TryteString
"""
Returns a TryteString representation of the transaction's
attachment timestamp lower bound.
"""
#Note that we are padding to 27 _trits_.
return TryteString.from_trits(trits_from_int(self.attachment_timestamp_lower_bound, pad=27))

@property
def attachment_timestamp_upper_bound_as_trytes(self):
# type: () -> TryteString
"""
Returns a TryteString representation of the transaction's
attachment timestamp upper bound.
"""
#Note that we are padding to 27 _trits_.
return TryteString.from_trits(trits_from_int(self.attachment_timestamp_upper_bound, pad=27))

def as_json_compatible(self):
# type: () -> dict
Expand All @@ -237,18 +286,22 @@ def as_json_compatible(self):
- :py:class:`iota.json.JsonEncoder`.
"""
return {
'hash_': self.hash,
'signature_message_fragment': self.signature_message_fragment,
'address': self.address,
'value': self.value,
'tag': self.tag,
'timestamp': self.timestamp,
'current_index': self.current_index,
'last_index': self.last_index,
'bundle_hash': self.bundle_hash,
'trunk_transaction_hash': self.trunk_transaction_hash,
'branch_transaction_hash': self.branch_transaction_hash,
'nonce': self.nonce,
'hash_': self.hash,
'signature_message_fragment': self.signature_message_fragment,
'address': self.address,
'value': self.value,
'legacy_tag': self.legacy_tag,
'timestamp': self.timestamp,
'current_index': self.current_index,
'last_index': self.last_index,
'bundle_hash': self.bundle_hash,
'trunk_transaction_hash': self.trunk_transaction_hash,
'branch_transaction_hash': self.branch_transaction_hash,
'tag': self.tag,
'attachment_timestamp': self.attachment_timestamp,
'attachment_timestamp_lower_bound': self.attachment_timestamp_lower_bound,
'attachment_timestamp_upper_bound': self.attachment_timestamp_upper_bound,
'nonce': self.nonce,
}

def as_tryte_string(self):
Expand All @@ -260,13 +313,17 @@ def as_tryte_string(self):
self.signature_message_fragment
+ self.address.address
+ self.value_as_trytes
+ self.tag
+ self.legacy_tag
+ self.timestamp_as_trytes
+ self.current_index_as_trytes
+ self.last_index_as_trytes
+ self.bundle_hash
+ self.trunk_transaction_hash
+ self.branch_transaction_hash
+ self.tag
+ self.attachment_timestamp_as_trytes
+ self.attachment_timestamp_lower_bound_as_trytes
+ self.attachment_timestamp_upper_bound_as_trytes
+ self.nonce
)

Expand All @@ -279,11 +336,20 @@ def get_signature_validation_trytes(self):
return (
self.address.address
+ self.value_as_trytes
+ self.tag
+ self.legacy_tag
+ self.timestamp_as_trytes
+ self.current_index_as_trytes
+ self.last_index_as_trytes
)

@property
def legacy_tag(self):
# type: () -> Tag
"""
Return the legacy tag of the transaction.
If no legacy tag was set, returns the tag instead.
"""
return self._legacy_tag or self.tag


class Bundle(JsonSerializable, Sequence[Transaction]):
Expand Down
29 changes: 16 additions & 13 deletions iota/transaction/creation.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from iota.crypto.types import PrivateKey
from iota.exceptions import with_context
from iota.transaction.base import Bundle, Transaction
from iota.transaction.types import BundleHash, Fragment, TransactionHash
from iota.transaction.types import BundleHash, Fragment, TransactionHash, Nonce
from iota.transaction.utils import get_current_timestamp
from iota.types import Address, Hash, Tag, TryteString

Expand All @@ -36,23 +36,26 @@ def __init__(self, address, value, tag=None, message=None, timestamp=None):
timestamp = get_current_timestamp()

super(ProposedTransaction, self).__init__(
address = address,
tag = Tag(b'') if tag is None else tag,
timestamp = timestamp,
value = value,
address = address,
tag = Tag(b'') if tag is None else tag,
timestamp = timestamp,
value = value,

# These values will be populated when the bundle is finalized.
bundle_hash = None,
current_index = None,
hash_ = None,
last_index = None,
signature_message_fragment = None,
bundle_hash = None,
current_index = None,
hash_ = None,
last_index = None,
signature_message_fragment = None,
attachment_timestamp = 0,
attachment_timestamp_lower_bound = 0,
attachment_timestamp_upper_bound = 0,

# These values start out empty; they will be populated when the
# node does PoW.
branch_transaction_hash = TransactionHash(b''),
nonce = Hash(b''),
trunk_transaction_hash = TransactionHash(b''),
branch_transaction_hash = TransactionHash(b''),
nonce = Nonce(b''),
trunk_transaction_hash = TransactionHash(b''),
)

self.message = TryteString(b'') if message is None else message
Expand Down
23 changes: 23 additions & 0 deletions iota/transaction/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
'Fragment',
'TransactionHash',
'TransactionTrytes',
'Nonce'
]


Expand Down Expand Up @@ -72,3 +73,25 @@ def __init__(self, trytes):
'trytes': trytes,
},
)

class Nonce(TryteString):
"""
A TryteString that acts as a transaction nonce.
"""
LEN = 27

def __init__(self, trytes):
# type: (TrytesCompatible) -> None
super(Nonce, self).__init__(trytes, pad=self.LEN)

if len(self._trytes) > self.LEN:
raise with_context(
exc = ValueError('{cls} values must be {len} trytes long.'.format(
cls = type(self).__name__,
len = self.LEN
)),

context = {
'trytes': trytes,
},
)
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
name = 'PyOTA',
description = 'IOTA API library for Python',
url = 'https://github.com/iotaledger/iota.lib.py',
version = '2.0.0b2',
version = '2.0.0',

long_description = long_description,

Expand Down Expand Up @@ -66,7 +66,7 @@
license = 'MIT',

classifiers = [
'Development Status :: 4 - Beta',
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Programming Language :: Python :: 2',
Expand Down
Loading