diff --git a/src/sakia/data/entities/transaction.py b/src/sakia/data/entities/transaction.py
index 82096a04466c1ac12440460043ecc617962545f3..460ca51bf8641d6c5a01892ff706c5d738a7ed37 100644
--- a/src/sakia/data/entities/transaction.py
+++ b/src/sakia/data/entities/transaction.py
@@ -111,18 +111,21 @@ class Transaction:
     Transaction entity
 
     :param str currency: the currency of the transaction
+    :param str pubkey: the pubkey of the issuer
     :param str sha_hash: the hash of the transaction
     :param int written_block: the number of the block
     :param duniterpy.documents.BlockUID blockstamp: the blockstamp of the transaction
     :param int timestamp: the timestamp of the transaction
-    :param str signature: the signature
-    :param str issuer: the pubkey of the issuer
-    :param str receiver: the pubkey of the receiver
+    :param str signatures: the signature
+    :param tuple issuers: tuple of pubkey of the issuers
+    :param tuple receivers: tuple of pubkey of the receivers
     :param int amount: the amount
     :param int amount_base: the amount base
     :param str comment: a comment
-    :param str txid: the transaction id to sort transctions
+    :param int txid: the transaction id to sort transctions
     :param int state: the state of the transaction
+    :param bool local: is the transaction local
+    :param str raw: the raw string of the transaction
     """
 
     TO_SEND = 0
diff --git a/src/sakia/data/processors/transactions.py b/src/sakia/data/processors/transactions.py
index 04ff3822e76f2bb36eaad9510b21d0b0bad9396d..ce3d357892aa5df462f5f061109f004d00f0f0ab 100644
--- a/src/sakia/data/processors/transactions.py
+++ b/src/sakia/data/processors/transactions.py
@@ -92,7 +92,7 @@ class TransactionsProcessor:
         except sqlite3.IntegrityError:
             self._repo.update(tx)
 
-    def find_by_hash(self, pubkey, sha_hash):
+    def find_by_hash(self, pubkey: str, sha_hash: str) -> Transaction:
         return self._repo.get_one(pubkey=pubkey, sha_hash=sha_hash)
 
     def awaiting(self, currency):
diff --git a/src/sakia/data/repositories/transactions.py b/src/sakia/data/repositories/transactions.py
index 04ba645b34d3f201029be53a3bd296923c224d18..c51c8a5d35a3f3d07b2ec16e49ca1ba4d404cdbc 100644
--- a/src/sakia/data/repositories/transactions.py
+++ b/src/sakia/data/repositories/transactions.py
@@ -75,7 +75,7 @@ class TransactionsRepo:
     def get_one(self, **search):
         """
         Get an existing transaction in the database
-        :param dict search: the criterions of the lookup
+        :param ** search: the criterions of the lookup
         :rtype: sakia.data.entities.Transaction
         """
         filters = []
diff --git a/src/sakia/services/documents.py b/src/sakia/services/documents.py
index 3f0a548ea6cc0fbdee4db78ba79b6f635c77efdd..e280500532fcf37342fbe42b1ef2025d8fe008f8 100644
--- a/src/sakia/services/documents.py
+++ b/src/sakia/services/documents.py
@@ -1,3 +1,5 @@
+from hashlib import sha256
+
 import jsonschema
 import attr
 import logging
@@ -18,7 +20,7 @@ from duniterpy.documents import (
 from duniterpy.documents import Identity as IdentityDoc
 from duniterpy.documents import Transaction as TransactionDoc
 from duniterpy.documents.transaction import reduce_base
-from duniterpy.grammars.output import Condition, Operator, SIG, CSV
+from duniterpy.grammars.output import Condition, Operator, SIG, CSV, CLTV, XHX
 from duniterpy.api import bma
 from sakia.data.entities import Identity, Transaction, Source
 from sakia.data.processors import (
@@ -298,13 +300,13 @@ class DocumentsService:
 
         return document.signed_raw(), identity
 
-    def tx_sources(self, amount, amount_base, currency, pubkey):
+    def tx_sources(self, amount, amount_base, currency, key: SigningKey):
         """
         Get inputs to generate a transaction with a given amount of money
         :param int amount: The amount target value
         :param int amount_base: The amount base target value
         :param str currency: The community target of the transaction
-        :param str pubkey: The pubkey owning the sources
+        :param str key: The key owning the sources
         :return: The list of inputs to use in the transaction document
         """
 
@@ -321,7 +323,7 @@ class DocumentsService:
             return i
 
         amount, amount_base = reduce_base(amount, amount_base)
-        available_sources = self._sources_processor.available(currency, pubkey)
+        available_sources = self._sources_processor.available(currency, key.pubkey)
         if available_sources:
             current_base = max([src.base for src in available_sources])
             value = 0
@@ -331,6 +333,12 @@ class DocumentsService:
             buf_sources = list(available_sources)
             while current_base >= 0:
                 for s in [src for src in available_sources if src.base == current_base]:
+                    condition = pypeg2.parse(s.conditions, Condition)
+                    # evaluate the condition
+                    if not self.evaluate_condition(
+                        currency, condition, [key], [], s.identifier
+                    ):
+                        continue
                     test_sources = sources + [s]
                     val = current_value(test_sources, overheads)
                     # if we have to compute an overhead
@@ -503,7 +511,7 @@ class DocumentsService:
         forged_tx = []
         sources = [None] * 41
         while len(sources) > 40:
-            result = self.tx_sources(int(amount), amount_base, currency, key.pubkey)
+            result = self.tx_sources(int(amount), amount_base, currency, key)
             sources = result[0]
             computed_outputs = result[1]
             overheads = result[2]
@@ -626,3 +634,97 @@ class DocumentsService:
             return result
         except NotEnoughChangeError as e:
             return (False, str(e)), tx_entities
+
+    def evaluate_condition(
+        self,
+        currency,
+        condition: Condition,
+        keys: list,
+        passwords,
+        identifier: str,
+        result: bool = True,
+    ) -> bool:
+        """
+        Evaluate a source lock condition
+        Support multiple signatures and passwords
+
+        :param passwords:
+        :param str currency: Name of currency
+        :param Condition condition: Condition instance
+        :param [SigningKey] keys: Keys to unlock condition (first key is the source owner key)
+        :param str identifier: Source transaction identifier
+        :param bool result: result accumulator
+        :return:
+        """
+        left = False
+        right = False
+        # if left param is a condition...
+        if isinstance(condition.left, Condition):
+            # evaluate condition
+            left = self.evaluate_condition(
+                currency, condition.left, keys, passwords, identifier, result
+            )
+        # if right param is a condition...
+        if isinstance(condition.right, Condition):
+            # evaluate condition
+            right = self.evaluate_condition(
+                currency, condition.right, keys, passwords, identifier, result
+            )
+        # if left param is a SIG...
+        if isinstance(condition.left, SIG) and condition.left.pubkey in (
+            key.pubkey for key in keys
+        ):
+            left = True
+        # if left param is a CSV value...
+        if isinstance(condition.left, CSV):
+            # capture transaction of the source
+            tx = self._transactions_processor.find_by_hash(keys[0].pubkey, identifier)
+            if tx:
+                # capture current blockchain time
+                median_time = self._blockchain_processor.time(currency)
+                # param is true if tx time + CSV delay <= blockchain time
+                left = tx.timestamp + int(condition.left.time) <= median_time
+        # if left param is a CLTV value...
+        if isinstance(condition.left, CLTV):
+            # capture current blockchain time
+            median_time = self._blockchain_processor.time(currency)
+            # param is true if CL:TV value <= blockchain time
+            left = int(condition.left.timestamp) <= median_time
+        # if left param is a XHX value...
+        if isinstance(condition.left, XHX):
+            left = condition.left.sha_hash in [
+                sha256(password).hexdigest().upper() for password in passwords
+            ]
+        # if no op then stop evaluation...
+        if not condition.op:
+            return left
+        # if right param is a SIG...
+        if isinstance(condition.right, SIG) and condition.right.pubkey in (
+            key.pubkey for key in keys
+        ):
+            right = True
+        # if right param is a CSV value...
+        if isinstance(condition.right, CSV):
+            # capture transaction of the source
+            tx = self._transactions_processor.find_by_hash(keys[0].pubkey, identifier)
+            if tx:
+                # capture current blockchain time
+                median_time = self._blockchain_processor.time(currency)
+                # param is true if tx time + CSV delay <= blockchain time
+                right = tx.timestamp + int(condition.right.time) <= median_time
+        # if right param is a CLTV value...
+        if isinstance(condition.right, CLTV):
+            # capture current blockchain time
+            median_time = self._blockchain_processor.time(currency)
+            # param is true if CLTV value <= blockchain time
+            right = int(condition.right.timestamp) <= median_time
+        # if right param is a XHX value...
+        if isinstance(condition.right, XHX):
+            right = condition.right.sha_hash in [
+                sha256(password).upper() for password in passwords
+            ]
+        # if operator AND...
+        if condition.op == "&&":
+            return left & right
+        # operator OR
+        return left | right
diff --git a/tests/unit/services/test_documents.py b/tests/unit/services/test_documents.py
index 00084fa94b0ad7d2ce2106ba88303aff979742ec..4374dca2d48041ecf1398ea2a248008fbdd976ba 100644
--- a/tests/unit/services/test_documents.py
+++ b/tests/unit/services/test_documents.py
@@ -1,4 +1,12 @@
+from hashlib import sha256
+
+import pypeg2
 import pytest
+from duniterpy.grammars import output
+from duniterpy.grammars.output import Condition
+
+from sakia.data.entities import Transaction, Source
+from sakia.data.repositories import TransactionsRepo, SourcesRepo
 
 
 @pytest.mark.asyncio
@@ -69,3 +77,619 @@ async def test_lock_mode_1(application_with_one_connection, fake_server, bob, al
         "Outputs:\n100:0:SIG(F3HWkYnUSbdpEueosKqzYd1m8ftwojwE2uXR7ScoAVKo) || (SIG(GfFUvqaVSgCt6nFDQCAuULWk6K16MUDckeyBJQFcaYj7) && CSV(604800))\n"
         in sakia_tx_list[0].raw
     )
+
+
+def test_evaluate_condition_source_lock_mode_0(
+    application_with_one_connection, bob, alice, meta_repo
+):
+    application_with_one_connection.instanciate_services()
+
+    # capture blockchain median time
+    median_time = application_with_one_connection.blockchain_service._blockchain_processor.time(
+        application_with_one_connection.currency
+    )
+    tx_hash = "FCAD5A388AC8A811B45A9334A375585E77071AA9F6E5B6896582961A6C66F365"
+
+    # add a transaction in bob tx history
+    transactions_repo = TransactionsRepo(meta_repo.conn)
+    transactions_repo.insert(
+        Transaction(
+            "testcurrency",
+            bob.key.pubkey,
+            tx_hash,
+            20,
+            "15-76543400E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67",
+            median_time,
+            "H41/8OGV2W4CLKbE35kk5t1HJQsb3jEM0/QGLUf80CwJvGZf3HvVCcNtHPUFoUBKEDQO9mPK3KJkqOoxHpqHCw==",
+            alice.key.pubkey,
+            bob.key.pubkey,
+            1565,
+            1,
+            "",
+            0,
+            Transaction.VALIDATED,
+        )
+    )
+    transactions_repo.insert(
+        Transaction(
+            "testcurrency",
+            alice.key.pubkey,
+            tx_hash,
+            20,
+            "15-76543400E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67",
+            median_time,
+            "H41/8OGV2W4CLKbE35kk5t1HJQsb3jEM0/QGLUf80CwJvGZf3HvVCcNtHPUFoUBKEDQO9mPK3KJkqOoxHpqHCw==",
+            alice.key.pubkey,
+            bob.key.pubkey,
+            1565,
+            1,
+            "",
+            0,
+            Transaction.VALIDATED,
+        )
+    )
+    # test simple signature condition
+    condition = output.Condition.token(output.SIG.token(bob.key.pubkey),)
+    # bob can spend this source
+    assert (
+        application_with_one_connection.documents_service.evaluate_condition(
+            application_with_one_connection.currency, condition, [bob.key], [], tx_hash
+        )
+        is True
+    )
+    # alice can not
+    assert (
+        application_with_one_connection.documents_service.evaluate_condition(
+            application_with_one_connection.currency,
+            condition,
+            [alice.key],
+            [],
+            tx_hash,
+        )
+        is False
+    )
+
+
+def test_evaluate_condition_source_lock_mode_1(
+    application_with_one_connection, bob, alice, meta_repo
+):
+    application_with_one_connection.instanciate_services()
+
+    # capture blockchain median time
+    median_time = application_with_one_connection.blockchain_service._blockchain_processor.time(
+        application_with_one_connection.currency
+    )
+    tx_hash = "FCAD5A388AC8A811B45A9334A375585E77071AA9F6E5B6896582961A6C66F365"
+
+    # add a transaction in bob tx history
+    transactions_repo = TransactionsRepo(meta_repo.conn)
+    transactions_repo.insert(
+        Transaction(
+            "testcurrency",
+            bob.key.pubkey,
+            tx_hash,
+            20,
+            "15-76543400E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67",
+            median_time,
+            "H41/8OGV2W4CLKbE35kk5t1HJQsb3jEM0/QGLUf80CwJvGZf3HvVCcNtHPUFoUBKEDQO9mPK3KJkqOoxHpqHCw==",
+            alice.key.pubkey,
+            bob.key.pubkey,
+            1565,
+            1,
+            "",
+            0,
+            Transaction.VALIDATED,
+        )
+    )
+    transactions_repo.insert(
+        Transaction(
+            "testcurrency",
+            alice.key.pubkey,
+            tx_hash,
+            20,
+            "15-76543400E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67",
+            median_time,
+            "H41/8OGV2W4CLKbE35kk5t1HJQsb3jEM0/QGLUf80CwJvGZf3HvVCcNtHPUFoUBKEDQO9mPK3KJkqOoxHpqHCw==",
+            alice.key.pubkey,
+            bob.key.pubkey,
+            1565,
+            1,
+            "",
+            0,
+            Transaction.VALIDATED,
+        )
+    )
+
+    # test condition: receiver or (issuer and CSV(one week))
+    condition = output.Condition.token(
+        output.SIG.token(bob.key.pubkey),
+        output.Operator.token("||"),
+        output.Condition.token(
+            output.SIG.token(alice.key.pubkey),
+            output.Operator.token("&&"),
+            output.CSV.token(604800),
+        ),
+    )
+    # bob try to spend his source
+    assert (
+        application_with_one_connection.documents_service.evaluate_condition(
+            application_with_one_connection.currency, condition, [bob.key], [], tx_hash
+        )
+        is True
+    )
+    # alice try to get back this source before the CSV delay
+    assert (
+        application_with_one_connection.documents_service.evaluate_condition(
+            application_with_one_connection.currency,
+            condition,
+            [alice.key],
+            [],
+            tx_hash,
+        )
+        is False
+    )
+
+    # Transaction was made one week ago...
+    transactions_repo.update(
+        Transaction(
+            "testcurrency",
+            bob.key.pubkey,
+            tx_hash,
+            20,
+            "15-76543400E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67",
+            median_time - 604800,
+            "H41/8OGV2W4CLKbE35kk5t1HJQsb3jEM0/QGLUf80CwJvGZf3HvVCcNtHPUFoUBKEDQO9mPK3KJkqOoxHpqHCw==",
+            alice.key.pubkey,
+            bob.key.pubkey,
+            1565,
+            1,
+            "",
+            0,
+            Transaction.VALIDATED,
+        )
+    )
+    transactions_repo.update(
+        Transaction(
+            "testcurrency",
+            alice.key.pubkey,
+            tx_hash,
+            20,
+            "15-76543400E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67",
+            median_time - 604800,
+            "H41/8OGV2W4CLKbE35kk5t1HJQsb3jEM0/QGLUf80CwJvGZf3HvVCcNtHPUFoUBKEDQO9mPK3KJkqOoxHpqHCw==",
+            alice.key.pubkey,
+            bob.key.pubkey,
+            1565,
+            1,
+            "",
+            0,
+            Transaction.VALIDATED,
+        )
+    )
+    tx = transactions_repo.get_one(sha_hash=tx_hash)
+    assert tx.timestamp == median_time - 604800
+
+    # bob try to spend his source
+    assert (
+        application_with_one_connection.documents_service.evaluate_condition(
+            application_with_one_connection.currency, condition, [bob.key], [], tx_hash
+        )
+        is True
+    )
+    # alice can get back this source after the CSV delay
+    assert (
+        application_with_one_connection.documents_service.evaluate_condition(
+            application_with_one_connection.currency,
+            condition,
+            [alice.key],
+            [],
+            tx_hash,
+        )
+        is True
+    )
+
+
+def test_evaluate_condition_source_multisig(
+    application_with_one_connection, bob, alice, meta_repo
+):
+    application_with_one_connection.instanciate_services()
+
+    # capture blockchain median time
+    median_time = application_with_one_connection.blockchain_service._blockchain_processor.time(
+        application_with_one_connection.currency
+    )
+    tx_hash = "FCAD5A388AC8A811B45A9334A375585E77071AA9F6E5B6896582961A6C66F365"
+
+    # add a transaction in bob tx history
+    transactions_repo = TransactionsRepo(meta_repo.conn)
+    transactions_repo.insert(
+        Transaction(
+            "testcurrency",
+            bob.key.pubkey,
+            tx_hash,
+            20,
+            "15-76543400E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67",
+            median_time,
+            "H41/8OGV2W4CLKbE35kk5t1HJQsb3jEM0/QGLUf80CwJvGZf3HvVCcNtHPUFoUBKEDQO9mPK3KJkqOoxHpqHCw==",
+            alice.key.pubkey,
+            bob.key.pubkey,
+            1565,
+            1,
+            "",
+            0,
+            Transaction.VALIDATED,
+        )
+    )
+    transactions_repo.insert(
+        Transaction(
+            "testcurrency",
+            alice.key.pubkey,
+            tx_hash,
+            20,
+            "15-76543400E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67",
+            median_time,
+            "H41/8OGV2W4CLKbE35kk5t1HJQsb3jEM0/QGLUf80CwJvGZf3HvVCcNtHPUFoUBKEDQO9mPK3KJkqOoxHpqHCw==",
+            alice.key.pubkey,
+            bob.key.pubkey,
+            1565,
+            1,
+            "",
+            0,
+            Transaction.VALIDATED,
+        )
+    )
+
+    # test condition: multi signatures
+    condition = output.Condition.token(
+        output.SIG.token(bob.key.pubkey),
+        output.Operator.token("&&"),
+        output.SIG.token(alice.key.pubkey),
+    )
+    # bob can not spend this source alone
+    assert (
+        application_with_one_connection.documents_service.evaluate_condition(
+            application_with_one_connection.currency, condition, [bob.key], [], tx_hash
+        )
+        is False
+    )
+    # alice can not spend this source alone
+    assert (
+        application_with_one_connection.documents_service.evaluate_condition(
+            application_with_one_connection.currency,
+            condition,
+            [alice.key],
+            [],
+            tx_hash,
+        )
+        is False
+    )
+    # alice && bob together only can spend this source
+    assert (
+        application_with_one_connection.documents_service.evaluate_condition(
+            application_with_one_connection.currency,
+            condition,
+            [alice.key, bob.key],
+            [],
+            tx_hash,
+        )
+        is True
+    )
+
+
+def test_evaluate_condition_source_atomic_swap(
+    application_with_one_connection, bob, alice, meta_repo
+):
+    application_with_one_connection.instanciate_services()
+    transactions_repo = TransactionsRepo(meta_repo.conn)
+
+    # capture blockchain median time
+    median_time = application_with_one_connection.blockchain_service._blockchain_processor.time(
+        application_with_one_connection.currency
+    )
+
+    tx1_hash = "FCAD5A388AC8A811B45A9334A375585E77071AA9F6E5B6896582961A6C66F365"
+    # add TX1 transaction in alice tx history
+    transactions_repo.insert(
+        Transaction(
+            "testcurrency",
+            alice.key.pubkey,  # alice history
+            tx1_hash,
+            20,
+            "15-76543400E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67",
+            median_time,
+            "H41/8OGV2W4CLKbE35kk5t1HJQsb3jEM0/QGLUf80CwJvGZf3HvVCcNtHPUFoUBKEDQO9mPK3KJkqOoxHpqHCw==",
+            alice.key.pubkey,  # do not care
+            bob.key.pubkey,  # do not care
+            1565,
+            1,
+            "",
+            0,
+            Transaction.VALIDATED,
+        )
+    )
+    # add TX1 transaction in bob tx history
+    transactions_repo.insert(
+        Transaction(
+            "testcurrency",
+            bob.key.pubkey,  # bob history
+            tx1_hash,
+            20,
+            "15-76543400E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67",
+            median_time,
+            "H41/8OGV2W4CLKbE35kk5t1HJQsb3jEM0/QGLUf80CwJvGZf3HvVCcNtHPUFoUBKEDQO9mPK3KJkqOoxHpqHCw==",
+            alice.key.pubkey,  # do not care
+            bob.key.pubkey,  # do not care
+            1565,
+            1,
+            "",
+            0,
+            Transaction.VALIDATED,
+        )
+    )
+
+    # atomic swap initiator TX1 condition created by alice
+    # (XHX(password) && SIG(bob)) || (SIG(alice) && SIG(bob)) || (SIG(alice) && CSV(48h))
+    password = "test".encode("utf8")  # password must be encoded in str not unicode
+    hash_password = sha256(password).hexdigest().upper()
+    tx1_condition = output.Condition.token(
+        output.Condition.token(
+            output.Condition.token(
+                output.XHX.token(hash_password),
+                output.Operator.token("&&"),
+                output.SIG.token(bob.key.pubkey),
+            ),
+            output.Operator.token("||"),
+            output.Condition.token(
+                output.SIG.token(alice.key.pubkey),
+                output.Operator.token("&&"),
+                output.SIG.token(bob.key.pubkey),
+            ),
+        ),
+        output.Operator.token("||"),
+        output.Condition.token(
+            output.SIG.token(alice.key.pubkey),
+            output.Operator.token("&&"),
+            output.CSV.token(172800),
+        ),
+    )
+
+    tx2_hash = "ACAB5A388AC8A811B45A9334A375585E77071AA9F6E5B6896582961A6C66F365"
+    # add TX2 transaction in alice tx history
+    transactions_repo.insert(
+        Transaction(
+            "testcurrency",
+            alice.key.pubkey,  # alice history
+            tx2_hash,
+            20,
+            "15-76543400E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67",
+            median_time,
+            "H41/8OGV2W4CLKbE35kk5t1HJQsb3jEM0/QGLUf80CwJvGZf3HvVCcNtHPUFoUBKEDQO9mPK3KJkqOoxHpqHCw==",
+            alice.key.pubkey,  # do not care
+            bob.key.pubkey,  # do not care
+            1565,
+            1,
+            "",
+            0,
+            Transaction.VALIDATED,
+        )
+    )
+    # add TX2 transaction in bob tx history
+    transactions_repo.insert(
+        Transaction(
+            "testcurrency",
+            bob.key.pubkey,  # bob history
+            tx2_hash,
+            20,
+            "15-76543400E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67",
+            median_time,
+            "H41/8OGV2W4CLKbE35kk5t1HJQsb3jEM0/QGLUf80CwJvGZf3HvVCcNtHPUFoUBKEDQO9mPK3KJkqOoxHpqHCw==",
+            alice.key.pubkey,  # do not care
+            bob.key.pubkey,  # do not care
+            1565,
+            1,
+            "",
+            0,
+            Transaction.VALIDATED,
+        )
+    )
+
+    # test atomic swap participant TX2 condition created by bob with alice password hash
+    # (XHX(password) && SIG(alice)) || (SIG(alice) && SIG(bob)) || (SIG(bob) && CSV(24h))
+    tx2_condition = output.Condition.token(
+        output.Condition.token(
+            output.Condition.token(
+                output.XHX.token(hash_password),
+                output.Operator.token("&&"),
+                output.SIG.token(alice.key.pubkey),
+            ),
+            output.Operator.token("||"),
+            output.Condition.token(
+                output.SIG.token(alice.key.pubkey),
+                output.Operator.token("&&"),
+                output.SIG.token(bob.key.pubkey),
+            ),
+        ),
+        output.Operator.token("||"),
+        output.Condition.token(
+            output.SIG.token(bob.key.pubkey),
+            output.Operator.token("&&"),
+            output.CSV.token(86400),
+        ),
+    )
+
+    # alice spend the source from tx2 with the password
+    assert (
+        application_with_one_connection.documents_service.evaluate_condition(
+            application_with_one_connection.currency,
+            tx2_condition,
+            [alice.key],
+            [password],
+            tx2_hash,
+        )
+        is True
+    )
+
+    # the password is revealed in the unlock of the tx3 spending tx2
+    # bob can now spend tx1 using the password
+    assert (
+        application_with_one_connection.documents_service.evaluate_condition(
+            application_with_one_connection.currency,
+            tx1_condition,
+            [bob.key],
+            [password],
+            tx1_hash,
+        )
+        is True
+    )
+
+    # alice and bob can sign together to spend tx1
+    assert (
+        application_with_one_connection.documents_service.evaluate_condition(
+            application_with_one_connection.currency,
+            tx1_condition,
+            [bob.key, alice.key],
+            [password],
+            tx1_hash,
+        )
+        is True
+    )
+
+    # alice and bob can sign together to spend tx2
+    assert (
+        application_with_one_connection.documents_service.evaluate_condition(
+            application_with_one_connection.currency,
+            tx2_condition,
+            [bob.key, alice.key],
+            [password],
+            tx2_hash,
+        )
+        is True
+    )
+
+    # alice can not spend the source from tx2 without the password
+    assert (
+        application_with_one_connection.documents_service.evaluate_condition(
+            application_with_one_connection.currency,
+            tx2_condition,
+            [alice.key],
+            [],
+            tx2_hash,
+        )
+        is False
+    )
+
+    # bob can not spend tx1 without the password
+    assert (
+        application_with_one_connection.documents_service.evaluate_condition(
+            application_with_one_connection.currency,
+            tx1_condition,
+            [bob.key],
+            [],
+            tx2_hash,
+        )
+        is False
+    )
+
+    # TX1 Transaction was made 48h ago...
+    # update TX1 transaction in alice tx history
+    transactions_repo.update(
+        Transaction(
+            "testcurrency",
+            alice.key.pubkey,  # alice history
+            tx1_hash,
+            20,
+            "15-76543400E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67",
+            median_time - 172800,
+            "H41/8OGV2W4CLKbE35kk5t1HJQsb3jEM0/QGLUf80CwJvGZf3HvVCcNtHPUFoUBKEDQO9mPK3KJkqOoxHpqHCw==",
+            alice.key.pubkey,  # do not care
+            bob.key.pubkey,  # do not care
+            1565,
+            1,
+            "",
+            0,
+            Transaction.VALIDATED,
+        )
+    )
+    # update TX1 transaction in bob tx history
+    transactions_repo.update(
+        Transaction(
+            "testcurrency",
+            bob.key.pubkey,  # bob history
+            tx1_hash,
+            20,
+            "15-76543400E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67",
+            median_time - 172800,
+            "H41/8OGV2W4CLKbE35kk5t1HJQsb3jEM0/QGLUf80CwJvGZf3HvVCcNtHPUFoUBKEDQO9mPK3KJkqOoxHpqHCw==",
+            alice.key.pubkey,  # do not care
+            bob.key.pubkey,  # do not care
+            1565,
+            1,
+            "",
+            0,
+            Transaction.VALIDATED,
+        )
+    )
+
+    # TX2 Transaction was made 24h ago...
+    # update TX2 transaction in alice tx history
+    transactions_repo.update(
+        Transaction(
+            "testcurrency",
+            alice.key.pubkey,  # alice history
+            tx2_hash,
+            20,
+            "15-76543400E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67",
+            median_time - 86400,
+            "H41/8OGV2W4CLKbE35kk5t1HJQsb3jEM0/QGLUf80CwJvGZf3HvVCcNtHPUFoUBKEDQO9mPK3KJkqOoxHpqHCw==",
+            alice.key.pubkey,  # do not care
+            bob.key.pubkey,  # do not care
+            1565,
+            1,
+            "",
+            0,
+            Transaction.VALIDATED,
+        )
+    )
+    # update TX2 transaction in bob tx history
+    transactions_repo.update(
+        Transaction(
+            "testcurrency",
+            bob.key.pubkey,  # bob history
+            tx2_hash,
+            20,
+            "15-76543400E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67",
+            median_time - 86400,
+            "H41/8OGV2W4CLKbE35kk5t1HJQsb3jEM0/QGLUf80CwJvGZf3HvVCcNtHPUFoUBKEDQO9mPK3KJkqOoxHpqHCw==",
+            alice.key.pubkey,  # do not care
+            bob.key.pubkey,  # do not care
+            1565,
+            1,
+            "",
+            0,
+            Transaction.VALIDATED,
+        )
+    )
+
+    # alice can get back the source from tx1 without the password after 48h
+    assert (
+        application_with_one_connection.documents_service.evaluate_condition(
+            application_with_one_connection.currency,
+            tx1_condition,
+            [alice.key],
+            [],
+            tx1_hash,
+        )
+        is True
+    )
+
+    # bob can spend tx2 without the password after 24h
+    assert (
+        application_with_one_connection.documents_service.evaluate_condition(
+            application_with_one_connection.currency,
+            tx2_condition,
+            [bob.key],
+            [],
+            tx2_hash,
+        )
+        is True
+    )