diff --git a/ucoinpy/documents/__init__.py b/ucoinpy/documents/__init__.py index d8d1a59a056c7e17dd43425075ba9ab0d304658d..4e993849897a27ced08c290760f92a05f5ee28d1 100644 --- a/ucoinpy/documents/__init__.py +++ b/ucoinpy/documents/__init__.py @@ -13,12 +13,3 @@ class Document: def __init__(self, version): self.version = version - - def content(self): - return "" - - def sign(self, key): - return key.sign(self.content(), encoder=Base58Encoder) - - def signed(self, key): - return "{0}\n{1}\n".format(self.content(), self.sign(key)) diff --git a/ucoinpy/documents/block.py b/ucoinpy/documents/block.py index 1f02736ec9e02551d5bd515fa655a2756e3a7161..c849531f660abe86df4fb8cfa8f132ef58592e4d 100644 --- a/ucoinpy/documents/block.py +++ b/ucoinpy/documents/block.py @@ -72,12 +72,13 @@ BOTTOM_SIGNATURE re_excluded = re.compile("Excluded:\n") re_certifications = re.compile("Certifications:\n") re_transactions = re.compile("Transactions:\n") + re_sign = re.compile("([A-Za-z0-9+/]+)") def __init__(self, version, currency, noonce, number, powmin, time, mediantime, ud, issuer, prev_hash, prev_issuer, parameters, members_count, identities, joiners, actives, leavers, excluded, certifications, - transactions): + transactions, sign): ''' Constructor ''' @@ -101,6 +102,7 @@ BOTTOM_SIGNATURE self.excluded = excluded self.certifications = certifications self.transactions = transactions + self.sign = sign @classmethod def from_raw(cls, raw): @@ -161,55 +163,56 @@ BOTTOM_SIGNATURE if Block.re_identities.match(lines[n]) is not None: while Block.re_joiners.match(lines[n]) is None: - selfcert = SelfCertification.from_inline(lines[n]) - if selfcert is None: - return None - else: - identities.append(selfcert) - lines = lines + 1 + selfcert = SelfCertification.from_inline(version, lines[n]) + identities.append(selfcert) + lines = lines + 1 if Block.re_joiners.match(lines[n]) is not None: while Block.re_actives.match(lines[n]) is None: - membership = Membership.from_inline(lines[n]) + membership = Membership.from_inline(version, lines[n]) joiners.append(membership) lines = lines + 1 if Block.re_actives.match(lines[n]) is not None: while Block.re_leavers.match(lines[n]) is None: - membership = Membership.from_inline(lines[n]) + membership = Membership.from_inline(version, lines[n]) actives.append(membership) lines = lines + 1 if Block.re_leavers.match(lines[n]) is not None: while Block.re_excluded.match(lines[n]) is None: - membership = Membership.from_inline(lines[n]) + membership = Membership.from_inline(version, lines[n]) leavers.append(membership) lines = lines + 1 if Block.re_excluded.match(lines[n]) is not None: while Block.re_certifications.match(lines[n]) is None: - membership = Membership.from_inline(lines[n]) + membership = Membership.from_inline(version, lines[n]) excluded.append(membership) lines = lines + 1 if Block.re_certifications.match(lines[n]) is not None: while Block.re_transactions.match(lines[n]) is None: - certification = Certification.from_inline(lines[n]) + certification = Certification.from_inline(version, lines[n]) certifications.append(certification) lines = lines + 1 if Block.re_transactions.match(lines[n]) is not None: while Block.re_transactions.match(lines[n]) is None: - transaction = Transaction.from_compact(lines[n]) + transaction = Transaction.from_compact(version, lines[n]) transactions.append(transaction) lines = lines + 1 + sign = Block.re_sign.match(lines[n]) + n = n + 1 + return cls(version, currency, noonce, number, powmin, time, mediantime, ud, issuer, prev_hash, prev_issuer, parameters, members_count, identities, joiners, - actives, leavers, excluded, certifications, transactions) + actives, leavers, excluded, certifications, + transactions, sign) - def content(self): + def raw(self): doc = """ Version: {0} Type: Block @@ -265,3 +268,5 @@ Identities:""".format(PROTOCOL_VERSION, doc += "Transactions:\n" for transaction in self.transactions: doc += "{0}\n".format(transaction.inline()) + + doc += self.sign diff --git a/ucoinpy/documents/certification.py b/ucoinpy/documents/certification.py index c9cdca44c454daad1e39242a409f776e852d13c3..b9f821eabd43cf0195c8096d3f4f5da78d93eba0 100644 --- a/ucoinpy/documents/certification.py +++ b/ucoinpy/documents/certification.py @@ -3,6 +3,8 @@ Created on 2 déc. 2014 @author: inso ''' +import re + from . import Document @@ -10,14 +12,24 @@ class SelfCertification(Document): ''' A document discribing a self certification. ''' - def __init__(self, ts, identifier): - self.identifier = identifier + + re_inline = re.compile("([1-9A-Za-z][^OIl]{43,45}):([A-Za-z0-9+/]+):([0-9]+):([^\n]+)\n") + + def __init__(self, version, pubkey, ts, identifier, sign): + super(version) + self.pubkey = pubkey self.timestamp = ts + self.identifier = identifier + self.sign = sign @classmethod - def from_inline(cls, inline): - #TODO : Parsing - return cls() + def from_inline(cls, version, inline): + selfcert_data = SelfCertification.re_inline.match(inline) + pubkey = selfcert_data.group(1) + sign = selfcert_data.group(2) + ts = selfcert_data.group(3) + identifier = selfcert_data.group(4) + return cls(version, pubkey, ts, identifier, sign) @classmethod def from_raw(cls, raw): @@ -30,33 +42,43 @@ class SelfCertification(Document): def uid(self): return "UID:{0}".format(self.identifier) - def content(self): + def raw(self): return "{0}\n{1}".format(self.uid(), self.ts()) class Certification(Document): ''' - classdocs + A document describing a certification. ''' - def __init__(self, selfcert, blockid): + re_inline = re.compile("([1-9A-Za-z][^OIl]{43,45}):\ + ([A-Za-z0-9+/]+)(==)?:([0-9]+):([0-9a-fA-F]{5,40}):\ + ([0-9]+):([^\n]+)\n") + + def __init__(self, version, pubkey_from, pubkey_to, + blockhash, blocknumber, sign): ''' Constructor ''' - self.selfcert = selfcert - self.blockid = blockid - - @classmethod - def from_inline(cls, inline): - return cls() + super(version) + self.pubkey_from = pubkey_from + self.pubkey_to = pubkey_to + self.blockhash = blockhash + self.blocknumber = blocknumber + self.sign = sign @classmethod - def from_raw(cls, raw): - #TODO : Parsing - return cls() + def from_inline(cls, version, blockhash, inline): + cert_data = Certification.re_inline.match(inline) + pubkey_from = cert_data.group(1) + pubkey_to = cert_data.group(2) + blocknumber = cert_data.group(3) + sign = cert_data.group(4) + return cls(version, pubkey_from, pubkey_to, + blockhash, blocknumber, sign) def ts(self): - return "META:TS:{0}".format(self.blockid) + return "META:TS:{0}-{1}".format(self.blockhash, self.blocknumber) - def content(self): - return "{0}\n{1}".format(self.selfcert.content(), self.ts()) + def raw(self, selfcert): + return "{0}\n{1}".format(selfcert.content(), self.ts()) diff --git a/ucoinpy/documents/membership.py b/ucoinpy/documents/membership.py index fa76d4280e354e8f039e94072ece3783d01645c5..49eef154f190caebce68d626c0caa6644831eada 100644 --- a/ucoinpy/documents/membership.py +++ b/ucoinpy/documents/membership.py @@ -4,9 +4,12 @@ Created on 2 déc. 2014 @author: inso ''' from .. import PROTOCOL_VERSION +from . import Document +import re -class Membership(object): + +class Membership(Document): ''' This is a utility class to generate membership documents : Version: VERSION @@ -19,11 +22,16 @@ class Membership(object): CertTS: CERTIFICATION_TS ''' - def __init__(self, currency, issuer, block_number, block_hash, - membership_type, userid, cert_ts): + # PUBLIC_KEY:SIGNATURE:NUMBER:HASH:TIMESTAMP:USER_ID + re_inline = re.compile("([1-9A-Za-z][^OIl]{43,45}):([A-Za-z0-9+/]+):\ + ([0-9]+):([0-9a-fA-F]{5,40}):([0-9]+):([^\n]+)\n") + + def __init__(self, version, currency, issuer, block_number, block_hash, + membership_type, userid, cert_ts, sign): ''' Constructor ''' + super(version) self.currency = currency self.issuer = issuer self.block_number = block_number @@ -31,11 +39,19 @@ class Membership(object): self.membership_type = membership_type self.userid = userid self.cert_ts = cert_ts + self.sign = sign @classmethod - def from_inline(cls, inline): - #TODO: Parsing - return None + def from_inline(cls, version, currency, type, inline): + data = Membership.re_inline.match(inline) + issuer = data.group(1) + sign = data.group(2) + block_number = data.group(3) + block_hash = data.group(4) + cert_ts = data.group(5) + userid = data.group(6) + return cls(version, currency, issuer, block_number, + block_hash, type, userid, cert_ts, sign) @classmethod def from_raw(cls, raw): @@ -61,7 +77,7 @@ CertTS: {7}""".format(PROTOCOL_VERSION, def inline(self): return "{0}:{1}:{2}:{3}".format(self.issuer, - self.sign(), + self.sign, self.block_number, self.block_hash, self.cert_ts) diff --git a/ucoinpy/documents/peer.py b/ucoinpy/documents/peer.py index d696665bd47f2c89689476f296e9e26a15ead25d..0a387f79e884b7d62c32f80cf2a13b8217bf06b9 100644 --- a/ucoinpy/documents/peer.py +++ b/ucoinpy/documents/peer.py @@ -29,7 +29,7 @@ class Peer(Document): self.pubkey = pubkey self.blockid = blockid self.endpoints = endpoints - + @classmethod def from_raw(cls, raw): #TODO : Parsing @@ -59,22 +59,22 @@ class Endpoint(): def from_inline(inline): for api in MANAGED_API: if (inline.startswith(api)): - return Endpoint.parse_line(inline, api) - - @staticmethod - def parse_line(self, inline, api): - if (api == "BASIC_MERKLED_API"): - bma_endpoints = re.compile('^BASIC_MERKLED_API( ([a-z_][a-z0-9-_.]+))?( ([0-9.]+))?( ([0-9a-f:]+))?( ([0-9]+))$') - m = bma_endpoints.match(inline) - server = m.group(2) - ipv4 = m.group(4) - ipv6 = m.group(6) - port = int(m.group(8)) - return BMAEndpoint(server, ipv4, ipv6, port) - return None + if (api == "BASIC_MERKLED_API"): + return BMAEndpoint.from_inline(inline) class BMAEndpoint(Endpoint): + re_inline = re.compile('^BASIC_MERKLED_API( ([a-z_][a-z0-9-_.]+))?( ([0-9.]+))?( ([0-9a-f:]+))?( ([0-9]+))$') + + @classmethod + def from_inline(cls, inline): + m = BMAEndpoint.re_inline.match(inline) + server = m.group(2) + ipv4 = m.group(4) + ipv6 = m.group(6) + port = int(m.group(8)) + return cls(server, ipv4, ipv6, port) + def __init__(self, server, ipv4, ipv6, port): self.server = server self.ipv4 = ipv4