diff --git a/duniterpy/documents/block.py b/duniterpy/documents/block.py
index 09f2095eaec1bae47edda45f1dd5eeb004383ad1..9a01fdecf101c6dba722e2438bbaf0bb91d51d7a 100644
--- a/duniterpy/documents/block.py
+++ b/duniterpy/documents/block.py
@@ -194,6 +194,13 @@ The class Block handles Block documents.
         :param list[str] signatures: the block signaturezs
         """
         super().__init__(version, currency, [signature])
+        documents_versions = max(max([1] + [i.version for i in identities]),
+                               max([1] + [m.version for m in actives + leavers + joiners + excluded + actives]),
+                               max([1] + [r.version for r in revokations]),
+                               max([1] + [c.version for c in certifications]),
+                               max([1] + [t.version for t in transactions]))
+        if self.version < documents_versions:
+            raise MalformedDocumentError("Block version is too low : {0} < {1}".format(self.version, documents_versions))
         self.number = number
         self.powmin = powmin
         self.time = time
@@ -344,13 +351,19 @@ The class Block handles Block documents.
                 header_data = Transaction.re_header.match(lines[n])
                 if header_data is None:
                     raise MalformedDocumentError("Compact transaction ({0})".format(lines[n]))
-                version = int(header_data.group(1))
+                tx_version = int(header_data.group(1))
                 issuers_num = int(header_data.group(2))
                 inputs_num = int(header_data.group(3))
                 unlocks_num = int(header_data.group(4))
                 outputs_num = int(header_data.group(5))
                 has_comment = int(header_data.group(6))
-                tx_max = n + 1 + issuers_num * 2 + inputs_num + unlocks_num + outputs_num + has_comment
+                if version > 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
                 for i in range(n, tx_max):
                     tx_lines += lines[n]
                     n += 1
diff --git a/duniterpy/documents/transaction.py b/duniterpy/documents/transaction.py
index 4bb3391a1c25fc0dd141e970aa2b6266d506c0a8..c882d5e670d891f95ddb83f90584141380d9188d 100644
--- a/duniterpy/documents/transaction.py
+++ b/duniterpy/documents/transaction.py
@@ -1,5 +1,5 @@
 from .document import Document, MalformedDocumentError
-from .constants import pubkey_regex, transaction_hash_regex, block_id_regex
+from .constants import pubkey_regex, transaction_hash_regex, block_id_regex, block_uid_regex
 from ..grammars import output
 import pypeg2
 import re
@@ -63,6 +63,8 @@ class Transaction(Document):
 
     re_type = re.compile("Type: (Transaction)\n")
     re_header = re.compile("TX:([0-9]+):([0-9]+):([0-9]+):([0-9]+):([0-9]+):(0|1):([0-9]+)\n")
+    re_compact_blockstamp = re.compile("({block_uid_regex})\n".format(block_uid_regex=block_uid_regex))
+    re_blockstamp = re.compile("Blockstamp: ({block_uid_regex})\n".format(block_uid_regex=block_uid_regex))
     re_locktime = re.compile("Locktime: ([0-9]+)\n")
     re_issuers = re.compile("Issuers:\n")
     re_inputs = re.compile("Inputs:\n")
@@ -74,6 +76,8 @@ class Transaction(Document):
 
     fields_parsers = {**Document.fields_parsers, **{
             "Type": re_type,
+            "Blockstamp": re_blockstamp,
+            "CompactBlockstamp": re_compact_blockstamp,
             "Locktime": re_locktime,
             "TX": re_header,
             "Issuers": re_issuers,
@@ -86,13 +90,23 @@ class Transaction(Document):
         }
     }
 
-    def __init__(self, version, currency, locktime, issuers, inputs, unlocks, outputs,
+    def __init__(self, version, currency, blockstamp, locktime, issuers, inputs, unlocks, outputs,
                  comment, signatures):
         """
-        Constructor
+
+        :param int version:
+        :param str currency:
+        :param BlockUID blockstamp:
+        :param int locktime:
+        :param str issuers:
+        :param inputs:
+        :param unlocks:
+        :param outputs:
+        :param comment:
+        :param signatures:
         """
         super().__init__(version, currency, signatures)
-
+        self.blockstamp = blockstamp
         self.locktime = locktime
         self.issuers = issuers
         self.inputs = inputs
@@ -102,6 +116,7 @@ class Transaction(Document):
 
     @classmethod
     def from_compact(cls, currency, compact):
+        from .block import BlockUID
         lines = compact.splitlines(True)
         n = 0
 
@@ -117,6 +132,12 @@ class Transaction(Document):
         locktime = int(header_data.group(7))
         n += 1
 
+        if version >= 3:
+            blockstamp = BlockUID.from_str(Transaction.parse_field("CompactBlockstamp", lines[n]))
+            n += 1
+        else:
+            blockstamp = None
+
         issuers = []
         inputs = []
         unlocks = []
@@ -128,7 +149,7 @@ class Transaction(Document):
             n += 1
 
         for i in range(0, inputs_num):
-            input_source = InputSource.from_inline(lines[n])
+            input_source = InputSource.from_inline(version, lines[n])
             inputs.append(input_source)
             n += 1
 
@@ -157,10 +178,11 @@ class Transaction(Document):
             else:
                 raise MalformedDocumentError("Compact TX Signatures")
 
-        return cls(version, currency, locktime, issuers, inputs, unlocks, outputs, comment, signatures)
+        return cls(version, currency, blockstamp, locktime, issuers, inputs, unlocks, outputs, comment, signatures)
 
     @classmethod
     def from_signed_raw(cls, raw):
+        from .block import BlockUID
         lines = raw.splitlines(True)
         n = 0
 
@@ -173,6 +195,12 @@ class Transaction(Document):
         currency = Transaction.parse_field("Currency", lines[n])
         n += 1
 
+        if version >= 3:
+            blockstamp = BlockUID.from_str(Transaction.parse_field("Blockstamp", lines[n]))
+            n += 1
+        else:
+            blockstamp = None
+
         locktime = Transaction.parse_field("Locktime", lines[n])
         n += 1
 
@@ -192,7 +220,7 @@ class Transaction(Document):
         if Transaction.re_inputs.match(lines[n]):
             n += 1
             while Transaction.re_unlocks.match(lines[n]) is None:
-                input_source = InputSource.from_inline(lines[n])
+                input_source = InputSource.from_inline(version, lines[n])
                 inputs.append(input_source)
                 n += 1
 
@@ -219,25 +247,28 @@ class Transaction(Document):
                 signatures.append(sign)
                 n += 1
 
-        return cls(version, currency, locktime, issuers, inputs, unlocks, outputs,
+        return cls(version, currency, blockstamp, locktime, issuers, inputs, unlocks, outputs,
                    comment, signatures)
 
     def raw(self):
         doc = """Version: {0}
 Type: Transaction
 Currency: {1}
-Locktime: {2}
-Issuers:
 """.format(self.version,
-           self.currency,
-           self.locktime)
+           self.currency)
 
+        if self.version >= 3:
+            doc += "Blockstamp: {0}\n".format(self.blockstamp)
+
+        doc += "Locktime: {0}\n".format(self.locktime)
+
+        doc += "Issuers:\n"
         for p in self.issuers:
             doc += "{0}\n".format(p)
 
         doc += "Inputs:\n"
         for i in self.inputs:
-            doc += "{0}\n".format(i.inline())
+            doc += "{0}\n".format(i.inline(self.version))
 
         doc += "Unlocks:\n"
         for u in self.unlocks:
@@ -272,10 +303,13 @@ COMMENT
                                               len(self.outputs),
                                               '1' if self.comment != "" else '0',
                                                self.locktime)
+        if self.version >= 3:
+            doc += "{0}\n".format(self.blockstamp)
+
         for pubkey in self.issuers:
             doc += "{0}\n".format(pubkey)
         for i in self.inputs:
-            doc += "{0}\n".format(i.inline())
+            doc += "{0}\n".format(i.inline(self.version))
         for u in self.unlocks:
             doc += "{0}\n".format(u.inline())
         for o in self.outputs:
@@ -340,40 +374,66 @@ class InputSource:
                            .format(pubkey_regex=pubkey_regex,
                                    block_id_regex=block_id_regex,
                                     transaction_hash_regex=transaction_hash_regex))
-    re_compact = re.compile("([0-9]+):(D|T):([0-9a-fA-F]{5,40}):([0-9]+)\n")
+    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,
+                                   block_id_regex=block_id_regex,
+                                    transaction_hash_regex=transaction_hash_regex))
 
-    def __init__(self, source, origin_id, index):
+    def __init__(self, amount, base, source, origin_id, index):
         """
         An input source can come from a dividend or a transaction.
 
+        :param int amount: amount of the input
+        :param int base: base of the input
         :param str source: D if dividend, T if transaction
         :param str origin_id: a Public key if a dividend, a tx hash if a transaction
         :param int index: a block id if a dividend, an tx index if a transaction
         :return:
         """
+        self.amount = amount
+        self.base = base
         self.source = source
         self.origin_id = origin_id
         self.index = index
 
     @classmethod
-    def from_inline(cls, inline):
-        data = InputSource.re_inline.match(inline)
-        if data is None:
-            raise MalformedDocumentError("Inline input")
-        if data.group(1):
-            source = data.group(1)
-            origin_id = data.group(2)
-            index = int(data.group(3))
+    def from_inline(cls, tx_version, inline):
+        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 = data.group(1)
+            base = data.group(2)
+        if data.group(1 + source_offset):
+            source = data.group(1 + source_offset)
+            origin_id = data.group(2 + source_offset)
+            index = int(data.group(3 + source_offset))
         else:
-            source = data.group(4)
-            origin_id = data.group(5)
-            index = int(data.group(6))
-        return cls(source, origin_id, index)
+            source = data.group(4 + source_offset)
+            origin_id = data.group(5 + source_offset)
+            index = int(data.group(6 + source_offset))
 
-    def inline(self):
-        return "{0}:{1}:{2}".format(self.source,
-                                            self.origin_id,
-                                            self.index)
+        return cls(amount, base, source, origin_id, index)
+
+    def inline(self, tx_version):
+        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,
+                                        self.base,
+                                        self.source,
+                                        self.origin_id,
+                                        self.index)
 
 
 class UnlockParameter:
diff --git a/tests/documents/test_block.py b/tests/documents/test_block.py
index 99533d89f813e63e5de5b6ea0c4d8bd3245eb2dc..2442f754fecbefb6d2bccb6429b960341b3d56ef 100644
--- a/tests/documents/test_block.py
+++ b/tests/documents/test_block.py
@@ -160,6 +160,68 @@ Nonce: 9906
 5LZCFSnm5FkFihPBTpmsPyILEdvu8MXfJOp6OR4d1s+/e2jVWg4J6YSDfO2KBBPgubASyr2QwQuiBlYD2918Bw==
 """
 
+raw_block_with_tx_v3 = """Version: 3
+Type: Block
+Currency: meta_brouzouf
+Number: 34436
+PoWMin: 5
+Time: 1443896211
+MedianTime: 1443881811
+Issuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk
+PreviousHash: 000002B06C990DEBD5C1D947289C2CF4F4396FB2
+PreviousIssuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk
+MembersCount: 19
+Identities:
+Joiners:
+Actives:
+ATkjQPa4sn4LBF69jqEPzFtRdHYJs6MJQjvP8JdN7MtN:QTowsupV+uXrcomL44WCxbu3LQoJM2C2VPMet5Xg6gXGAHEtGRp47FfQLb2ok1+/588JiIHskCyazj3UOsmKDw==:34434-00000D21F80687248A8C02F16BB19A975B4F983D:34432-00000D21F80687248A8C02F16BB19A975B4F983D:urodelus
+Leavers:
+Revoked:
+Excluded:
+Certifications:
+5ocqzyDMMWf1V8bsoNhWb1iNwax1e9M7VTUN6navs8of:ATkjQPa4sn4LBF69jqEPzFtRdHYJs6MJQjvP8JdN7MtN:0:6TuxRcARnpo13l3cXtgPTkjJlv8DZOUvsAzmZJMbjHZbbZfDQ6MJpH9DIuH0eyG3WGc0EX/046mbMGBrKKg9DQ==
+ATkjQPa4sn4LBF69jqEPzFtRdHYJs6MJQjvP8JdN7MtN:2qwGeLWoPG7db72bKXPfJpAtj67FYDnPaJn2JB7tyXxJ:0:LusTbb7CgwrqqacDKjtldw60swwvDBH8wVUIJN4SWRb2pZPJSpDxgqaGyjC5P9i/DendfyQWc7cfzPDqSZmZAg==
+Transactions:
+TX:3:1:3:3:1:0:0
+32-DB30D958EE5CB75186972286ED3F4686B8A1C2CD
+HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY
+5:0:T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:0
+1:1:T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:10
+35:0:D:HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY:88
+0:SIG(0)
+1:SIG(0)
+2:SIG(0)
+30:2:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)
+42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r
+TX:3:3:6:6:3:1:0
+3-DB30D958EE5CB75186972286ED3F4686B8A1C2CD
+HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY
+CYYjHsNyg3HMRMpTHqCJAN9McjH5BwFLmDKGV3PmCuKp
+9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB
+30:0:T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:2
+25:0:T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:8
+5:1:D:HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY:46
+10:1:T:A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956:3
+60:0:T:67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B:5
+50:0:D:9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB:46
+0:SIG(0)
+1:XHX(7665798292)
+2:SIG(0)
+3:SIG(0) SIG(2)
+4:SIG(0) SIG(1) SIG(2)
+5:SIG(2)
+120:2:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)
+146:2:SIG(DSz4rgncXCytsUMW2JU2yhLquZECD2XpEkpP9gG5HyAx)
+49:2:(SIG(6DyGr5LFtFmbaJYRvcs9WmBsr4cbJbJ1EV9zBbqG7A6i) OR XHX(3EB4702F2AC2FD3FA4FDC46A4FC05AE8CDEE1A85))
+-----@@@----- (why not this comment?)
+42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r
+2D96KZwNUvVtcapQPq2mm7J9isFcDCfykwJpVEZwBc7tCgL4qPyu17BT5ePozAE9HS6Yvj51f62Mp4n9d9dkzJoX
+2XiBDpuUdu6zCPWGzHXXy8c4ATSscfFQG9DjmqMZUxDZVt1Dp4m2N5oHYVUfoPdrU9SLk4qxi65RNrfCVnvQtQJk
+InnerHash: DB30D958EE5CB75186972286ED3F4686B8A1C2CD
+Nonce: 581
+nY/MsFU2luiohLmSiOOimL1RIqbriOBgc22ua03Z2dhxtSJxKZeGNGDvl1jaXgmEBRnXU87yXbZ7ioOS/AAVCA==
+"""
+
 
 class Test_Block(unittest.TestCase):
     def test_fromraw(self):
@@ -282,6 +344,31 @@ class Test_Block(unittest.TestCase):
 
         self.assertEqual(block.signed_raw(), raw_block_with_tx)
 
+    def test_raw_with_tx_v3(self):
+        block = Block.from_signed_raw(raw_block_with_tx_v3)
+        rendered_raw = block.signed_raw()
+        from_rendered_raw = block.from_signed_raw(rendered_raw)
+
+        self.assertEqual(from_rendered_raw.version, 3)
+        self.assertEqual(from_rendered_raw.currency, "meta_brouzouf")
+        self.assertEqual(from_rendered_raw.noonce, 581)
+        self.assertEqual(from_rendered_raw.number, 34436)
+        self.assertEqual(from_rendered_raw.powmin, 5)
+        self.assertEqual(from_rendered_raw.time, 1443896211)
+        self.assertEqual(from_rendered_raw.mediantime, 1443881811)
+        self.assertEqual(from_rendered_raw.issuer, "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk")
+        self.assertEqual(from_rendered_raw.parameters, None)
+        self.assertEqual(from_rendered_raw.members_count, 19)
+        self.assertEqual(from_rendered_raw.identities, [])
+        self.assertEqual(from_rendered_raw.joiners, [])
+        self.assertEqual(len(from_rendered_raw.actives), 1)
+        self.assertEqual(from_rendered_raw.leavers, [])
+        self.assertEqual(from_rendered_raw.excluded, [])
+        self.assertEqual(len(from_rendered_raw.certifications), 2)
+        self.assertEqual(len(from_rendered_raw.transactions), 2)
+
+        self.assertEqual(block.signed_raw(), raw_block_with_tx_v3)
+
     def test_raw_with_leavers(self):
         block = Block.from_signed_raw(raw_block_with_leavers)
         rendered_raw = block.signed_raw()
diff --git a/tests/documents/test_transaction.py b/tests/documents/test_transaction.py
index a80cbc3553b5ab1d95bdf2461412845267131515..24246811b86b4df7bc74b78d6262515c2da111c3 100644
--- a/tests/documents/test_transaction.py
+++ b/tests/documents/test_transaction.py
@@ -43,6 +43,32 @@ D:GNPdPNwSJAYw7ixkDeibo3YpdELgLmrZ2Q86HF4cyg92:471
 XDQeEMcJDd+XVGaFIZc8d4kKRJgsPuWAPVNG5UKNk8mDZx2oE1kTP/hbxiFx6yDouBELCswuf/X6POK9ES7JCA==
 """
 
+tx_compact_v3 = """TX:3:3:6:6:3:1:0
+32-DB30D958EE5CB75186972286ED3F4686B8A1C2CD
+HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY
+CYYjHsNyg3HMRMpTHqCJAN9McjH5BwFLmDKGV3PmCuKp
+9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB
+30:0:T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:2
+25:0:T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:8
+5:1:D:HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY:46
+10:1:T:A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956:3
+60:0:T:67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B:5
+50:0:D:9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB:46
+0:SIG(0)
+1:XHX(7665798292)
+2:SIG(0)
+3:SIG(0) SIG(2)
+4:SIG(0) SIG(1) SIG(2)
+5:SIG(2)
+120:2:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)
+146:2:SIG(DSz4rgncXCytsUMW2JU2yhLquZECD2XpEkpP9gG5HyAx)
+49:2:(SIG(6DyGr5LFtFmbaJYRvcs9WmBsr4cbJbJ1EV9zBbqG7A6i) OR XHX(3EB4702F2AC2FD3FA4FDC46A4FC05AE8CDEE1A85))
+-----@@@----- (why not this comment?)
+42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r
+2D96KZwNUvVtcapQPq2mm7J9isFcDCfykwJpVEZwBc7tCgL4qPyu17BT5ePozAE9HS6Yvj51f62Mp4n9d9dkzJoX
+2XiBDpuUdu6zCPWGzHXXy8c4ATSscfFQG9DjmqMZUxDZVt1Dp4m2N5oHYVUfoPdrU9SLk4qxi65RNrfCVnvQtQJk
+"""
+
 tx_raw = """Version: 2
 Type: Transaction
 Currency: beta_brousouf
@@ -75,6 +101,38 @@ Comment: -----@@@----- (why not this comment?)
 2XiBDpuUdu6zCPWGzHXXy8c4ATSscfFQG9DjmqMZUxDZVt1Dp4m2N5oHYVUfoPdrU9SLk4qxi65RNrfCVnvQtQJk
 """
 
+tx_raw_v3 = """Version: 3
+Type: Transaction
+Currency: beta_brousouf
+Blockstamp: 32-DB30D958EE5CB75186972286ED3F4686B8A1C2CD
+Locktime: 0
+Issuers:
+HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY
+CYYjHsNyg3HMRMpTHqCJAN9McjH5BwFLmDKGV3PmCuKp
+9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB
+Inputs:
+30:0:T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:2
+25:0:T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:8
+5:1:D:HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY:46
+10:1:T:A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956:3
+60:0:T:67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B:5
+50:0: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) OR XHX(3EB4702F2AC2FD3FA4FDC46A4FC05AE8CDEE1A85))
+Comment: -----@@@----- (why not this comment?)
+42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r
+2D96KZwNUvVtcapQPq2mm7J9isFcDCfykwJpVEZwBc7tCgL4qPyu17BT5ePozAE9HS6Yvj51f62Mp4n9d9dkzJoX
+2XiBDpuUdu6zCPWGzHXXy8c4ATSscfFQG9DjmqMZUxDZVt1Dp4m2N5oHYVUfoPdrU9SLk4qxi65RNrfCVnvQtQJk
+"""
 
 class Test_Transaction(unittest.TestCase):
     def test_fromcompact(self):
@@ -169,6 +227,72 @@ class Test_Transaction(unittest.TestCase):
         self.assertEqual(type(tx.outputs[1].conditions.left), output.SIG)
         self.assertEqual(tx.signatures[0], "XDQeEMcJDd+XVGaFIZc8d4kKRJgsPuWAPVNG5UKNk8mDZx2oE1kTP/hbxiFx6yDouBELCswuf/X6POK9ES7JCA==")
 
+    def test_fromcompact_v3(self):
+        tx = Transaction.from_compact("zeta_brousouf", tx_compact_v3)
+        self.assertEqual(tx.version, 3)
+        self.assertEqual(tx.currency, "zeta_brousouf")
+        self.assertEqual(tx.blockstamp.number, 32)
+        self.assertEqual(tx.blockstamp.sha_hash, "DB30D958EE5CB75186972286ED3F4686B8A1C2CD")
+        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].conditions, 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].conditions, 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].conditions, output.Condition), "(SIG(6DyGr5LFtFmbaJYRvcs9WmBsr4cbJbJ1EV9zBbqG7A6i) OR XHX(3EB4702F2AC2FD3FA4FDC46A4FC05AE8CDEE1A85))")
+
+        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(self):
         tx = Transaction.from_signed_raw(tx_raw)
         self.assertEqual(tx.version, 2)
@@ -300,6 +424,75 @@ class Test_Transaction(unittest.TestCase):
         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.blockstamp.number, 32)
+        self.assertEqual(tx.blockstamp.sha_hash, "DB30D958EE5CB75186972286ED3F4686B8A1C2CD")
+        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].conditions, 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].conditions, 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].conditions, output.Condition), "(SIG(6DyGr5LFtFmbaJYRvcs9WmBsr4cbJbJ1EV9zBbqG7A6i) OR XHX(3EB4702F2AC2FD3FA4FDC46A4FC05AE8CDEE1A85))")
+
+        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_reduce_base(self):
         amount = 1200
         base = 0