diff --git a/duniterpy/api/bma/wot.py b/duniterpy/api/bma/wot.py index fc756c54aef236677047edea5b4aeb437bd5e1a2..a96e6dfef4c4203382ac29eb8649f169e82e982c 100644 --- a/duniterpy/api/bma/wot.py +++ b/duniterpy/api/bma/wot.py @@ -50,8 +50,7 @@ class Revoke(WOT): """POST Public key data.""" async def __post__(self, session, **kwargs): - assert 'pubkey' in kwargs - assert 'self_' in kwargs + assert 'revocation' in kwargs r = await self.requests_post(session, '/revoke', **kwargs) return r diff --git a/duniterpy/documents/__init__.py b/duniterpy/documents/__init__.py index dec8379a1dfb057b1175447d0a193bcac626ab08..a976b3a6e4f6df56b7ef4f3176c44aa57986d625 100644 --- a/duniterpy/documents/__init__.py +++ b/duniterpy/documents/__init__.py @@ -1,5 +1,5 @@ from .block import Block, BlockUID -from .certification import SelfCertification, Certification, Revokation +from .certification import SelfCertification, Certification, Revocation from .membership import Membership from .peer import Endpoint, BMAEndpoint, UnknownEndpoint, Peer from .transaction import SimpleTransaction, Transaction diff --git a/duniterpy/documents/block.py b/duniterpy/documents/block.py index b5977d9384827b5e45f57a79eda35de1f5fd28bc..09f2095eaec1bae47edda45f1dd5eeb004383ad1 100644 --- a/duniterpy/documents/block.py +++ b/duniterpy/documents/block.py @@ -1,5 +1,5 @@ from .document import Document, MalformedDocumentError -from .certification import SelfCertification, Certification, Revokation +from .certification import SelfCertification, Certification, Revocation from .membership import Membership from .transaction import Transaction from .constants import pubkey_regex, block_id_regex, block_hash_regex @@ -184,7 +184,7 @@ The class Block handles Block documents. :param list[duniterpy.documents.Membership] joiners: the joiners memberships via "IN" documents :param list[duniterpy.documents.Membership] actives: renewed memberships via "IN" documents :param list[duniterpy.documents.Membership] leavers: the leavers memberships via "OUT" documents - :param list[duniterpy.documents.Revokation] revokations: revokations + :param list[duniterpy.documents.Revocation] revokations: revokations :param list[duniterpy.documents.Membership] excluded: members excluded because of missing certifications :param list[duniterpy.documents.Membership] actives: renewed memberships via "IN" documents :param list[duniterpy.documents.Certification] certifications: certifications documents @@ -221,8 +221,8 @@ The class Block handles Block documents. return BlockUID(self.number, self.sha_hash) @classmethod - def from_signed_raw(cls, raw): - lines = raw.splitlines(True) + def from_signed_raw(cls, signed_raw): + lines = signed_raw.splitlines(True) n = 0 version = int(Block.parse_field("Version", lines[n])) @@ -318,7 +318,7 @@ The class Block handles Block documents. if Block.re_revoked.match(lines[n]): n += 1 while Block.re_excluded.match(lines[n]) is None: - revokation = Revokation.from_inline(version, currency, lines[n]) + revokation = Revocation.from_inline(version, currency, lines[n]) revoked.append(revokation) n += 1 diff --git a/duniterpy/documents/certification.py b/duniterpy/documents/certification.py index bc21a693e21ee5d681d13763e41ca344fffe88fe..d2a6fef406e2fb458ecc96cb8bf1e5c4791e1993 100644 --- a/duniterpy/documents/certification.py +++ b/duniterpy/documents/certification.py @@ -163,7 +163,7 @@ CertTimestamp: {timestamp} self.timestamp.number, self.signatures[0]) -class Revokation(Document): +class Revocation(Document): """ A document describing a self-revocation. """ @@ -172,6 +172,20 @@ class Revokation(Document): signature_regex=signature_regex )) + re_type = re.compile("Type: (Revocation)") + re_issuer = re.compile("Issuer: ({pubkey_regex})\n".format(pubkey_regex=pubkey_regex)) + re_uniqueid = re.compile("IdtyUniqueID: ([^\n]+)\n") + re_timestamp = re.compile("IdtyTimestamp: ({block_uid_regex})\n".format(block_uid_regex=block_uid_regex)) + re_idtysignature = re.compile("IdtySignature: ({signature_regex})\n".format(signature_regex=signature_regex)) + + fields_parsers = {**Document.fields_parsers, **{ + "Type": re_type, + "Issuer": re_issuer, + "IdtyUniqueID": re_uniqueid, + "IdtyTimestamp": re_timestamp, + "IdtySignature": re_idtysignature, + }} + def __init__(self, version, currency, pubkey, signature): """ Constructor @@ -189,13 +203,67 @@ class Revokation(Document): :param str signature: :return: """ - cert_data = Revokation.re_inline.match(inline) + cert_data = Revocation.re_inline.match(inline) if cert_data is None: raise MalformedDocumentError("Revokation") pubkey = cert_data.group(1) signature = cert_data.group(2) return cls(version, currency, pubkey, signature) + @classmethod + def from_signed_raw(cls, signed_raw): + """ + Instanciates a revocation from a signed raw file + :param str signed_raw: raw document file in duniter format + :return: a revocation instance + """ + lines = signed_raw.splitlines(True) + n = 0 + + version = int(Revocation.parse_field("Version", lines[n])) + n += 1 + + Revocation.parse_field("Type", lines[n]) + n += 1 + + currency = Revocation.parse_field("Currency", lines[n]) + n += 1 + + issuer = Revocation.parse_field("Issuer", lines[n]) + n += 4 + + signature = Revocation.parse_field("Signature", lines[n]) + n += 1 + + return cls(version, currency, issuer, signature) + + @staticmethod + def extract_self_cert(signed_raw): + lines = signed_raw.splitlines(True) + n = 0 + + version = int(Revocation.parse_field("Version", lines[n])) + n += 1 + + Revocation.parse_field("Type", lines[n]) + n += 1 + + currency = Revocation.parse_field("Currency", lines[n]) + n += 1 + + issuer = Revocation.parse_field("Issuer", lines[n]) + n += 1 + + unique_id = Revocation.parse_field("IdtyUniqueID", lines[n]) + n += 1 + + timestamp = Revocation.parse_field("IdtyTimestamp", lines[n]) + n += 1 + + signature = Revocation.parse_field("IdtySignature", lines[n]) + n += 1 + + return SelfCertification(version, currency, issuer, unique_id, timestamp, signature) def raw(self, selfcert): """ diff --git a/duniterpy/documents/membership.py b/duniterpy/documents/membership.py index 068b0dafca56441f3c630129f4c80a0939a991d2..24abc12b667b72a23f19ae2f3577ce039aa7b128 100644 --- a/duniterpy/documents/membership.py +++ b/duniterpy/documents/membership.py @@ -71,9 +71,9 @@ class Membership(Document): return cls(version, currency, issuer, membership_ts, membership_type, uid, identity_ts, signature) @classmethod - def from_signed_raw(cls, raw, signature=None): + def from_signed_raw(cls, signed_raw): from .block import BlockUID - lines = raw.splitlines(True) + lines = signed_raw.splitlines(True) n = 0 version = int(Membership.parse_field("Version", lines[n])) diff --git a/tests/documents/test_certification.py b/tests/documents/test_certification.py index 25d97c2bbb1637c87088fed52dccc35388a05831..5bf7c2c2467b38793dded16cea742ad5f45b0d13 100644 --- a/tests/documents/test_certification.py +++ b/tests/documents/test_certification.py @@ -5,7 +5,7 @@ Created on 6 déc. 2014 ''' import unittest -from duniterpy.documents.certification import SelfCertification, Certification, Revokation +from duniterpy.documents.certification import SelfCertification, Certification, Revocation from duniterpy.documents import Block, BlockUID selfcert_inlines = ["HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk:\ @@ -111,7 +111,7 @@ SoKwoa8PFfCDJWZ6dNCv7XstezHcc2BbKiJgVDXv82R5zYR83nis9dShLgWJ5w48noVUHimdngzYQneN def test_revokation_from_inline(self): version = 2 currency = "zeta_brousouf" - revokation = Revokation.from_inline(version, currency, revokation_inline) + revokation = Revocation.from_inline(version, currency, revokation_inline) self.assertEqual(revokation.pubkey, "8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU") self.assertEqual(revokation.signatures[0], "TgmDuMxZdyutroj9jiLJA8tQp/389JIzDKuxW5+h7GIfjDu1ZbwI7HNm5rlUDhR2KreaV/QJjEaItT4Cf75rCQ==") @@ -121,7 +121,7 @@ SoKwoa8PFfCDJWZ6dNCv7XstezHcc2BbKiJgVDXv82R5zYR83nis9dShLgWJ5w48noVUHimdngzYQneN currency = "beta_brousouf" pubkey = "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd" signature = "SoKwoa8PFfCDJWZ6dNCv7XstezHcc2BbKiJgVDXv82R5zYR83nis9dShLgWJ5w48noVUHimdngzYQneNYSMV3rk" - revokation = Revokation(version, currency, pubkey, signature) + revokation = Revocation(version, currency, pubkey, signature) selfcert = SelfCertification(version, currency, pubkey, "lolcat", BlockUID(32, "DB30D958EE5CB75186972286ED3F4686B8A1C2CD"), "J3G9oM5AKYZNLAB5Wx499w61NuUoS57JVccTShUbGpCMjCqj9yXXqNq7dyZpDWA6BxipsiaMZhujMeBfCznzyci") @@ -135,4 +135,18 @@ IdtyTimestamp: 32-DB30D958EE5CB75186972286ED3F4686B8A1C2CD IdtySignature: J3G9oM5AKYZNLAB5Wx499w61NuUoS57JVccTShUbGpCMjCqj9yXXqNq7dyZpDWA6BxipsiaMZhujMeBfCznzyci SoKwoa8PFfCDJWZ6dNCv7XstezHcc2BbKiJgVDXv82R5zYR83nis9dShLgWJ5w48noVUHimdngzYQneNYSMV3rk """ - self.assertEqual(revokation.signed_raw(selfcert), result) \ No newline at end of file + self.assertEqual(revokation.signed_raw(selfcert), result) + + def test_revokation_from_signed_raw(self): + signed_raw = """Version: 2 +Type: Revocation +Currency: beta_brousouf +Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd +IdtyUniqueID: lolcat +IdtyTimestamp: 32-DB30D958EE5CB75186972286ED3F4686B8A1C2CD +IdtySignature: J3G9oM5AKYZNLAB5Wx499w61NuUoS57JVccTShUbGpCMjCqj9yXXqNq7dyZpDWA6BxipsiaMZhujMeBfCznzyci +SoKwoa8PFfCDJWZ6dNCv7XstezHcc2BbKiJgVDXv82R5zYR83nis9dShLgWJ5w48noVUHimdngzYQneNYSMV3rk +""" + revocation = Revocation.from_signed_raw(signed_raw) + selfcert = Revocation.extract_self_cert(signed_raw) + self.assertEqual(revocation.signed_raw(selfcert), signed_raw) \ No newline at end of file