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

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
Branches
Tags
No related merge requests found
Pipeline #3546 passed
...@@ -141,17 +141,17 @@ class OutputSource: ...@@ -141,17 +141,17 @@ class OutputSource:
""" """
re_inline = re.compile("([0-9]+):([0-9]+):(.*)\n") 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 Init OutputSource instance
:param amount: Amount of the output :param amount: Amount of the output
:param base: Base number :param base: Base number
:param conditions: Conditions expression :param condition: Condition expression
""" """
self.amount = amount self.amount = amount
self.base = base self.base = base
self.conditions = conditions self.condition = self.condition_from_text(condition)
@classmethod @classmethod
def from_inline(cls: Type[OutputSourceType], inline: str) -> OutputSourceType: def from_inline(cls: Type[OutputSourceType], inline: str) -> OutputSourceType:
...@@ -166,14 +166,9 @@ class OutputSource: ...@@ -166,14 +166,9 @@ class OutputSource:
raise MalformedDocumentError("Inline output") raise MalformedDocumentError("Inline output")
amount = int(data.group(1)) amount = int(data.group(1))
base = int(data.group(2)) base = int(data.group(2))
conditions_text = data.group(3) condition_text = data.group(3)
try:
conditions = pypeg2.parse(conditions_text, output.Condition) return cls(amount, base, condition_text)
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)
def inline(self) -> str: def inline(self) -> str:
""" """
...@@ -181,11 +176,24 @@ class OutputSource: ...@@ -181,11 +176,24 @@ class OutputSource:
:return: :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, return "{0}:{1}:{2}".format(self.amount, self.base,
pypeg2.compose(self.conditions, output.Condition)) 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 # required to type hint cls in classmethod
...@@ -759,7 +767,7 @@ class SimpleTransaction(Transaction): ...@@ -759,7 +767,7 @@ class SimpleTransaction(Transaction):
simple "SIG" functions, and the outputs must be simple simple "SIG" functions, and the outputs must be simple
SIG conditions. SIG conditions.
:param duniterpy.documents.Transaction tx: the transaction to check :param tx: the transaction to check
:return: True if a simple transaction :return: True if a simple transaction
""" """
...@@ -772,12 +780,11 @@ class SimpleTransaction(Transaction): ...@@ -772,12 +780,11 @@ class SimpleTransaction(Transaction):
elif type(unlock.parameters[0]) is not SIGParameter: elif type(unlock.parameters[0]) is not SIGParameter:
simple = False simple = False
for o in tx.outputs: for o in tx.outputs:
# If condition is str type, it is unlockable # if right condition is not None...
if type(o.conditions) is str: if getattr('right', o.condition, None):
simple = False
else:
if getattr('right', o.conditions, None):
simple = False simple = False
elif type(o.conditions.left) is not output.SIG: # if left is not SIG...
elif type(o.condition.left) is not output.SIG:
simple = False simple = False
return simple return simple
...@@ -5,7 +5,6 @@ from duniterpy.api import bma ...@@ -5,7 +5,6 @@ from duniterpy.api import bma
from duniterpy.api.client import Client from duniterpy.api.client import Client
from duniterpy.documents import BlockUID, Transaction from duniterpy.documents import BlockUID, Transaction
from duniterpy.documents.transaction import InputSource, OutputSource, Unlock, SIGParameter from duniterpy.documents.transaction import InputSource, OutputSource, Unlock, SIGParameter
from duniterpy.grammars.output import Condition, SIG
from duniterpy.key import SigningKey from duniterpy.key import SigningKey
# CONFIG ####################################### # CONFIG #######################################
...@@ -61,12 +60,7 @@ def get_transaction_document(current_block: dict, source: dict, from_pubkey: str ...@@ -61,12 +60,7 @@ def get_transaction_document(current_block: dict, source: dict, from_pubkey: str
# lists of outputs # lists of outputs
outputs = [ outputs = [
OutputSource( OutputSource(amount=source['amount'], base=source['base'], condition="SIG({0})".format(to_pubkey))
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))
)
] ]
transaction = Transaction( transaction = Transaction(
...@@ -79,7 +73,7 @@ def get_transaction_document(current_block: dict, source: dict, from_pubkey: str ...@@ -79,7 +73,7 @@ def get_transaction_document(current_block: dict, source: dict, from_pubkey: str
unlocks=unlocks, unlocks=unlocks,
outputs=outputs, outputs=outputs,
comment='', comment='',
signatures=None signatures=[]
) )
return transaction return transaction
......
...@@ -191,13 +191,13 @@ class Test_Transaction(unittest.TestCase): ...@@ -191,13 +191,13 @@ class Test_Transaction(unittest.TestCase):
self.assertEqual(tx.outputs[0].amount, 120) self.assertEqual(tx.outputs[0].amount, 120)
self.assertEqual(tx.outputs[0].base, 2) 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].amount, 146)
self.assertEqual(tx.outputs[1].base, 2) 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].amount, 49)
self.assertEqual(tx.outputs[2].base, 2) 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?)") self.assertEqual(tx.comment, "-----@@@----- (why not this comment?)")
...@@ -225,12 +225,12 @@ class Test_Transaction(unittest.TestCase): ...@@ -225,12 +225,12 @@ class Test_Transaction(unittest.TestCase):
self.assertEqual(tx.outputs[0].amount, 90) self.assertEqual(tx.outputs[0].amount, 90)
self.assertEqual(tx.outputs[0].base, 0) self.assertEqual(tx.outputs[0].base, 0)
self.assertEqual(pypeg2.compose(tx.outputs[0].conditions, output.Condition), "SIG(5zDvFjJB1PGDQNiExpfzL9c1tQGs6xPA8mf1phr3VoVi)") self.assertEqual(pypeg2.compose(tx.outputs[0].condition, output.Condition), "SIG(5zDvFjJB1PGDQNiExpfzL9c1tQGs6xPA8mf1phr3VoVi)")
self.assertEqual(type(tx.outputs[0].conditions.left), output.SIG) self.assertEqual(type(tx.outputs[0].condition.left), output.SIG)
self.assertEqual(tx.outputs[1].amount, 10) self.assertEqual(tx.outputs[1].amount, 10)
self.assertEqual(tx.outputs[1].base, 0) self.assertEqual(tx.outputs[1].base, 0)
self.assertEqual(pypeg2.compose(tx.outputs[1].conditions, output.Condition), "SIG(GNPdPNwSJAYw7ixkDeibo3YpdELgLmrZ2Q86HF4cyg92)") self.assertEqual(pypeg2.compose(tx.outputs[1].condition, output.Condition), "SIG(GNPdPNwSJAYw7ixkDeibo3YpdELgLmrZ2Q86HF4cyg92)")
self.assertEqual(type(tx.outputs[1].conditions.left), output.SIG) self.assertEqual(type(tx.outputs[1].condition.left), output.SIG)
self.assertEqual(tx.signatures[0], "XDQeEMcJDd+XVGaFIZc8d4kKRJgsPuWAPVNG5UKNk8mDZx2oE1kTP/hbxiFx6yDouBELCswuf/X6POK9ES7JCA==") self.assertEqual(tx.signatures[0], "XDQeEMcJDd+XVGaFIZc8d4kKRJgsPuWAPVNG5UKNk8mDZx2oE1kTP/hbxiFx6yDouBELCswuf/X6POK9ES7JCA==")
def test_fromraw(self): def test_fromraw(self):
...@@ -283,13 +283,13 @@ class Test_Transaction(unittest.TestCase): ...@@ -283,13 +283,13 @@ class Test_Transaction(unittest.TestCase):
self.assertEqual(tx.outputs[0].amount, 120) self.assertEqual(tx.outputs[0].amount, 120)
self.assertEqual(tx.outputs[0].base, 2) 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].amount, 146)
self.assertEqual(tx.outputs[1].base, 2) 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].amount, 49)
self.assertEqual(tx.outputs[2].base, 2) 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?)") self.assertEqual(tx.comment, "-----@@@----- (why not this comment?)")
...@@ -350,13 +350,13 @@ class Test_Transaction(unittest.TestCase): ...@@ -350,13 +350,13 @@ class Test_Transaction(unittest.TestCase):
self.assertEqual(tx.outputs[0].amount, 120) self.assertEqual(tx.outputs[0].amount, 120)
self.assertEqual(tx.outputs[0].base, 2) 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].amount, 146)
self.assertEqual(tx.outputs[1].base, 2) 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].amount, 49)
self.assertEqual(tx.outputs[2].base, 2) 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?)") self.assertEqual(tx.comment, "-----@@@----- (why not this comment?)")
...@@ -419,13 +419,13 @@ class Test_Transaction(unittest.TestCase): ...@@ -419,13 +419,13 @@ class Test_Transaction(unittest.TestCase):
self.assertEqual(tx.outputs[0].amount, 120) self.assertEqual(tx.outputs[0].amount, 120)
self.assertEqual(tx.outputs[0].base, 2) 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].amount, 146)
self.assertEqual(tx.outputs[1].base, 2) 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].amount, 49)
self.assertEqual(tx.outputs[2].base, 2) 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?)") self.assertEqual(tx.comment, "-----@@@----- (why not this comment?)")
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment