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

[fix] #798 add condition evaluation on automatic sources when creating a transaction

This is to avoid using locked sources

Need all the tx referenced by the sources in the db !

Fix the previous commit that add complex and potentially locked sources in db
parent e2313e7d
Branches
Tags
1 merge request!778Release 0.51.0
......@@ -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
......
......@@ -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):
......
......@@ -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 = []
......
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
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
)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment