diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 32a1b8935d1cdf520518b51913e347322680ca40..22a0fd66f56e3359fd1f45ff55e57d752fa269ce 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -37,8 +37,21 @@ push_to_github:
     - eval "$(pyenv init -)"
     - pyenv shell $PYENV_PYTHON_VERSION
 
+.changes: &changes
+  except:
+    changes:
+      - CHANGELOG.md
+      - ci/*
+      - config
+      - docs
+      - LICENSE*
+      - Makefile
+      - README*
+      - release.sh
+
 build: &build
   <<: *pyenv
+  <<: *changes
   stage: build
   script:
     - pip install -r requirements.txt
@@ -47,6 +60,7 @@ build: &build
 
 test:
   <<: *pyenv
+  <<: *changes
   stage: test
   script:
     - pip install coveralls
@@ -55,6 +69,7 @@ test:
 
 mypy:
   <<: *pyenv
+  <<: *changes
   stage: test
   script:
     - pip install -r requirements_dev.txt
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..aba3f0b6893b5ea53b9298879920db507dea29ba
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,27 @@
+## 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…
diff --git a/Makefile b/Makefile
index 4d1db9708ec0d41af620f3cdf5e2e9b3bf5bae36..1c169e390cde0fc9118291a97a542fa33bee9638 100644
--- a/Makefile
+++ b/Makefile
@@ -6,8 +6,8 @@ docs:
 
 # run tests
 tests:
-	python -m unittest ${test_filter}
+	python3 -m unittest ${TESTS_FILTER}
 
 # check static typing
 check:
-	mypy duniterpy --ignore-missing-imports
+	python3 -m mypy duniterpy --ignore-missing-imports
diff --git a/README.rst b/README.rst
index 9e8b412e3d1d1fb428b7143a45220e9139c1e2bb..c7455629c76d62d8010b8f32ebf31466e333c138 100644
--- a/README.rst
+++ b/README.rst
@@ -69,9 +69,9 @@ Development
 
     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
 -------------
diff --git a/duniterpy/documents/block.py b/duniterpy/documents/block.py
index 9ec967daff271db06619f6366dc3dde4fe71512c..ad2afe035edaa5018b2e638ad1456edf0abd74d3 100644
--- a/duniterpy/documents/block.py
+++ b/duniterpy/documents/block.py
@@ -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_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]+):\
-([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]+)\n")
     re_memberscount = re.compile("MembersCount: ([0-9]+)\n")
@@ -252,24 +250,18 @@ The class Block handles Block documents.
             ud = int(Block.parse_field("UD", lines[n]))
             n += 1
 
-        if version >= 3 or ud:
-            unit_base = int(Block.parse_field("UnitBase", lines[n]))
-            n += 1
+        unit_base = int(Block.parse_field("UnitBase", lines[n]))
+        n += 1
 
         issuer = Block.parse_field("Issuer", lines[n])
         n += 1
 
-        if version >= 3:
-            issuers_frame = Block.parse_field("IssuersFrame", lines[n])
-            n += 1
-            issuers_frame_var = Block.parse_field("IssuersFrameVar", lines[n])
-            n += 1
-            different_issuers_count = Block.parse_field("DifferentIssuersCount", lines[n])
-            n += 1
-        else:
-            issuers_frame = None
-            issuers_frame_var = None
-            different_issuers_count = None
+        issuers_frame = Block.parse_field("IssuersFrame", lines[n])
+        n += 1
+        issuers_frame_var = Block.parse_field("IssuersFrameVar", lines[n])
+        n += 1
+        different_issuers_count = Block.parse_field("DifferentIssuersCount", lines[n])
+        n += 1
 
         prev_hash = None
         prev_issuer = None
@@ -283,16 +275,10 @@ The class Block handles Block documents.
         parameters = None
         if number == 0:
             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])
-                    if params_match is None:
-                        raise MalformedDocumentError("Parameters")
-                    parameters = params_match.groups()
+                params_match = Block.re_parameters.match(lines[n])
+                if params_match is None:
+                    raise MalformedDocumentError("Parameters")
+                parameters = params_match.groups()
                 n += 1
             except AttributeError:
                 raise MalformedDocumentError("Parameters")
@@ -374,12 +360,7 @@ The class Block handles Block documents.
                 unlocks_num = int(header_data.group(4))
                 outputs_num = int(header_data.group(5))
                 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
-                else:
-                    sup_lines = 1
+                sup_lines = 2
                 tx_max = n + sup_lines + issuers_num * 2 + inputs_num + unlocks_num + outputs_num + has_comment
                 for i in range(n, tx_max):
                     tx_lines += lines[n]
@@ -419,13 +400,11 @@ MedianTime: {mediantime}
         if 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)
 
-        if self.version >= 3:
-            doc += """IssuersFrame: {0}
+        doc += """IssuersFrame: {0}
 IssuersFrameVar: {1}
 DifferentIssuersCount: {2}
 """.format(self.issuers_frame, self.issuers_frame_var, self.different_issuers_count)
diff --git a/duniterpy/documents/block_uid.py b/duniterpy/documents/block_uid.py
index 65a2816f6b1bf8c85eea3d974217f5f65c19a60d..025510476047fd5c01017a7935eaac07cfb663be 100644
--- a/duniterpy/documents/block_uid.py
+++ b/duniterpy/documents/block_uid.py
@@ -56,22 +56,22 @@ class BlockUID:
 
     def __lt__(self, other: object) -> bool:
         if not isinstance(other, BlockUID):
-            return False
+            return NotImplemented
         return self.number < other.number
 
     def __gt__(self, other: object) -> bool:
         if not isinstance(other, BlockUID):
-            return False
+            return NotImplemented
         return self.number > other.number
 
     def __le__(self, other: object) -> bool:
         if not isinstance(other, BlockUID):
-            return False
+            return NotImplemented
         return self.number <= other.number
 
     def __ge__(self, other: object) -> bool:
         if not isinstance(other, BlockUID):
-            return False
+            return NotImplemented
         return self.number >= other.number
 
     def __hash__(self) -> int:
diff --git a/duniterpy/documents/document.py b/duniterpy/documents/document.py
index 55677bd8c222a08c9c92e66efa407ea245cbdbc0..fa4f62122855096dda633b6a3b43e25f6b6485da 100644
--- a/duniterpy/documents/document.py
+++ b/duniterpy/documents/document.py
@@ -44,8 +44,6 @@ class Document:
         :param currency: Name of the currency
         :param signatures: List of signatures
         """
-        if version < 2:
-            raise MalformedDocumentError("Version 1 documents are not handled by duniterpy>0.2")
         self.version = version
         self.currency = currency
         if signatures:
diff --git a/duniterpy/documents/transaction.py b/duniterpy/documents/transaction.py
index fa3f19af2882f9d7b5da095585363a0c11a4d102..8f8ea6dada456208457896fb5aca3e3bc4a15c57 100644
--- a/duniterpy/documents/transaction.py
+++ b/duniterpy/documents/transaction.py
@@ -50,13 +50,8 @@ class InputSource:
 
     """
     re_inline = re.compile(
-        "(?:(?:(D):({pubkey_regex}):({block_id_regex}))|(?:(T):({transaction_hash_regex}):([0-9]+)))\n"
-        .format(pubkey_regex=PUBKEY_REGEX,
-                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"
+        "([0-9]+):([0-9]):(?:(?:(D):({pubkey_regex}):({block_id_regex}))|(?:(T):({transaction_hash_regex}):\
+([0-9]+)))"
         .format(pubkey_regex=PUBKEY_REGEX,
                 block_id_regex=BLOCK_ID_REGEX,
                 transaction_hash_regex=TRANSACTION_HASH_REGEX))
@@ -94,28 +89,19 @@ class InputSource:
         return hash((self.amount, self.base, self.source, self.origin_id, self.index))
 
     @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
 
-        :param tx_version: Version number of the document
         :param inline: Inline string format
         :return:
         """
-        if tx_version == 2:
-            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:
-                raise MalformedDocumentError("Inline input")
-            source_offset = 2
-            amount = int(data.group(1))
-            base = int(data.group(2))
+        data = InputSource.re_inline.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):
             source = data.group(1 + source_offset)
             origin_id = data.group(2 + source_offset)
@@ -127,19 +113,13 @@ class InputSource:
 
         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
 
-        :param tx_version: Version number of the document
         :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.source,
                                                 self.origin_id,
@@ -154,7 +134,7 @@ class OutputSource:
     """
     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:
         """
@@ -200,13 +180,21 @@ class OutputSource:
 
     def inline(self) -> str:
         """
-        Return an inline string format of the document
+        Return an inline string format of the output source
 
         :return:
         """
         return "{0}:{1}:{2}".format(self.amount, self.base,
                                     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
     def condition_from_text(text) -> Condition:
         """
@@ -557,10 +545,8 @@ Comment: {comment}
         locktime = int(header_data.group(7))
         n += 1
 
-        blockstamp = None  # type: Optional[BlockUID]
-        if version >= 3:
-            blockstamp = BlockUID.from_str(Transaction.parse_field("CompactBlockstamp", lines[n]))
-            n += 1
+        blockstamp = BlockUID.from_str(Transaction.parse_field("CompactBlockstamp", lines[n]))
+        n += 1
 
         issuers = []
         inputs = []
@@ -573,7 +559,7 @@ Comment: {comment}
             n += 1
 
         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)
             n += 1
 
@@ -651,7 +637,7 @@ Comment: {comment}
         if Transaction.re_inputs.match(lines[n]):
             n += 1
             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)
                 n += 1
 
@@ -704,7 +690,7 @@ Currency: {1}
 
         doc += "Inputs:\n"
         for i in self.inputs:
-            doc += "{0}\n".format(i.inline(self.version))
+            doc += "{0}\n".format(i.inline())
 
         doc += "Unlocks:\n"
         for u in self.unlocks:
@@ -747,7 +733,7 @@ COMMENT
         for pubkey in self.issuers:
             doc += "{0}\n".format(pubkey)
         for i in self.inputs:
-            doc += "{0}\n".format(i.inline(self.version))
+            doc += "{0}\n".format(i.inline())
         for u in self.unlocks:
             doc += "{0}\n".format(u.inline())
         for o in self.outputs:
diff --git a/requirements_dev.txt b/requirements_dev.txt
index 5816b58ffe5061bef5e60cef8f520692e43a12ca..e70f7780458caa75b832fd0b6325c44ef9177712 100644
--- a/requirements_dev.txt
+++ b/requirements_dev.txt
@@ -1,3 +1,4 @@
+coveralls
 mypy
 sphinx
 sphinx_rtd_theme
diff --git a/setup.py b/setup.py
index 775b88415547d05f3f5e2b676932f51fcbfeb258..ce1b7ea516f1a7813c67860552f94a06f0148387 100644
--- a/setup.py
+++ b/setup.py
@@ -63,13 +63,16 @@ setup(
     test_suite="tests",
 
     classifiers=[
-        "Programming Language :: Python",
         "Development Status :: 5 - Production/Stable",
         "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
         "Natural Language :: English",
         "Operating System :: OS Independent",
+        "Programming Language :: Python :: 3 :: Only",
+        "Programming Language :: Python :: 3.7",
+        "Programming Language :: Python :: 3.6",
         "Programming Language :: Python :: 3.5",
         "Topic :: Software Development :: Libraries",
+        "Intended Audience :: Developers",
     ],
     install_requires=install_requires,
     dependency_links=dependency_links
diff --git a/tests/documents/test_block.py b/tests/documents/test_block.py
index 4472edc35252c8a2fe59bd0013d070affba43295..3e3562d49cc2ccbef9bdc3c5548a79f9b6bb99d4 100644
--- a/tests/documents/test_block.py
+++ b/tests/documents/test_block.py
@@ -8,14 +8,18 @@ import unittest
 from duniterpy.documents.block import Block
 from duniterpy.documents.block_uid import BlockUID, block_uid
 
-raw_block = """Version: 2
+raw_block = """Version: 11
 Type: Block
 Currency: zeta_brouzouf
 Number: 15
 PoWMin: 4
 Time: 1418083330
 MedianTime: 1418080208
+UnitBase: 0
 Issuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk
+IssuersFrame: 1
+IssuersFrameVar: 0
+DifferentIssuersCount: 0
 PreviousHash: 0000E73C340601ACA1AD5AAA5B5E56B03E178EF8
 PreviousIssuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk
 MembersCount: 4
@@ -32,14 +36,18 @@ Nonce: 45079
 42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r
 """
 
-raw_block_with_tx = """Version: 2
+raw_block_with_tx = """Version: 11
 Type: Block
 Currency: meta_brouzouf
 Number: 34436
 PoWMin: 5
 Time: 1443896211
 MedianTime: 1443881811
+UnitBase: 0
 Issuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk
+IssuersFrame: 1
+IssuersFrameVar: 0
+DifferentIssuersCount: 0
 PreviousHash: 000002B06C990DEBD5C1D947289C2CF4F4396FB2
 PreviousIssuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk
 MembersCount: 19
@@ -54,26 +62,28 @@ Certifications:
 5ocqzyDMMWf1V8bsoNhWb1iNwax1e9M7VTUN6navs8of:ATkjQPa4sn4LBF69jqEPzFtRdHYJs6MJQjvP8JdN7MtN:0:6TuxRcARnpo13l3cXtgPTkjJlv8DZOUvsAzmZJMbjHZbbZfDQ6MJpH9DIuH0eyG3WGc0EX/046mbMGBrKKg9DQ==
 ATkjQPa4sn4LBF69jqEPzFtRdHYJs6MJQjvP8JdN7MtN:2qwGeLWoPG7db72bKXPfJpAtj67FYDnPaJn2JB7tyXxJ:0:LusTbb7CgwrqqacDKjtldw60swwvDBH8wVUIJN4SWRb2pZPJSpDxgqaGyjC5P9i/DendfyQWc7cfzPDqSZmZAg==
 Transactions:
-TX:2:1:3:3:1:0:0
+TX:10:1:3:3:1:0:0
+33363-000021C4B5BE2DA996F953DC09482F4FA2FA68774B1A38FAB03B2AAB4A08EBE0
 HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY
-T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:0
-T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:10
-D:HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY:88
+5200:0:T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:0
+500:0:T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:10
+20:0:D:HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY:88
 0:SIG(0)
 1:SIG(0)
 2:SIG(0)
 30:2:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)
 42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r
-TX:2:3:6:6:3:1:0
+TX:10:3:6:6:3:1:0
+33363-000021C4B5BE2DA996F953DC09482F4FA2FA68774B1A38FAB03B2AAB4A08EBE0
 HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY
 CYYjHsNyg3HMRMpTHqCJAN9McjH5BwFLmDKGV3PmCuKp
 9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB
-T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:2
-T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:8
-D:HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY:46
-T:A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956:3
-T:67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B:5
-D:9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB:46
+78900:0:T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:2
+700:0:T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:8
+8900:0:D:HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY:46
+780:0:T:A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956:3
+780:0:T:67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B:5
+8900:0:D:9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB:46
 0:SIG(0)
 1:XHX(7665798292)
 2:SIG(0)
@@ -92,7 +102,7 @@ Nonce: 581
 nY/MsFU2luiohLmSiOOimL1RIqbriOBgc22ua03Z2dhxtSJxKZeGNGDvl1jaXgmEBRnXU87yXbZ7ioOS/AAVCA==
 """
 
-raw_block_zero = """Version: 10
+raw_block_zero = """Version: 11
 Type: Block
 Currency: zeta_brouzouf
 Number: 0
@@ -139,14 +149,18 @@ Nonce: 2125
 42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r
 """
 
-raw_block_with_leavers = """Version: 2
+raw_block_with_leavers = """Version: 11
 Type: Block
 Currency: meta_brouzouf
 Number: 34895
 PoWMin: 4
 Time: 1444434128
 MedianTime: 1444426438
+UnitBase: 0
 Issuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk
+IssuersFrame: 1
+IssuersFrameVar: 0
+DifferentIssuersCount: 0
 PreviousHash: 0000E88115ADDF79344372C0212928501E21622B
 PreviousIssuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk
 MembersCount: 21
@@ -164,7 +178,7 @@ Nonce: 9906
 5LZCFSnm5FkFihPBTpmsPyILEdvu8MXfJOp6OR4d1s+/e2jVWg4J6YSDfO2KBBPgubASyr2QwQuiBlYD2918Bw==
 """
 
-raw_block_with_excluded = """Version: 3
+raw_block_with_excluded = """Version: 11
 Type: Block
 Currency: test_net
 Number: 33365
@@ -189,7 +203,7 @@ Excluded:
 2VAxjr8QoJtSzhE7APno4AkR2RAQNySpNNvDzMgPotSF
 Certifications:
 Transactions:
-TX:3:1:4:4:12:1:0
+TX:10:1:4:4:12:1:0
 33363-000021C4B5BE2DA996F953DC09482F4FA2FA68774B1A38FAB03B2AAB4A08EBE0
 TENGx7WtzFsTXwnbrPEvb6odX2WnqYcnnrjiiLvp1mS
 5:0:T:D25272F1D778B52798B7A51CF0CE21F7C5812F841374508F4367872D4A47F0F7:0
@@ -219,7 +233,7 @@ Nonce: 137387
 GmgYhWrwCtsK7t2B/omPpxZ8EfJgv9UYzJIFo++Za+A0Mo70xRfZG7kywxbQTTxDk/V7r90P946N89vdVjv1Bg==
 """
 
-negative_issuers_frame_var = """Version: 3
+negative_issuers_frame_var = """Version: 11
 Type: Block
 Currency: test_net
 Number: 34662
@@ -242,7 +256,7 @@ Revoked:
 Excluded:
 Certifications:
 Transactions:
-TX:3:1:4:4:2:1:0
+TX:10:1:4:4:2:1:0
 34660-00001EEB3FDCEB2F9F39F931ED8F6D419C4C64B4D3F7EA52C35FB6B07A085664
 5ocqzyDMMWf1V8bsoNhWb1iNwax1e9M7VTUN6navs8of
 765201:3:T:636150D38D565DA0B9717E93C2AD8D6270FA032BF963360ECFCDD55F44493F08:1
@@ -266,7 +280,7 @@ WnJvw204wccmSBQK9UE2rCFw0EG34zf+b58n2KTLwSIhTpgmGsnr5ohkSyYZYcLEKjisLXKNCmMl7D1Q
 class TestBlock(unittest.TestCase):
     def test_fromraw(self):
         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.noonce, 45079)
         self.assertEqual(block.number, 15)
@@ -287,7 +301,7 @@ class TestBlock(unittest.TestCase):
 
     def test_from_signed_raw_block_zero(self):
         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.noonce, 2125)
         self.assertEqual(block.number, 0)
@@ -315,7 +329,7 @@ class TestBlock(unittest.TestCase):
         rendered_raw = block.signed_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.noonce, 45079)
         self.assertEqual(from_rendered_raw.number, 15)
@@ -341,7 +355,7 @@ class TestBlock(unittest.TestCase):
         rendered_raw = block.signed_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.noonce, 2125)
         self.assertEqual(from_rendered_raw.number, 0)
@@ -365,7 +379,7 @@ class TestBlock(unittest.TestCase):
         rendered_raw = block.signed_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.noonce, 581)
         self.assertEqual(from_rendered_raw.number, 34436)
@@ -389,7 +403,7 @@ class TestBlock(unittest.TestCase):
         block = Block.from_signed_raw(raw_block_with_leavers)
         rendered_raw = block.signed_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.noonce, 9906)
         self.assertEqual(from_rendered_raw.number, 34895)
@@ -452,7 +466,7 @@ class TestBlock(unittest.TestCase):
             self.fail("Empty blockuid __nonzero__ comparison failed")
 
     def test_proof_of_work(self):
-        block = """Version: 5
+        block = """Version: 11
 Type: Block
 Currency: test_net
 Number: 60803
diff --git a/tests/documents/test_transaction.py b/tests/documents/test_transaction.py
index 64e01f83feb9507a4afb7a37019a0a7db65f8dcd..415397522a0ff1099e03e5e1dd6f324517fb1bff 100644
--- a/tests/documents/test_transaction.py
+++ b/tests/documents/test_transaction.py
@@ -6,7 +6,7 @@ Created on 12 déc. 2014
 import unittest
 import pypeg2
 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
 13410-000041DF0CCA173F09B5FBA48F619D4BC934F12ADF1D0B798639EB2149C4A8CC
@@ -35,16 +35,17 @@ Comment: XHX for pubkey DCYELkvV1aAsxFv58SbfRerHy5giJwKA1i4ZKTTcVGZe
 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
 CYYjHsNyg3HMRMpTHqCJAN9McjH5BwFLmDKGV3PmCuKp
 9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB
-T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:2
-T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:8
-D:HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY:46
-T:A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956:3
-T:67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B:5
-D:9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB:46
+230:2:T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:2
+2230:2:T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:8
+2430:2:D:HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY:46
+2310:2:T:A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956:3
+30:2:T:67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B:5
+2330:2:D:9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB:46
 0:SIG(0)
 1:XHX(7665798292)
 2:SIG(0)
@@ -60,48 +61,17 @@ D:9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB:46
 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
-D:GNPdPNwSJAYw7ixkDeibo3YpdELgLmrZ2Q86HF4cyg92:471
+100:0:D:GNPdPNwSJAYw7ixkDeibo3YpdELgLmrZ2Q86HF4cyg92:471
 0:SIG(0)
 90:0:SIG(5zDvFjJB1PGDQNiExpfzL9c1tQGs6xPA8mf1phr3VoVi)
 10:0:SIG(GNPdPNwSJAYw7ixkDeibo3YpdELgLmrZ2Q86HF4cyg92)
 XDQeEMcJDd+XVGaFIZc8d4kKRJgsPuWAPVNG5UKNk8mDZx2oE1kTP/hbxiFx6yDouBELCswuf/X6POK9ES7JCA==
 """
 
-tx_raw = """Version: 2
-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
+tx_raw = """Version: 10
 Type: Transaction
 Currency: beta_brousouf
 Blockstamp: 32-DB30D958EE5CB75186972286ED3F4686B8A1C2CD
@@ -138,109 +108,8 @@ Comment: -----@@@----- (why not this comment?)
 class TestTransaction(unittest.TestCase):
     def test_fromcompact(self):
         tx = Transaction.from_compact("zeta_brousouf", tx_compact)
-        self.assertEqual(tx.version, 2)
-        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.version, 10)
         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.inputs), 6)
         self.assertEqual(len(tx.unlocks), 6)
@@ -250,21 +119,33 @@ class TestTransaction(unittest.TestCase):
         self.assertEqual(tx.issuers[1], "CYYjHsNyg3HMRMpTHqCJAN9McjH5BwFLmDKGV3PmCuKp")
         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].origin_id, "6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3")
         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].origin_id, "3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435")
         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].origin_id, "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY")
         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].origin_id, "A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956")
         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].origin_id, "67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B")
         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].origin_id, "9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB")
         self.assertEqual(tx.inputs[5].index, 46)
@@ -312,80 +193,7 @@ class TestTransaction(unittest.TestCase):
         rendered_tx = tx.signed_raw()
         from_rendered_tx = Transaction.from_signed_raw(rendered_tx)
 
-        self.assertEqual(tx.version, 2)
-        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.version, 10)
         self.assertEqual(tx.currency, "beta_brousouf")
         self.assertEqual(tx.blockstamp.number, 32)
         self.assertEqual(tx.blockstamp.sha_hash, "DB30D958EE5CB75186972286ED3F4686B8A1C2CD")
@@ -475,8 +283,26 @@ class TestTransaction(unittest.TestCase):
         self.assertEqual(computed[1], 5)
 
     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))
 
         tx = Transaction.from_compact("zeta_brousouf", tx_compact)
         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])