Commit ccc75d2f authored by Vincent Texier's avatar Vincent Texier

issue #52 fix type hint problem in outputSource.conditions (BC broken)

Output instances in transactions get condition argument as text only now, and check grammar before storing condition as Condition instance.
parent d9019635
Pipeline #3546 passed with stages
in 1 minute and 44 seconds
......@@ -141,17 +141,17 @@ class OutputSource:
"""
re_inline = re.compile("([0-9]+):([0-9]+):(.*)\n")
def __init__(self, amount: int, base: int, conditions: Union[str, Condition]) -> None:
def __init__(self, amount: int, base: int, condition: str) -> None:
"""
Init OutputSource instance
:param amount: Amount of the output
:param base: Base number
:param conditions: Conditions expression
:param condition: Condition expression
"""
self.amount = amount
self.base = base
self.conditions = conditions
self.condition = self.condition_from_text(condition)
@classmethod
def from_inline(cls: Type[OutputSourceType], inline: str) -> OutputSourceType:
......@@ -166,14 +166,9 @@ class OutputSource:
raise MalformedDocumentError("Inline output")
amount = int(data.group(1))
base = int(data.group(2))
conditions_text = data.group(3)
try:
conditions = pypeg2.parse(conditions_text, output.Condition)
except SyntaxError:
# Invalid conditions are possible, see https://github.com/duniter/duniter/issues/1156
# In such a case, they are store "as-is" and considered unlockable
conditions = conditions_text
return cls(amount, base, conditions)
condition_text = data.group(3)
return cls(amount, base, condition_text)
def inline(self) -> str:
"""
......@@ -181,11 +176,24 @@ class OutputSource:
:return:
"""
if type(self.conditions) is str:
return "{0}:{1}:{2}".format(self.amount, self.base, self.conditions)
else:
return "{0}:{1}:{2}".format(self.amount, self.base,
pypeg2.compose(self.conditions, output.Condition))
return "{0}:{1}:{2}".format(self.amount, self.base,
pypeg2.compose(self.condition, output.Condition))
@staticmethod
def condition_from_text(text) -> Condition:
"""
Return a Condition instance with PEG grammar from text
:param text: PEG parsable string
:return:
"""
try:
condition = pypeg2.parse(text, output.Condition)
except SyntaxError:
# Invalid conditions are possible, see https://github.com/duniter/duniter/issues/1156
# In such a case, they are store as empty PEG grammar object and considered unlockable
condition = Condition(text)
return condition
# required to type hint cls in classmethod
......@@ -759,7 +767,7 @@ class SimpleTransaction(Transaction):
simple "SIG" functions, and the outputs must be simple
SIG conditions.
:param duniterpy.documents.Transaction tx: the transaction to check
:param tx: the transaction to check
:return: True if a simple transaction
"""
......@@ -772,12 +780,11 @@ class SimpleTransaction(Transaction):
elif type(unlock.parameters[0]) is not SIGParameter:
simple = False
for o in tx.outputs:
# If condition is str type, it is unlockable
if type(o.conditions) is str:
# if right condition is not None...
if getattr('right', o.condition, None):
simple = False
else:
if getattr('right', o.conditions, None):
simple = False
elif type(o.conditions.left) is not output.SIG:
simple = False
# if left is not SIG...
elif type(o.condition.left) is not output.SIG:
simple = False
return simple
......@@ -5,7 +5,6 @@ from duniterpy.api import bma
from duniterpy.api.client import Client
from duniterpy.documents import BlockUID, Transaction
from duniterpy.documents.transaction import InputSource, OutputSource, Unlock, SIGParameter
from duniterpy.grammars.output import Condition, SIG
from duniterpy.key import SigningKey
# CONFIG #######################################
......@@ -61,12 +60,7 @@ def get_transaction_document(current_block: dict, source: dict, from_pubkey: str
# lists of outputs
outputs = [
OutputSource(
amount=source['amount'],
base=source['base'],
# only the receiver of the output can use it as input in another transaction
conditions=Condition.token(SIG.token(to_pubkey))
)
OutputSource(amount=source['amount'], base=source['base'], condition="SIG({0})".format(to_pubkey))
]
transaction = Transaction(
......@@ -79,7 +73,7 @@ def get_transaction_document(current_block: dict, source: dict, from_pubkey: str
unlocks=unlocks,
outputs=outputs,
comment='',
signatures=None
signatures=[]
)
return transaction
......
......@@ -191,13 +191,13 @@ class Test_Transaction(unittest.TestCase):
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(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].conditions, output.Condition), "SIG(DSz4rgncXCytsUMW2JU2yhLquZECD2XpEkpP9gG5HyAx)")
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].conditions, output.Condition), "(SIG(6DyGr5LFtFmbaJYRvcs9WmBsr4cbJbJ1EV9zBbqG7A6i) || XHX(8FAA0ED653CA4D2C1156D511F0D0036F5168ABA4DAC2929676D279C8A2A12E36))")
self.assertEqual(pypeg2.compose(tx.outputs[2].condition, output.Condition), "(SIG(6DyGr5LFtFmbaJYRvcs9WmBsr4cbJbJ1EV9zBbqG7A6i) || XHX(8FAA0ED653CA4D2C1156D511F0D0036F5168ABA4DAC2929676D279C8A2A12E36))")
self.assertEqual(tx.comment, "-----@@@----- (why not this comment?)")
......@@ -225,12 +225,12 @@ class Test_Transaction(unittest.TestCase):
self.assertEqual(tx.outputs[0].amount, 90)
self.assertEqual(tx.outputs[0].base, 0)
self.assertEqual(pypeg2.compose(tx.outputs[0].conditions, output.Condition), "SIG(5zDvFjJB1PGDQNiExpfzL9c1tQGs6xPA8mf1phr3VoVi)")
self.assertEqual(type(tx.outputs[0].conditions.left), output.SIG)
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].conditions, output.Condition), "SIG(GNPdPNwSJAYw7ixkDeibo3YpdELgLmrZ2Q86HF4cyg92)")
self.assertEqual(type(tx.outputs[1].conditions.left), output.SIG)
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):
......@@ -283,13 +283,13 @@ class Test_Transaction(unittest.TestCase):
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(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].conditions, output.Condition), "SIG(DSz4rgncXCytsUMW2JU2yhLquZECD2XpEkpP9gG5HyAx)")
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].conditions, output.Condition), "(SIG(6DyGr5LFtFmbaJYRvcs9WmBsr4cbJbJ1EV9zBbqG7A6i) || XHX(8FAA0ED653CA4D2C1156D511F0D0036F5168ABA4DAC2929676D279C8A2A12E36))")
self.assertEqual(pypeg2.compose(tx.outputs[2].condition, output.Condition), "(SIG(6DyGr5LFtFmbaJYRvcs9WmBsr4cbJbJ1EV9zBbqG7A6i) || XHX(8FAA0ED653CA4D2C1156D511F0D0036F5168ABA4DAC2929676D279C8A2A12E36))")
self.assertEqual(tx.comment, "-----@@@----- (why not this comment?)")
......@@ -350,13 +350,13 @@ class Test_Transaction(unittest.TestCase):
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(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].conditions, output.Condition), "SIG(DSz4rgncXCytsUMW2JU2yhLquZECD2XpEkpP9gG5HyAx)")
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].conditions, output.Condition), "(SIG(6DyGr5LFtFmbaJYRvcs9WmBsr4cbJbJ1EV9zBbqG7A6i) || XHX(8FAA0ED653CA4D2C1156D511F0D0036F5168ABA4DAC2929676D279C8A2A12E36))")
self.assertEqual(pypeg2.compose(tx.outputs[2].condition, output.Condition), "(SIG(6DyGr5LFtFmbaJYRvcs9WmBsr4cbJbJ1EV9zBbqG7A6i) || XHX(8FAA0ED653CA4D2C1156D511F0D0036F5168ABA4DAC2929676D279C8A2A12E36))")
self.assertEqual(tx.comment, "-----@@@----- (why not this comment?)")
......@@ -419,13 +419,13 @@ class Test_Transaction(unittest.TestCase):
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(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].conditions, output.Condition), "SIG(DSz4rgncXCytsUMW2JU2yhLquZECD2XpEkpP9gG5HyAx)")
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].conditions, output.Condition), "(SIG(6DyGr5LFtFmbaJYRvcs9WmBsr4cbJbJ1EV9zBbqG7A6i) || XHX(8FAA0ED653CA4D2C1156D511F0D0036F5168ABA4DAC2929676D279C8A2A12E36))")
self.assertEqual(pypeg2.compose(tx.outputs[2].condition, output.Condition), "(SIG(6DyGr5LFtFmbaJYRvcs9WmBsr4cbJbJ1EV9zBbqG7A6i) || XHX(8FAA0ED653CA4D2C1156D511F0D0036F5168ABA4DAC2929676D279C8A2A12E36))")
self.assertEqual(tx.comment, "-----@@@----- (why not this comment?)")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment