Commit 676b1099 authored by Vincent Texier's avatar Vincent Texier

Merge branch 'transaction' into 'dev'

Several transaction enhancements, other improvements

See merge request !56
parents 3a1e5d61 4db793ba
Pipeline #5330 passed with stages
in 43 seconds
...@@ -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,16 +275,10 @@ The class Block handles Block documents. ...@@ -283,16 +275,10 @@ 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.match(lines[n])
params_match = Block.re_parameters_v10.match(lines[n]) if params_match is None:
if params_match is None: raise MalformedDocumentError("Parameters")
raise MalformedDocumentError("Parameters") parameters = params_match.groups()
parameters = params_match.groups()
else:
params_match = Block.re_parameters.match(lines[n])
if params_match is None:
raise MalformedDocumentError("Parameters")
parameters = params_match.groups()
n += 1 n += 1
except AttributeError: except AttributeError:
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: sup_lines = 2
if tx_version <= 2:
raise MalformedDocumentError("TX document is using wrong version")
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,13 +400,11 @@ MedianTime: {mediantime} ...@@ -419,13 +400,11 @@ 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}
""".format(self.issuers_frame, self.issuers_frame_var, self.different_issuers_count) """.format(self.issuers_frame, self.issuers_frame_var, self.different_issuers_count)
......
...@@ -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,28 +89,19 @@ class InputSource: ...@@ -94,28 +89,19 @@ 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:
if data is None: raise MalformedDocumentError("Inline input")
raise MalformedDocumentError("Inline input") source_offset = 2
source_offset = 0 amount = int(data.group(1))
amount = 0 base = int(data.group(2))
base = 0
else:
data = InputSource.re_inline_v3.match(inline)
if data is None:
raise MalformedDocumentError("Inline input")
source_offset = 2
amount = int(data.group(1))
base = int(data.group(2))
if data.group(1 + source_offset): if data.group(1 + source_offset):
source = data.group(1 + source_offset) source = data.group(1 + source_offset)
origin_id = data.group(2 + source_offset) origin_id = data.group(2 + source_offset)
...@@ -127,19 +113,13 @@ class InputSource: ...@@ -127,19 +113,13 @@ 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}:{3}:{4}".format(self.amount,
return "{0}:{1}:{2}".format(self.source,
self.origin_id,
self.index)
else:
return "{0}:{1}:{2}:{3}:{4}".format(self.amount,
self.base, self.base,
self.source, self.source,
self.origin_id, self.origin_id,
...@@ -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,10 +545,8 @@ Comment: {comment} ...@@ -557,10 +545,8 @@ Comment: {comment}
locktime = int(header_data.group(7)) locktime = int(header_data.group(7))
n += 1 n += 1
blockstamp = None # type: Optional[BlockUID] blockstamp = BlockUID.from_str(Transaction.parse_field("CompactBlockstamp", lines[n]))
if version >= 3: n += 1
blockstamp = BlockUID.from_str(Transaction.parse_field("CompactBlockstamp", lines[n]))
n += 1
issuers = [] issuers = []
inputs = [] inputs = []
...@@ -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):