Skip to content
Snippets Groups Projects
Commit 676b1099 authored by Vincent Texier's avatar Vincent Texier
Browse files

Merge branch 'transaction' into 'dev'

Several transaction enhancements, other improvements

See merge request clients/python/duniterpy!56
parents 3a1e5d61 4db793ba
No related branches found
No related tags found
1 merge request!56Several transaction enhancements, other improvements
Pipeline #5330 passed
...@@ -37,8 +37,21 @@ push_to_github: ...@@ -37,8 +37,21 @@ push_to_github:
- eval "$(pyenv init -)" - eval "$(pyenv init -)"
- pyenv shell $PYENV_PYTHON_VERSION - pyenv shell $PYENV_PYTHON_VERSION
.changes: &changes
except:
changes:
- CHANGELOG.md
- ci/*
- config
- docs
- LICENSE*
- Makefile
- README*
- release.sh
build: &build build: &build
<<: *pyenv <<: *pyenv
<<: *changes
stage: build stage: build
script: script:
- pip install -r requirements.txt - pip install -r requirements.txt
...@@ -47,6 +60,7 @@ build: &build ...@@ -47,6 +60,7 @@ build: &build
test: test:
<<: *pyenv <<: *pyenv
<<: *changes
stage: test stage: test
script: script:
- pip install coveralls - pip install coveralls
...@@ -55,6 +69,7 @@ test: ...@@ -55,6 +69,7 @@ test:
mypy: mypy:
<<: *pyenv <<: *pyenv
<<: *changes
stage: test stage: test
script: script:
- pip install -r requirements_dev.txt - pip install -r requirements_dev.txt
......
## v0.54.0 (XX April 2019)
### Code/tests
- Fix OutputSource and InputSource from_inline() regex matching
- Transaction document: tests and code: drop versions 2 and 3 management
- Block document: code: drop vensions 2 and 3 management
- Block document: Upgrade blocks to v11 and TX to v10
- Add OutputSource.inline_condition() method
### Other
- CI: Do not trigger build, tests, type check on modification of non-relevant files
- Makefile: use python3 module to run tests and type check
- Add coveralls as dev dependency
- setup.py: add classifiers: Python versions, Intended Audience
- Add CHANGELOG.md from v0.53.1
- Thanks @Moul, @vtexier
## v0.53.1 (18 April 2019)
- Implement equality `__eq__()` and `__hash__()` methods for InputSource and OutputSource classes
Thanks @Moul, @vtexier
## v0.53.0 (30 March 2019)
- To be completed…
...@@ -6,8 +6,8 @@ docs: ...@@ -6,8 +6,8 @@ docs:
# run tests # run tests
tests: tests:
python -m unittest ${test_filter} python3 -m unittest ${TESTS_FILTER}
# check static typing # check static typing
check: check:
mypy duniterpy --ignore-missing-imports python3 -m mypy duniterpy --ignore-missing-imports
...@@ -69,9 +69,9 @@ Development ...@@ -69,9 +69,9 @@ Development
make tests make tests
* Run only some unit tests with:: * Run only some unit tests by passing a special ENV variable::
make tests test_filter=tests.documents.test_block.TestBlock.test_fromraw make tests TESTS_FILTER=tests.documents.test_block.TestBlock.test_fromraw
Documentation Documentation
------------- -------------
......
...@@ -75,8 +75,6 @@ The class Block handles Block documents. ...@@ -75,8 +75,6 @@ The class Block handles Block documents.
re_previoushash = re.compile("PreviousHash: ({block_hash_regex})\n".format(block_hash_regex=BLOCK_HASH_REGEX)) re_previoushash = re.compile("PreviousHash: ({block_hash_regex})\n".format(block_hash_regex=BLOCK_HASH_REGEX))
re_previousissuer = re.compile("PreviousIssuer: ({pubkey_regex})\n".format(pubkey_regex=PUBKEY_REGEX)) re_previousissuer = re.compile("PreviousIssuer: ({pubkey_regex})\n".format(pubkey_regex=PUBKEY_REGEX))
re_parameters = re.compile("Parameters: ([0-9]+\\.[0-9]+):([0-9]+):([0-9]+):([0-9]+):([0-9]+):([0-9]+):\ re_parameters = re.compile("Parameters: ([0-9]+\\.[0-9]+):([0-9]+):([0-9]+):([0-9]+):([0-9]+):([0-9]+):\
([0-9]+):([0-9]+):([0-9]+\\.[0-9]+):([0-9]+):([0-9]+):([0-9]+):([0-9]+):([0-9]+):([0-9]+):([0-9]+\\.[0-9]+)\n")
re_parameters_v10 = re.compile("Parameters: ([0-9]+\\.[0-9]+):([0-9]+):([0-9]+):([0-9]+):([0-9]+):([0-9]+):\
([0-9]+):([0-9]+):([0-9]+):([0-9]+):([0-9]+\\.[0-9]+):([0-9]+):([0-9]+):([0-9]+):([0-9]+):([0-9]+):([0-9]+\\.[0-9]+):\ ([0-9]+):([0-9]+):([0-9]+):([0-9]+):([0-9]+\\.[0-9]+):([0-9]+):([0-9]+):([0-9]+):([0-9]+):([0-9]+):([0-9]+\\.[0-9]+):\
([0-9]+):([0-9]+):([0-9]+)\n") ([0-9]+):([0-9]+):([0-9]+)\n")
re_memberscount = re.compile("MembersCount: ([0-9]+)\n") re_memberscount = re.compile("MembersCount: ([0-9]+)\n")
...@@ -252,24 +250,18 @@ The class Block handles Block documents. ...@@ -252,24 +250,18 @@ The class Block handles Block documents.
ud = int(Block.parse_field("UD", lines[n])) ud = int(Block.parse_field("UD", lines[n]))
n += 1 n += 1
if version >= 3 or ud:
unit_base = int(Block.parse_field("UnitBase", lines[n])) unit_base = int(Block.parse_field("UnitBase", lines[n]))
n += 1 n += 1
issuer = Block.parse_field("Issuer", lines[n]) issuer = Block.parse_field("Issuer", lines[n])
n += 1 n += 1
if version >= 3:
issuers_frame = Block.parse_field("IssuersFrame", lines[n]) issuers_frame = Block.parse_field("IssuersFrame", lines[n])
n += 1 n += 1
issuers_frame_var = Block.parse_field("IssuersFrameVar", lines[n]) issuers_frame_var = Block.parse_field("IssuersFrameVar", lines[n])
n += 1 n += 1
different_issuers_count = Block.parse_field("DifferentIssuersCount", lines[n]) different_issuers_count = Block.parse_field("DifferentIssuersCount", lines[n])
n += 1 n += 1
else:
issuers_frame = None
issuers_frame_var = None
different_issuers_count = None
prev_hash = None prev_hash = None
prev_issuer = None prev_issuer = None
...@@ -283,12 +275,6 @@ The class Block handles Block documents. ...@@ -283,12 +275,6 @@ The class Block handles Block documents.
parameters = None parameters = None
if number == 0: if number == 0:
try: try:
if version >= 10:
params_match = Block.re_parameters_v10.match(lines[n])
if params_match is None:
raise MalformedDocumentError("Parameters")
parameters = params_match.groups()
else:
params_match = Block.re_parameters.match(lines[n]) params_match = Block.re_parameters.match(lines[n])
if params_match is None: if params_match is None:
raise MalformedDocumentError("Parameters") raise MalformedDocumentError("Parameters")
...@@ -374,12 +360,7 @@ The class Block handles Block documents. ...@@ -374,12 +360,7 @@ The class Block handles Block documents.
unlocks_num = int(header_data.group(4)) unlocks_num = int(header_data.group(4))
outputs_num = int(header_data.group(5)) outputs_num = int(header_data.group(5))
has_comment = int(header_data.group(6)) has_comment = int(header_data.group(6))
if version > 2:
if tx_version <= 2:
raise MalformedDocumentError("TX document is using wrong version")
sup_lines = 2 sup_lines = 2
else:
sup_lines = 1
tx_max = n + sup_lines + issuers_num * 2 + inputs_num + unlocks_num + outputs_num + has_comment tx_max = n + sup_lines + issuers_num * 2 + inputs_num + unlocks_num + outputs_num + has_comment
for i in range(n, tx_max): for i in range(n, tx_max):
tx_lines += lines[n] tx_lines += lines[n]
...@@ -419,12 +400,10 @@ MedianTime: {mediantime} ...@@ -419,12 +400,10 @@ MedianTime: {mediantime}
if self.ud: if self.ud:
doc += "UniversalDividend: {0}\n".format(self.ud) doc += "UniversalDividend: {0}\n".format(self.ud)
if self.version >= 3 or self.ud:
doc += "UnitBase: {0}\n".format(self.unit_base) doc += "UnitBase: {0}\n".format(self.unit_base)
doc += "Issuer: {0}\n".format(self.issuer) doc += "Issuer: {0}\n".format(self.issuer)
if self.version >= 3:
doc += """IssuersFrame: {0} doc += """IssuersFrame: {0}
IssuersFrameVar: {1} IssuersFrameVar: {1}
DifferentIssuersCount: {2} DifferentIssuersCount: {2}
......
...@@ -56,22 +56,22 @@ class BlockUID: ...@@ -56,22 +56,22 @@ class BlockUID:
def __lt__(self, other: object) -> bool: def __lt__(self, other: object) -> bool:
if not isinstance(other, BlockUID): if not isinstance(other, BlockUID):
return False return NotImplemented
return self.number < other.number return self.number < other.number
def __gt__(self, other: object) -> bool: def __gt__(self, other: object) -> bool:
if not isinstance(other, BlockUID): if not isinstance(other, BlockUID):
return False return NotImplemented
return self.number > other.number return self.number > other.number
def __le__(self, other: object) -> bool: def __le__(self, other: object) -> bool:
if not isinstance(other, BlockUID): if not isinstance(other, BlockUID):
return False return NotImplemented
return self.number <= other.number return self.number <= other.number
def __ge__(self, other: object) -> bool: def __ge__(self, other: object) -> bool:
if not isinstance(other, BlockUID): if not isinstance(other, BlockUID):
return False return NotImplemented
return self.number >= other.number return self.number >= other.number
def __hash__(self) -> int: def __hash__(self) -> int:
......
...@@ -44,8 +44,6 @@ class Document: ...@@ -44,8 +44,6 @@ class Document:
:param currency: Name of the currency :param currency: Name of the currency
:param signatures: List of signatures :param signatures: List of signatures
""" """
if version < 2:
raise MalformedDocumentError("Version 1 documents are not handled by duniterpy>0.2")
self.version = version self.version = version
self.currency = currency self.currency = currency
if signatures: if signatures:
......
...@@ -50,13 +50,8 @@ class InputSource: ...@@ -50,13 +50,8 @@ class InputSource:
""" """
re_inline = re.compile( re_inline = re.compile(
"(?:(?:(D):({pubkey_regex}):({block_id_regex}))|(?:(T):({transaction_hash_regex}):([0-9]+)))\n" "([0-9]+):([0-9]):(?:(?:(D):({pubkey_regex}):({block_id_regex}))|(?:(T):({transaction_hash_regex}):\
.format(pubkey_regex=PUBKEY_REGEX, ([0-9]+)))"
block_id_regex=BLOCK_ID_REGEX,
transaction_hash_regex=TRANSACTION_HASH_REGEX))
re_inline_v3 = re.compile(
"([0-9]+):([0-9]+):(?:(?:(D):({pubkey_regex}):({block_id_regex}))|(?:(T):({transaction_hash_regex}):\
([0-9]+)))\n"
.format(pubkey_regex=PUBKEY_REGEX, .format(pubkey_regex=PUBKEY_REGEX,
block_id_regex=BLOCK_ID_REGEX, block_id_regex=BLOCK_ID_REGEX,
transaction_hash_regex=TRANSACTION_HASH_REGEX)) transaction_hash_regex=TRANSACTION_HASH_REGEX))
...@@ -94,23 +89,14 @@ class InputSource: ...@@ -94,23 +89,14 @@ class InputSource:
return hash((self.amount, self.base, self.source, self.origin_id, self.index)) return hash((self.amount, self.base, self.source, self.origin_id, self.index))
@classmethod @classmethod
def from_inline(cls: Type[InputSourceType], tx_version: int, inline: str) -> InputSourceType: def from_inline(cls: Type[InputSourceType], inline: str) -> InputSourceType:
""" """
Return Transaction instance from inline string format Return Transaction instance from inline string format
:param tx_version: Version number of the document
:param inline: Inline string format :param inline: Inline string format
:return: :return:
""" """
if tx_version == 2:
data = InputSource.re_inline.match(inline) data = InputSource.re_inline.match(inline)
if data is None:
raise MalformedDocumentError("Inline input")
source_offset = 0
amount = 0
base = 0
else:
data = InputSource.re_inline_v3.match(inline)
if data is None: if data is None:
raise MalformedDocumentError("Inline input") raise MalformedDocumentError("Inline input")
source_offset = 2 source_offset = 2
...@@ -127,18 +113,12 @@ class InputSource: ...@@ -127,18 +113,12 @@ class InputSource:
return cls(amount, base, source, origin_id, index) return cls(amount, base, source, origin_id, index)
def inline(self, tx_version: int) -> str: def inline(self) -> str:
""" """
Return an inline string format of the document Return an inline string format of the document
:param tx_version: Version number of the document
:return: :return:
""" """
if tx_version == 2:
return "{0}:{1}:{2}".format(self.source,
self.origin_id,
self.index)
else:
return "{0}:{1}:{2}:{3}:{4}".format(self.amount, return "{0}:{1}:{2}:{3}:{4}".format(self.amount,
self.base, self.base,
self.source, self.source,
...@@ -154,7 +134,7 @@ class OutputSource: ...@@ -154,7 +134,7 @@ class OutputSource:
""" """
A Transaction OUTPUT A Transaction OUTPUT
""" """
re_inline = re.compile("([0-9]+):([0-9]+):(.*)\n") re_inline = re.compile("([0-9]+):([0-9]):(.*)")
def __init__(self, amount: int, base: int, condition: str) -> None: def __init__(self, amount: int, base: int, condition: str) -> None:
""" """
...@@ -200,13 +180,21 @@ class OutputSource: ...@@ -200,13 +180,21 @@ class OutputSource:
def inline(self) -> str: def inline(self) -> str:
""" """
Return an inline string format of the document Return an inline string format of the output source
:return: :return:
""" """
return "{0}:{1}:{2}".format(self.amount, self.base, return "{0}:{1}:{2}".format(self.amount, self.base,
pypeg2.compose(self.condition, output.Condition)) pypeg2.compose(self.condition, output.Condition))
def inline_condition(self) -> str:
"""
Return an inline string format of the output source’s condition
:return:
"""
return pypeg2.compose(self.condition, output.Condition)
@staticmethod @staticmethod
def condition_from_text(text) -> Condition: def condition_from_text(text) -> Condition:
""" """
...@@ -557,8 +545,6 @@ Comment: {comment} ...@@ -557,8 +545,6 @@ Comment: {comment}
locktime = int(header_data.group(7)) locktime = int(header_data.group(7))
n += 1 n += 1
blockstamp = None # type: Optional[BlockUID]
if version >= 3:
blockstamp = BlockUID.from_str(Transaction.parse_field("CompactBlockstamp", lines[n])) blockstamp = BlockUID.from_str(Transaction.parse_field("CompactBlockstamp", lines[n]))
n += 1 n += 1
...@@ -573,7 +559,7 @@ Comment: {comment} ...@@ -573,7 +559,7 @@ Comment: {comment}
n += 1 n += 1
for i in range(0, inputs_num): for i in range(0, inputs_num):
input_source = InputSource.from_inline(version, lines[n]) input_source = InputSource.from_inline(lines[n])
inputs.append(input_source) inputs.append(input_source)
n += 1 n += 1
...@@ -651,7 +637,7 @@ Comment: {comment} ...@@ -651,7 +637,7 @@ Comment: {comment}
if Transaction.re_inputs.match(lines[n]): if Transaction.re_inputs.match(lines[n]):
n += 1 n += 1
while Transaction.re_unlocks.match(lines[n]) is None: while Transaction.re_unlocks.match(lines[n]) is None:
input_source = InputSource.from_inline(version, lines[n]) input_source = InputSource.from_inline(lines[n])
inputs.append(input_source) inputs.append(input_source)
n += 1 n += 1
...@@ -704,7 +690,7 @@ Currency: {1} ...@@ -704,7 +690,7 @@ Currency: {1}
doc += "Inputs:\n" doc += "Inputs:\n"
for i in self.inputs: for i in self.inputs:
doc += "{0}\n".format(i.inline(self.version)) doc += "{0}\n".format(i.inline())
doc += "Unlocks:\n" doc += "Unlocks:\n"
for u in self.unlocks: for u in self.unlocks:
...@@ -747,7 +733,7 @@ COMMENT ...@@ -747,7 +733,7 @@ COMMENT
for pubkey in self.issuers: for pubkey in self.issuers:
doc += "{0}\n".format(pubkey) doc += "{0}\n".format(pubkey)
for i in self.inputs: for i in self.inputs:
doc += "{0}\n".format(i.inline(self.version)) doc += "{0}\n".format(i.inline())
for u in self.unlocks: for u in self.unlocks:
doc += "{0}\n".format(u.inline()) doc += "{0}\n".format(u.inline())
for o in self.outputs: for o in self.outputs:
......
coveralls
mypy mypy
sphinx sphinx
sphinx_rtd_theme sphinx_rtd_theme
...@@ -63,13 +63,16 @@ setup( ...@@ -63,13 +63,16 @@ setup(
test_suite="tests", test_suite="tests",
classifiers=[ classifiers=[
"Programming Language :: Python",
"Development Status :: 5 - Production/Stable", "Development Status :: 5 - Production/Stable",
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)", "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
"Natural Language :: English", "Natural Language :: English",
"Operating System :: OS Independent", "Operating System :: OS Independent",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.5",
"Topic :: Software Development :: Libraries", "Topic :: Software Development :: Libraries",
"Intended Audience :: Developers",
], ],
install_requires=install_requires, install_requires=install_requires,
dependency_links=dependency_links dependency_links=dependency_links
......
...@@ -8,14 +8,18 @@ import unittest ...@@ -8,14 +8,18 @@ import unittest
from duniterpy.documents.block import Block from duniterpy.documents.block import Block
from duniterpy.documents.block_uid import BlockUID, block_uid from duniterpy.documents.block_uid import BlockUID, block_uid
raw_block = """Version: 2 raw_block = """Version: 11
Type: Block Type: Block
Currency: zeta_brouzouf Currency: zeta_brouzouf
Number: 15 Number: 15
PoWMin: 4 PoWMin: 4
Time: 1418083330 Time: 1418083330
MedianTime: 1418080208 MedianTime: 1418080208
UnitBase: 0
Issuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk Issuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk
IssuersFrame: 1
IssuersFrameVar: 0
DifferentIssuersCount: 0
PreviousHash: 0000E73C340601ACA1AD5AAA5B5E56B03E178EF8 PreviousHash: 0000E73C340601ACA1AD5AAA5B5E56B03E178EF8
PreviousIssuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk PreviousIssuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk
MembersCount: 4 MembersCount: 4
...@@ -32,14 +36,18 @@ Nonce: 45079 ...@@ -32,14 +36,18 @@ Nonce: 45079
42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r 42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r
""" """
raw_block_with_tx = """Version: 2 raw_block_with_tx = """Version: 11
Type: Block Type: Block
Currency: meta_brouzouf Currency: meta_brouzouf
Number: 34436 Number: 34436
PoWMin: 5 PoWMin: 5
Time: 1443896211 Time: 1443896211
MedianTime: 1443881811 MedianTime: 1443881811
UnitBase: 0
Issuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk Issuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk
IssuersFrame: 1
IssuersFrameVar: 0
DifferentIssuersCount: 0
PreviousHash: 000002B06C990DEBD5C1D947289C2CF4F4396FB2 PreviousHash: 000002B06C990DEBD5C1D947289C2CF4F4396FB2
PreviousIssuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk PreviousIssuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk
MembersCount: 19 MembersCount: 19
...@@ -54,26 +62,28 @@ Certifications: ...@@ -54,26 +62,28 @@ Certifications:
5ocqzyDMMWf1V8bsoNhWb1iNwax1e9M7VTUN6navs8of:ATkjQPa4sn4LBF69jqEPzFtRdHYJs6MJQjvP8JdN7MtN:0:6TuxRcARnpo13l3cXtgPTkjJlv8DZOUvsAzmZJMbjHZbbZfDQ6MJpH9DIuH0eyG3WGc0EX/046mbMGBrKKg9DQ== 5ocqzyDMMWf1V8bsoNhWb1iNwax1e9M7VTUN6navs8of:ATkjQPa4sn4LBF69jqEPzFtRdHYJs6MJQjvP8JdN7MtN:0:6TuxRcARnpo13l3cXtgPTkjJlv8DZOUvsAzmZJMbjHZbbZfDQ6MJpH9DIuH0eyG3WGc0EX/046mbMGBrKKg9DQ==
ATkjQPa4sn4LBF69jqEPzFtRdHYJs6MJQjvP8JdN7MtN:2qwGeLWoPG7db72bKXPfJpAtj67FYDnPaJn2JB7tyXxJ:0:LusTbb7CgwrqqacDKjtldw60swwvDBH8wVUIJN4SWRb2pZPJSpDxgqaGyjC5P9i/DendfyQWc7cfzPDqSZmZAg== ATkjQPa4sn4LBF69jqEPzFtRdHYJs6MJQjvP8JdN7MtN:2qwGeLWoPG7db72bKXPfJpAtj67FYDnPaJn2JB7tyXxJ:0:LusTbb7CgwrqqacDKjtldw60swwvDBH8wVUIJN4SWRb2pZPJSpDxgqaGyjC5P9i/DendfyQWc7cfzPDqSZmZAg==
Transactions: Transactions:
TX:2:1:3:3:1:0:0 TX:10:1:3:3:1:0:0
33363-000021C4B5BE2DA996F953DC09482F4FA2FA68774B1A38FAB03B2AAB4A08EBE0
HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY
T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:0 5200:0:T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:0
T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:10 500:0:T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:10
D:HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY:88 20:0:D:HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY:88
0:SIG(0) 0:SIG(0)
1:SIG(0) 1:SIG(0)
2:SIG(0) 2:SIG(0)
30:2:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g) 30:2:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)
42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r 42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r
TX:2:3:6:6:3:1:0 TX:10:3:6:6:3:1:0
33363-000021C4B5BE2DA996F953DC09482F4FA2FA68774B1A38FAB03B2AAB4A08EBE0
HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY
CYYjHsNyg3HMRMpTHqCJAN9McjH5BwFLmDKGV3PmCuKp CYYjHsNyg3HMRMpTHqCJAN9McjH5BwFLmDKGV3PmCuKp
9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB 9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB
T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:2 78900:0:T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:2
T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:8 700:0:T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:8
D:HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY:46 8900:0:D:HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY:46
T:A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956:3 780:0:T:A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956:3
T:67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B:5 780:0:T:67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B:5
D:9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB:46 8900:0:D:9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB:46
0:SIG(0) 0:SIG(0)
1:XHX(7665798292) 1:XHX(7665798292)
2:SIG(0) 2:SIG(0)
...@@ -92,7 +102,7 @@ Nonce: 581 ...@@ -92,7 +102,7 @@ Nonce: 581
nY/MsFU2luiohLmSiOOimL1RIqbriOBgc22ua03Z2dhxtSJxKZeGNGDvl1jaXgmEBRnXU87yXbZ7ioOS/AAVCA== nY/MsFU2luiohLmSiOOimL1RIqbriOBgc22ua03Z2dhxtSJxKZeGNGDvl1jaXgmEBRnXU87yXbZ7ioOS/AAVCA==
""" """
raw_block_zero = """Version: 10 raw_block_zero = """Version: 11
Type: Block Type: Block
Currency: zeta_brouzouf Currency: zeta_brouzouf
Number: 0 Number: 0
...@@ -139,14 +149,18 @@ Nonce: 2125 ...@@ -139,14 +149,18 @@ Nonce: 2125
42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r 42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r
""" """
raw_block_with_leavers = """Version: 2 raw_block_with_leavers = """Version: 11
Type: Block Type: Block
Currency: meta_brouzouf Currency: meta_brouzouf
Number: 34895 Number: 34895
PoWMin: 4 PoWMin: 4
Time: 1444434128 Time: 1444434128
MedianTime: 1444426438 MedianTime: 1444426438
UnitBase: 0
Issuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk Issuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk
IssuersFrame: 1
IssuersFrameVar: 0
DifferentIssuersCount: 0
PreviousHash: 0000E88115ADDF79344372C0212928501E21622B PreviousHash: 0000E88115ADDF79344372C0212928501E21622B
PreviousIssuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk PreviousIssuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk
MembersCount: 21 MembersCount: 21
...@@ -164,7 +178,7 @@ Nonce: 9906 ...@@ -164,7 +178,7 @@ Nonce: 9906
5LZCFSnm5FkFihPBTpmsPyILEdvu8MXfJOp6OR4d1s+/e2jVWg4J6YSDfO2KBBPgubASyr2QwQuiBlYD2918Bw== 5LZCFSnm5FkFihPBTpmsPyILEdvu8MXfJOp6OR4d1s+/e2jVWg4J6YSDfO2KBBPgubASyr2QwQuiBlYD2918Bw==
""" """
raw_block_with_excluded = """Version: 3 raw_block_with_excluded = """Version: 11
Type: Block Type: Block
Currency: test_net Currency: test_net
Number: 33365 Number: 33365
...@@ -189,7 +203,7 @@ Excluded: ...@@ -189,7 +203,7 @@ Excluded:
2VAxjr8QoJtSzhE7APno4AkR2RAQNySpNNvDzMgPotSF 2VAxjr8QoJtSzhE7APno4AkR2RAQNySpNNvDzMgPotSF
Certifications: Certifications:
Transactions: Transactions:
TX:3:1:4:4:12:1:0 TX:10:1:4:4:12:1:0
33363-000021C4B5BE2DA996F953DC09482F4FA2FA68774B1A38FAB03B2AAB4A08EBE0 33363-000021C4B5BE2DA996F953DC09482F4FA2FA68774B1A38FAB03B2AAB4A08EBE0
TENGx7WtzFsTXwnbrPEvb6odX2WnqYcnnrjiiLvp1mS TENGx7WtzFsTXwnbrPEvb6odX2WnqYcnnrjiiLvp1mS
5:0:T:D25272F1D778B52798B7A51CF0CE21F7C5812F841374508F4367872D4A47F0F7:0 5:0:T:D25272F1D778B52798B7A51CF0CE21F7C5812F841374508F4367872D4A47F0F7:0
...@@ -219,7 +233,7 @@ Nonce: 137387 ...@@ -219,7 +233,7 @@ Nonce: 137387
GmgYhWrwCtsK7t2B/omPpxZ8EfJgv9UYzJIFo++Za+A0Mo70xRfZG7kywxbQTTxDk/V7r90P946N89vdVjv1Bg== GmgYhWrwCtsK7t2B/omPpxZ8EfJgv9UYzJIFo++Za+A0Mo70xRfZG7kywxbQTTxDk/V7r90P946N89vdVjv1Bg==
""" """
negative_issuers_frame_var = """Version: 3 negative_issuers_frame_var = """Version: 11
Type: Block Type: Block
Currency: test_net Currency: test_net
Number: 34662 Number: 34662
...@@ -242,7 +256,7 @@ Revoked: ...@@ -242,7 +256,7 @@ Revoked:
Excluded: Excluded:
Certifications: Certifications:
Transactions: Transactions:
TX:3:1:4:4:2:1:0 TX:10:1:4:4:2:1:0
34660-00001EEB3FDCEB2F9F39F931ED8F6D419C4C64B4D3F7EA52C35FB6B07A085664 34660-00001EEB3FDCEB2F9F39F931ED8F6D419C4C64B4D3F7EA52C35FB6B07A085664
5ocqzyDMMWf1V8bsoNhWb1iNwax1e9M7VTUN6navs8of 5ocqzyDMMWf1V8bsoNhWb1iNwax1e9M7VTUN6navs8of
765201:3:T:636150D38D565DA0B9717E93C2AD8D6270FA032BF963360ECFCDD55F44493F08:1 765201:3:T:636150D38D565DA0B9717E93C2AD8D6270FA032BF963360ECFCDD55F44493F08:1
...@@ -266,7 +280,7 @@ WnJvw204wccmSBQK9UE2rCFw0EG34zf+b58n2KTLwSIhTpgmGsnr5ohkSyYZYcLEKjisLXKNCmMl7D1Q ...@@ -266,7 +280,7 @@ WnJvw204wccmSBQK9UE2rCFw0EG34zf+b58n2KTLwSIhTpgmGsnr5ohkSyYZYcLEKjisLXKNCmMl7D1Q
class TestBlock(unittest.TestCase): class TestBlock(unittest.TestCase):
def test_fromraw(self): def test_fromraw(self):
block = Block.from_signed_raw(raw_block) block = Block.from_signed_raw(raw_block)
self.assertEqual(block.version, 2) self.assertEqual(block.version, 11)
self.assertEqual(block.currency, "zeta_brouzouf") self.assertEqual(block.currency, "zeta_brouzouf")
self.assertEqual(block.noonce, 45079) self.assertEqual(block.noonce, 45079)
self.assertEqual(block.number, 15) self.assertEqual(block.number, 15)
...@@ -287,7 +301,7 @@ class TestBlock(unittest.TestCase): ...@@ -287,7 +301,7 @@ class TestBlock(unittest.TestCase):
def test_from_signed_raw_block_zero(self): def test_from_signed_raw_block_zero(self):
block = Block.from_signed_raw(raw_block_zero) block = Block.from_signed_raw(raw_block_zero)
self.assertEqual(block.version, 10) self.assertEqual(block.version, 11)
self.assertEqual(block.currency, "zeta_brouzouf") self.assertEqual(block.currency, "zeta_brouzouf")
self.assertEqual(block.noonce, 2125) self.assertEqual(block.noonce, 2125)
self.assertEqual(block.number, 0) self.assertEqual(block.number, 0)
...@@ -315,7 +329,7 @@ class TestBlock(unittest.TestCase): ...@@ -315,7 +329,7 @@ class TestBlock(unittest.TestCase):
rendered_raw = block.signed_raw() rendered_raw = block.signed_raw()
from_rendered_raw = Block.from_signed_raw(rendered_raw) from_rendered_raw = Block.from_signed_raw(rendered_raw)
self.assertEqual(from_rendered_raw.version, 2) self.assertEqual(from_rendered_raw.version, 11)
self.assertEqual(from_rendered_raw.currency, "zeta_brouzouf") self.assertEqual(from_rendered_raw.currency, "zeta_brouzouf")
self.assertEqual(from_rendered_raw.noonce, 45079) self.assertEqual(from_rendered_raw.noonce, 45079)
self.assertEqual(from_rendered_raw.number, 15) self.assertEqual(from_rendered_raw.number, 15)
...@@ -341,7 +355,7 @@ class TestBlock(unittest.TestCase): ...@@ -341,7 +355,7 @@ class TestBlock(unittest.TestCase):
rendered_raw = block.signed_raw() rendered_raw = block.signed_raw()
from_rendered_raw = block.from_signed_raw(rendered_raw) from_rendered_raw = block.from_signed_raw(rendered_raw)
self.assertEqual(from_rendered_raw.version, 10) self.assertEqual(from_rendered_raw.version, 11)
self.assertEqual(from_rendered_raw.currency, "zeta_brouzouf") self.assertEqual(from_rendered_raw.currency, "zeta_brouzouf")
self.assertEqual(from_rendered_raw.noonce, 2125) self.assertEqual(from_rendered_raw.noonce, 2125)
self.assertEqual(from_rendered_raw.number, 0) self.assertEqual(from_rendered_raw.number, 0)
...@@ -365,7 +379,7 @@ class TestBlock(unittest.TestCase): ...@@ -365,7 +379,7 @@ class TestBlock(unittest.TestCase):
rendered_raw = block.signed_raw() rendered_raw = block.signed_raw()
from_rendered_raw = block.from_signed_raw(rendered_raw) from_rendered_raw = block.from_signed_raw(rendered_raw)
self.assertEqual(from_rendered_raw.version, 2) self.assertEqual(from_rendered_raw.version, 11)
self.assertEqual(from_rendered_raw.currency, "meta_brouzouf") self.assertEqual(from_rendered_raw.currency, "meta_brouzouf")
self.assertEqual(from_rendered_raw.noonce, 581) self.assertEqual(from_rendered_raw.noonce, 581)
self.assertEqual(from_rendered_raw.number, 34436) self.assertEqual(from_rendered_raw.number, 34436)
...@@ -389,7 +403,7 @@ class TestBlock(unittest.TestCase): ...@@ -389,7 +403,7 @@ class TestBlock(unittest.TestCase):
block = Block.from_signed_raw(raw_block_with_leavers) block = Block.from_signed_raw(raw_block_with_leavers)
rendered_raw = block.signed_raw() rendered_raw = block.signed_raw()
from_rendered_raw = block.from_signed_raw(rendered_raw) from_rendered_raw = block.from_signed_raw(rendered_raw)
self.assertEqual(from_rendered_raw.version, 2) self.assertEqual(from_rendered_raw.version, 11)
self.assertEqual(from_rendered_raw.currency, "meta_brouzouf") self.assertEqual(from_rendered_raw.currency, "meta_brouzouf")
self.assertEqual(from_rendered_raw.noonce, 9906) self.assertEqual(from_rendered_raw.noonce, 9906)
self.assertEqual(from_rendered_raw.number, 34895) self.assertEqual(from_rendered_raw.number, 34895)
...@@ -452,7 +466,7 @@ class TestBlock(unittest.TestCase): ...@@ -452,7 +466,7 @@ class TestBlock(unittest.TestCase):
self.fail("Empty blockuid __nonzero__ comparison failed") self.fail("Empty blockuid __nonzero__ comparison failed")
def test_proof_of_work(self): def test_proof_of_work(self):
block = """Version: 5 block = """Version: 11
Type: Block Type: Block
Currency: test_net Currency: test_net
Number: 60803 Number: 60803
......
...@@ -6,7 +6,7 @@ Created on 12 déc. 2014 ...@@ -6,7 +6,7 @@ Created on 12 déc. 2014
import unittest import unittest
import pypeg2 import pypeg2
from duniterpy.grammars import output from duniterpy.grammars import output
from duniterpy.documents.transaction import Transaction, reduce_base, SimpleTransaction from duniterpy.documents.transaction import Transaction, reduce_base, SimpleTransaction, InputSource, OutputSource
compact_change = """TX:10:1:1:1:1:1:0 compact_change = """TX:10:1:1:1:1:1:0
13410-000041DF0CCA173F09B5FBA48F619D4BC934F12ADF1D0B798639EB2149C4A8CC 13410-000041DF0CCA173F09B5FBA48F619D4BC934F12ADF1D0B798639EB2149C4A8CC
...@@ -35,16 +35,17 @@ Comment: XHX for pubkey DCYELkvV1aAsxFv58SbfRerHy5giJwKA1i4ZKTTcVGZe ...@@ -35,16 +35,17 @@ Comment: XHX for pubkey DCYELkvV1aAsxFv58SbfRerHy5giJwKA1i4ZKTTcVGZe
GXGephqTSJfb+8xsG/UMKRW0y+edL4RoMHM+OlgFq1aYOuaQ3/CtBKVSA01n2mkI7zwepeIABSjS94iVH4vZDg== GXGephqTSJfb+8xsG/UMKRW0y+edL4RoMHM+OlgFq1aYOuaQ3/CtBKVSA01n2mkI7zwepeIABSjS94iVH4vZDg==
""" """
tx_compact = """TX:2:3:6:6:3:1:0 tx_compact = """TX:10:3:6:6:3:1:0
13410-000041DF0CCA173F09B5FBA48F619D4BC934F12ADF1D0B798639EB2149C4A8CC
HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY
CYYjHsNyg3HMRMpTHqCJAN9McjH5BwFLmDKGV3PmCuKp CYYjHsNyg3HMRMpTHqCJAN9McjH5BwFLmDKGV3PmCuKp
9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB 9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB
T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:2 230:2:T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:2
T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:8 2230:2:T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:8
D:HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY:46 2430:2:D:HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY:46
T:A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956:3 2310:2:T:A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956:3
T:67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B:5 30:2:T:67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B:5
D:9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB:46 2330:2:D:9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB:46
0:SIG(0) 0:SIG(0)
1:XHX(7665798292) 1:XHX(7665798292)
2:SIG(0) 2:SIG(0)
...@@ -60,48 +61,17 @@ D:9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB:46 ...@@ -60,48 +61,17 @@ D:9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB:46
2XiBDpuUdu6zCPWGzHXXy8c4ATSscfFQG9DjmqMZUxDZVt1Dp4m2N5oHYVUfoPdrU9SLk4qxi65RNrfCVnvQtQJk 2XiBDpuUdu6zCPWGzHXXy8c4ATSscfFQG9DjmqMZUxDZVt1Dp4m2N5oHYVUfoPdrU9SLk4qxi65RNrfCVnvQtQJk
""" """
tx_compact_2 = """TX:2:1:1:1:2:0:0 simple_tx_compact = """TX:10:1:1:1:2:0:0
13410-000041DF0CCA173F09B5FBA48F619D4BC934F12ADF1D0B798639EB2149C4A8CC
GNPdPNwSJAYw7ixkDeibo3YpdELgLmrZ2Q86HF4cyg92 GNPdPNwSJAYw7ixkDeibo3YpdELgLmrZ2Q86HF4cyg92
D:GNPdPNwSJAYw7ixkDeibo3YpdELgLmrZ2Q86HF4cyg92:471 100:0:D:GNPdPNwSJAYw7ixkDeibo3YpdELgLmrZ2Q86HF4cyg92:471
0:SIG(0) 0:SIG(0)
90:0:SIG(5zDvFjJB1PGDQNiExpfzL9c1tQGs6xPA8mf1phr3VoVi) 90:0:SIG(5zDvFjJB1PGDQNiExpfzL9c1tQGs6xPA8mf1phr3VoVi)
10:0:SIG(GNPdPNwSJAYw7ixkDeibo3YpdELgLmrZ2Q86HF4cyg92) 10:0:SIG(GNPdPNwSJAYw7ixkDeibo3YpdELgLmrZ2Q86HF4cyg92)
XDQeEMcJDd+XVGaFIZc8d4kKRJgsPuWAPVNG5UKNk8mDZx2oE1kTP/hbxiFx6yDouBELCswuf/X6POK9ES7JCA== XDQeEMcJDd+XVGaFIZc8d4kKRJgsPuWAPVNG5UKNk8mDZx2oE1kTP/hbxiFx6yDouBELCswuf/X6POK9ES7JCA==
""" """
tx_raw = """Version: 2 tx_raw = """Version: 10
Type: Transaction
Currency: beta_brousouf
Locktime: 0
Issuers:
HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY
CYYjHsNyg3HMRMpTHqCJAN9McjH5BwFLmDKGV3PmCuKp
9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB
Inputs:
T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:2
T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:8
D:HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY:46
T:A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956:3
T:67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B:5
D:9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB:46
Unlocks:
0:SIG(0)
1:XHX(7665798292)
2:SIG(0)
3:SIG(0) SIG(2)
4:SIG(0) SIG(1) SIG(2)
5:SIG(2)
Outputs:
120:2:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)
146:2:SIG(DSz4rgncXCytsUMW2JU2yhLquZECD2XpEkpP9gG5HyAx)
49:2:(SIG(6DyGr5LFtFmbaJYRvcs9WmBsr4cbJbJ1EV9zBbqG7A6i) || XHX(8FAA0ED653CA4D2C1156D511F0D0036F5168ABA4DAC2929676D279C8A2A12E36))
Comment: -----@@@----- (why not this comment?)
42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r
2D96KZwNUvVtcapQPq2mm7J9isFcDCfykwJpVEZwBc7tCgL4qPyu17BT5ePozAE9HS6Yvj51f62Mp4n9d9dkzJoX
2XiBDpuUdu6zCPWGzHXXy8c4ATSscfFQG9DjmqMZUxDZVt1Dp4m2N5oHYVUfoPdrU9SLk4qxi65RNrfCVnvQtQJk
"""
tx_raw_v3 = """Version: 3
Type: Transaction Type: Transaction
Currency: beta_brousouf Currency: beta_brousouf
Blockstamp: 32-DB30D958EE5CB75186972286ED3F4686B8A1C2CD Blockstamp: 32-DB30D958EE5CB75186972286ED3F4686B8A1C2CD
...@@ -138,109 +108,8 @@ Comment: -----@@@----- (why not this comment?) ...@@ -138,109 +108,8 @@ Comment: -----@@@----- (why not this comment?)
class TestTransaction(unittest.TestCase): class TestTransaction(unittest.TestCase):
def test_fromcompact(self): def test_fromcompact(self):
tx = Transaction.from_compact("zeta_brousouf", tx_compact) tx = Transaction.from_compact("zeta_brousouf", tx_compact)
self.assertEqual(tx.version, 2) self.assertEqual(tx.version, 10)
self.assertEqual(tx.currency, "zeta_brousouf")
self.assertEqual(len(tx.issuers), 3)
self.assertEqual(len(tx.inputs), 6)
self.assertEqual(len(tx.unlocks), 6)
self.assertEqual(len(tx.outputs), 3)
self.assertEqual(tx.issuers[0], "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY")
self.assertEqual(tx.issuers[1], "CYYjHsNyg3HMRMpTHqCJAN9McjH5BwFLmDKGV3PmCuKp")
self.assertEqual(tx.issuers[2], "9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB")
self.assertEqual(tx.inputs[0].source, 'T')
self.assertEqual(tx.inputs[0].origin_id, "6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3")
self.assertEqual(tx.inputs[0].index, 2)
self.assertEqual(tx.inputs[1].source, 'T')
self.assertEqual(tx.inputs[1].origin_id, "3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435")
self.assertEqual(tx.inputs[1].index, 8)
self.assertEqual(tx.inputs[2].source, 'D')
self.assertEqual(tx.inputs[2].origin_id, "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY")
self.assertEqual(tx.inputs[2].index, 46)
self.assertEqual(tx.inputs[3].source, 'T')
self.assertEqual(tx.inputs[3].origin_id, "A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956")
self.assertEqual(tx.inputs[3].index, 3)
self.assertEqual(tx.inputs[4].source, 'T')
self.assertEqual(tx.inputs[4].origin_id, "67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B")
self.assertEqual(tx.inputs[4].index, 5)
self.assertEqual(tx.inputs[5].source, 'D')
self.assertEqual(tx.inputs[5].origin_id, "9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB")
self.assertEqual(tx.inputs[5].index, 46)
self.assertEqual(tx.unlocks[0].index, 0)
self.assertEqual(str(tx.unlocks[0].parameters[0]), "SIG(0)")
self.assertEqual(tx.unlocks[1].index, 1)
self.assertEqual(str(tx.unlocks[1].parameters[0]), "XHX(7665798292)")
self.assertEqual(tx.unlocks[2].index, 2)
self.assertEqual(str(tx.unlocks[2].parameters[0]), "SIG(0)")
self.assertEqual(tx.unlocks[3].index, 3)
self.assertEqual(str(tx.unlocks[3].parameters[0]), "SIG(0)")
self.assertEqual(str(tx.unlocks[3].parameters[1]), "SIG(2)")
self.assertEqual(tx.unlocks[4].index, 4)
self.assertEqual(str(tx.unlocks[4].parameters[0]), "SIG(0)")
self.assertEqual(str(tx.unlocks[4].parameters[1]), "SIG(1)")
self.assertEqual(str(tx.unlocks[4].parameters[2]), "SIG(2)")
self.assertEqual(tx.unlocks[5].index, 5)
self.assertEqual(str(tx.unlocks[5].parameters[0]), "SIG(2)")
self.assertEqual(tx.outputs[0].amount, 120)
self.assertEqual(tx.outputs[0].base, 2)
self.assertEqual(pypeg2.compose(tx.outputs[0].condition, output.Condition),
"SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)")
self.assertEqual(tx.outputs[1].amount, 146)
self.assertEqual(tx.outputs[1].base, 2)
self.assertEqual(pypeg2.compose(tx.outputs[1].condition, output.Condition),
"SIG(DSz4rgncXCytsUMW2JU2yhLquZECD2XpEkpP9gG5HyAx)")
self.assertEqual(tx.outputs[2].amount, 49)
self.assertEqual(tx.outputs[2].base, 2)
self.assertEqual(pypeg2.compose(tx.outputs[2].condition, output.Condition),
"(SIG(6DyGr5LFtFmbaJYRvcs9WmBsr4cbJbJ1EV9zBbqG7A6i) || XHX(8FAA0ED653CA4D2C1156D511F0D0036F5168ABA4DAC2929676D279C8A2A12E36))")
self.assertEqual(tx.comment, "-----@@@----- (why not this comment?)")
self.assertEqual(tx.signatures[0],
"42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r")
self.assertEqual(tx.signatures[1],
"2D96KZwNUvVtcapQPq2mm7J9isFcDCfykwJpVEZwBc7tCgL4qPyu17BT5ePozAE9HS6Yvj51f62Mp4n9d9dkzJoX")
self.assertEqual(tx.signatures[2],
"2XiBDpuUdu6zCPWGzHXXy8c4ATSscfFQG9DjmqMZUxDZVt1Dp4m2N5oHYVUfoPdrU9SLk4qxi65RNrfCVnvQtQJk")
def test_fromcompact2(self):
tx = Transaction.from_compact("zeta_brousouf", tx_compact_2)
self.assertEqual(tx.version, 2)
self.assertEqual(tx.currency, "zeta_brousouf") self.assertEqual(tx.currency, "zeta_brousouf")
self.assertEqual(len(tx.issuers), 1)
self.assertEqual(len(tx.inputs), 1)
self.assertEqual(len(tx.unlocks), 1)
self.assertEqual(len(tx.outputs), 2)
self.assertEqual(tx.issuers[0], "GNPdPNwSJAYw7ixkDeibo3YpdELgLmrZ2Q86HF4cyg92")
self.assertEqual(tx.inputs[0].source, 'D')
self.assertEqual(tx.inputs[0].origin_id, "GNPdPNwSJAYw7ixkDeibo3YpdELgLmrZ2Q86HF4cyg92")
self.assertEqual(tx.inputs[0].index, 471)
self.assertEqual(tx.unlocks[0].index, 0)
self.assertEqual(str(tx.unlocks[0].parameters[0]), "SIG(0)")
self.assertEqual(tx.outputs[0].amount, 90)
self.assertEqual(tx.outputs[0].base, 0)
self.assertEqual(pypeg2.compose(tx.outputs[0].condition, output.Condition),
"SIG(5zDvFjJB1PGDQNiExpfzL9c1tQGs6xPA8mf1phr3VoVi)")
self.assertEqual(type(tx.outputs[0].condition.left), output.SIG)
self.assertEqual(tx.outputs[1].amount, 10)
self.assertEqual(tx.outputs[1].base, 0)
self.assertEqual(pypeg2.compose(tx.outputs[1].condition, output.Condition),
"SIG(GNPdPNwSJAYw7ixkDeibo3YpdELgLmrZ2Q86HF4cyg92)")
self.assertEqual(type(tx.outputs[1].condition.left), output.SIG)
self.assertEqual(tx.signatures[0],
"XDQeEMcJDd+XVGaFIZc8d4kKRJgsPuWAPVNG5UKNk8mDZx2oE1kTP/hbxiFx6yDouBELCswuf/X6POK9ES7JCA==")
def test_fromraw(self):
tx = Transaction.from_signed_raw(tx_raw)
self.assertEqual(tx.version, 2)
self.assertEqual(tx.currency, "beta_brousouf")
self.assertEqual(len(tx.issuers), 3) self.assertEqual(len(tx.issuers), 3)
self.assertEqual(len(tx.inputs), 6) self.assertEqual(len(tx.inputs), 6)
self.assertEqual(len(tx.unlocks), 6) self.assertEqual(len(tx.unlocks), 6)
...@@ -250,21 +119,33 @@ class TestTransaction(unittest.TestCase): ...@@ -250,21 +119,33 @@ class TestTransaction(unittest.TestCase):
self.assertEqual(tx.issuers[1], "CYYjHsNyg3HMRMpTHqCJAN9McjH5BwFLmDKGV3PmCuKp") self.assertEqual(tx.issuers[1], "CYYjHsNyg3HMRMpTHqCJAN9McjH5BwFLmDKGV3PmCuKp")
self.assertEqual(tx.issuers[2], "9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB") self.assertEqual(tx.issuers[2], "9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB")
self.assertEqual(tx.inputs[0].amount, 230)
self.assertEqual(tx.inputs[0].base, 2)
self.assertEqual(tx.inputs[0].source, 'T') self.assertEqual(tx.inputs[0].source, 'T')
self.assertEqual(tx.inputs[0].origin_id, "6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3") self.assertEqual(tx.inputs[0].origin_id, "6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3")
self.assertEqual(tx.inputs[0].index, 2) self.assertEqual(tx.inputs[0].index, 2)
self.assertEqual(tx.inputs[1].amount, 2230)
self.assertEqual(tx.inputs[1].base, 2)
self.assertEqual(tx.inputs[1].source, 'T') self.assertEqual(tx.inputs[1].source, 'T')
self.assertEqual(tx.inputs[1].origin_id, "3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435") self.assertEqual(tx.inputs[1].origin_id, "3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435")
self.assertEqual(tx.inputs[1].index, 8) self.assertEqual(tx.inputs[1].index, 8)
self.assertEqual(tx.inputs[2].amount, 2430)
self.assertEqual(tx.inputs[2].base, 2)
self.assertEqual(tx.inputs[2].source, 'D') self.assertEqual(tx.inputs[2].source, 'D')
self.assertEqual(tx.inputs[2].origin_id, "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY") self.assertEqual(tx.inputs[2].origin_id, "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY")
self.assertEqual(tx.inputs[2].index, 46) self.assertEqual(tx.inputs[2].index, 46)
self.assertEqual(tx.inputs[3].amount, 2310)
self.assertEqual(tx.inputs[3].base, 2)
self.assertEqual(tx.inputs[3].source, 'T') self.assertEqual(tx.inputs[3].source, 'T')
self.assertEqual(tx.inputs[3].origin_id, "A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956") self.assertEqual(tx.inputs[3].origin_id, "A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956")
self.assertEqual(tx.inputs[3].index, 3) self.assertEqual(tx.inputs[3].index, 3)
self.assertEqual(tx.inputs[4].amount, 30)
self.assertEqual(tx.inputs[4].base, 2)
self.assertEqual(tx.inputs[4].source, 'T') self.assertEqual(tx.inputs[4].source, 'T')
self.assertEqual(tx.inputs[4].origin_id, "67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B") self.assertEqual(tx.inputs[4].origin_id, "67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B")
self.assertEqual(tx.inputs[4].index, 5) self.assertEqual(tx.inputs[4].index, 5)
self.assertEqual(tx.inputs[5].amount, 2330)
self.assertEqual(tx.inputs[5].base, 2)
self.assertEqual(tx.inputs[5].source, 'D') self.assertEqual(tx.inputs[5].source, 'D')
self.assertEqual(tx.inputs[5].origin_id, "9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB") self.assertEqual(tx.inputs[5].origin_id, "9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB")
self.assertEqual(tx.inputs[5].index, 46) self.assertEqual(tx.inputs[5].index, 46)
...@@ -312,80 +193,7 @@ class TestTransaction(unittest.TestCase): ...@@ -312,80 +193,7 @@ class TestTransaction(unittest.TestCase):
rendered_tx = tx.signed_raw() rendered_tx = tx.signed_raw()
from_rendered_tx = Transaction.from_signed_raw(rendered_tx) from_rendered_tx = Transaction.from_signed_raw(rendered_tx)
self.assertEqual(tx.version, 2) self.assertEqual(tx.version, 10)
self.assertEqual(tx.currency, "beta_brousouf")
self.assertEqual(len(tx.issuers), 3)
self.assertEqual(len(tx.inputs), 6)
self.assertEqual(len(tx.unlocks), 6)
self.assertEqual(len(tx.outputs), 3)
self.assertEqual(tx.issuers[0], "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY")
self.assertEqual(tx.issuers[1], "CYYjHsNyg3HMRMpTHqCJAN9McjH5BwFLmDKGV3PmCuKp")
self.assertEqual(tx.issuers[2], "9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB")
self.assertEqual(tx.inputs[0].source, 'T')
self.assertEqual(tx.inputs[0].origin_id, "6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3")
self.assertEqual(tx.inputs[0].index, 2)
self.assertEqual(tx.inputs[1].source, 'T')
self.assertEqual(tx.inputs[1].origin_id, "3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435")
self.assertEqual(tx.inputs[1].index, 8)
self.assertEqual(tx.inputs[2].source, 'D')
self.assertEqual(tx.inputs[2].origin_id, "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY")
self.assertEqual(tx.inputs[2].index, 46)
self.assertEqual(tx.inputs[3].source, 'T')
self.assertEqual(tx.inputs[3].origin_id, "A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956")
self.assertEqual(tx.inputs[3].index, 3)
self.assertEqual(tx.inputs[4].source, 'T')
self.assertEqual(tx.inputs[4].origin_id, "67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B")
self.assertEqual(tx.inputs[4].index, 5)
self.assertEqual(tx.inputs[5].source, 'D')
self.assertEqual(tx.inputs[5].origin_id, "9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB")
self.assertEqual(tx.inputs[5].index, 46)
self.assertEqual(tx.unlocks[0].index, 0)
self.assertEqual(str(tx.unlocks[0].parameters[0]), "SIG(0)")
self.assertEqual(tx.unlocks[1].index, 1)
self.assertEqual(str(tx.unlocks[1].parameters[0]), "XHX(7665798292)")
self.assertEqual(tx.unlocks[2].index, 2)
self.assertEqual(str(tx.unlocks[2].parameters[0]), "SIG(0)")
self.assertEqual(tx.unlocks[3].index, 3)
self.assertEqual(str(tx.unlocks[3].parameters[0]), "SIG(0)")
self.assertEqual(str(tx.unlocks[3].parameters[1]), "SIG(2)")
self.assertEqual(tx.unlocks[4].index, 4)
self.assertEqual(str(tx.unlocks[4].parameters[0]), "SIG(0)")
self.assertEqual(str(tx.unlocks[4].parameters[1]), "SIG(1)")
self.assertEqual(str(tx.unlocks[4].parameters[2]), "SIG(2)")
self.assertEqual(tx.unlocks[5].index, 5)
self.assertEqual(str(tx.unlocks[5].parameters[0]), "SIG(2)")
self.assertEqual(tx.outputs[0].amount, 120)
self.assertEqual(tx.outputs[0].base, 2)
self.assertEqual(pypeg2.compose(tx.outputs[0].condition, output.Condition),
"SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)")
self.assertEqual(tx.outputs[1].amount, 146)
self.assertEqual(tx.outputs[1].base, 2)
self.assertEqual(pypeg2.compose(tx.outputs[1].condition, output.Condition),
"SIG(DSz4rgncXCytsUMW2JU2yhLquZECD2XpEkpP9gG5HyAx)")
self.assertEqual(tx.outputs[2].amount, 49)
self.assertEqual(tx.outputs[2].base, 2)
self.assertEqual(pypeg2.compose(tx.outputs[2].condition, output.Condition),
"(SIG(6DyGr5LFtFmbaJYRvcs9WmBsr4cbJbJ1EV9zBbqG7A6i) || XHX(8FAA0ED653CA4D2C1156D511F0D0036F5168ABA4DAC2929676D279C8A2A12E36))")
self.assertEqual(tx.comment, "-----@@@----- (why not this comment?)")
self.assertEqual(tx.signatures[0],
"42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r")
self.assertEqual(tx.signatures[1],
"2D96KZwNUvVtcapQPq2mm7J9isFcDCfykwJpVEZwBc7tCgL4qPyu17BT5ePozAE9HS6Yvj51f62Mp4n9d9dkzJoX")
self.assertEqual(tx.signatures[2],
"2XiBDpuUdu6zCPWGzHXXy8c4ATSscfFQG9DjmqMZUxDZVt1Dp4m2N5oHYVUfoPdrU9SLk4qxi65RNrfCVnvQtQJk")
def test_fromraw_toraw_v3(self):
tx = Transaction.from_signed_raw(tx_raw_v3)
rendered_tx = tx.signed_raw()
from_rendered_tx = Transaction.from_signed_raw(rendered_tx)
self.assertEqual(tx.version, 3)
self.assertEqual(tx.currency, "beta_brousouf") self.assertEqual(tx.currency, "beta_brousouf")
self.assertEqual(tx.blockstamp.number, 32) self.assertEqual(tx.blockstamp.number, 32)
self.assertEqual(tx.blockstamp.sha_hash, "DB30D958EE5CB75186972286ED3F4686B8A1C2CD") self.assertEqual(tx.blockstamp.sha_hash, "DB30D958EE5CB75186972286ED3F4686B8A1C2CD")
...@@ -475,8 +283,26 @@ class TestTransaction(unittest.TestCase): ...@@ -475,8 +283,26 @@ class TestTransaction(unittest.TestCase):
self.assertEqual(computed[1], 5) self.assertEqual(computed[1], 5)
def test_is_simple(self): def test_is_simple(self):
tx = Transaction.from_compact("zeta_brousouf", tx_compact_2) tx = Transaction.from_compact("zeta_brousouf", simple_tx_compact)
self.assertTrue(SimpleTransaction.is_simple(tx)) self.assertTrue(SimpleTransaction.is_simple(tx))
tx = Transaction.from_compact("zeta_brousouf", tx_compact) tx = Transaction.from_compact("zeta_brousouf", tx_compact)
self.assertFalse(SimpleTransaction.is_simple(tx)) self.assertFalse(SimpleTransaction.is_simple(tx))
def test_inputsource_from_inline(self):
input_source_str = "30:0:T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:2"
i = InputSource.from_inline(input_source_str)
self.assertEqual(i.inline(), input_source_str)
def test_outputsource_from_inline(self):
output_source_str = "460:0:SIG(8kXygUHh1vLjmcRzXVM86t38EL8dfFJgfBeHmkaWLamu)"
o = OutputSource.from_inline(output_source_str)
self.assertEqual(o.inline(), output_source_str)
def test_outputsource_inline_condition(self):
output_source_str = "460:0:SIG(8kXygUHh1vLjmcRzXVM86t38EL8dfFJgfBeHmkaWLamu)"
o = OutputSource.from_inline(output_source_str)
self.assertEqual(o.inline_condition(), output_source_str.split(":")[2])
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment