Skip to content
Snippets Groups Projects
Commit 7aa63507 authored by inso's avatar inso
Browse files

from_raw is now from_signed_raw

More units tests
From_raw -> to_raw -> from_raw testing
parent c963f5e9
No related branches found
No related tags found
No related merge requests found
...@@ -7,15 +7,27 @@ import pytest ...@@ -7,15 +7,27 @@ import pytest
from ucoinpy.documents.block import Block from ucoinpy.documents.block import Block
from mock import Mock from mock import Mock
raw_block = "Version: 1\nType: \ raw_block = """Version: 1
Block\nCurrency: zeta_brouzouf\n\ Type: Block
Nonce: 45079\nNumber: 15\nPoWMin: 4\n\ Currency: zeta_brouzouf
Time: 1418083330\nMedianTime: 1418080208\n\ Nonce: 45079
Issuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk\n\ Number: 15
PreviousHash: 0000E73C340601ACA1AD5AAA5B5E56B03E178EF8\n\ PoWMin: 4
PreviousIssuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk\n\ Time: 1418083330
MembersCount: 4\nIdentities:\nJoiners:\nActives:\nLeavers:\n\ MedianTime: 1418080208
Excluded:\nCertifications:\nTransactions:\n" Issuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk
PreviousHash: 0000E73C340601ACA1AD5AAA5B5E56B03E178EF8
PreviousIssuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk
MembersCount: 4
Identities:
Joiners:
Actives:
Leavers:
Excluded:
Certifications:
Transactions:
42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r
"""
raw_block_zero = """Version: 1 raw_block_zero = """Version: 1
...@@ -56,12 +68,13 @@ HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk:RdrHvL179Rw62UuyBrqy2M1crx7RPajaViB ...@@ -56,12 +68,13 @@ HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk:RdrHvL179Rw62UuyBrqy2M1crx7RPajaViB
RdrHvL179Rw62UuyBrqy2M1crx7RPajaViBatS59EGS:9fx25FmeBDJcikZLWxK5HuzKNbY6MaWYXoK1ajteE42Y:0:90w2HrbdsKIc6YJq3Ksa4sSgjpYSMM05+UuowAlYjrk1ixHIyWyg5odyZPRwO50aiIyUsbikoOWsMc3G8ob/Cg== RdrHvL179Rw62UuyBrqy2M1crx7RPajaViBatS59EGS:9fx25FmeBDJcikZLWxK5HuzKNbY6MaWYXoK1ajteE42Y:0:90w2HrbdsKIc6YJq3Ksa4sSgjpYSMM05+UuowAlYjrk1ixHIyWyg5odyZPRwO50aiIyUsbikoOWsMc3G8ob/Cg==
HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk:9fx25FmeBDJcikZLWxK5HuzKNbY6MaWYXoK1ajteE42Y:0:28lv0p8EPHpVgAMiPvXvIe5lMvYJxwko2tv5bPO4voHRHSaDcTz5BR7Oe69S6wjANIEAMfebXiFMqZdj+mWRAA== HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk:9fx25FmeBDJcikZLWxK5HuzKNbY6MaWYXoK1ajteE42Y:0:28lv0p8EPHpVgAMiPvXvIe5lMvYJxwko2tv5bPO4voHRHSaDcTz5BR7Oe69S6wjANIEAMfebXiFMqZdj+mWRAA==
Transactions: Transactions:
42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r
""" """
class Test_Block: class Test_Block:
def test_fromraw(self): def test_fromraw(self):
block = Block.from_raw(raw_block) block = Block.from_signed_raw(raw_block)
assert block.version == 1 assert block.version == 1
assert block.currency == "zeta_brouzouf" assert block.currency == "zeta_brouzouf"
assert block.noonce == 45079 assert block.noonce == 45079
...@@ -81,8 +94,8 @@ class Test_Block: ...@@ -81,8 +94,8 @@ class Test_Block:
assert block.certifications == [] assert block.certifications == []
assert block.transactions == [] assert block.transactions == []
def test_from_raw_block_zero(self): def test_from_signed_raw_block_zero(self):
block = Block.from_raw(raw_block_zero) block = Block.from_signed_raw(raw_block_zero)
assert block.version == 1 assert block.version == 1
assert block.currency == "zeta_brouzouf" assert block.currency == "zeta_brouzouf"
assert block.noonce == 2125 assert block.noonce == 2125
...@@ -101,3 +114,53 @@ class Test_Block: ...@@ -101,3 +114,53 @@ class Test_Block:
assert block.excluded == [] assert block.excluded == []
assert len(block.certifications) == 12 assert len(block.certifications) == 12
assert block.transactions == [] assert block.transactions == []
def test_to_raw_from_signed_raw(self):
block = Block.from_signed_raw(raw_block)
rendered_raw = block.signed_raw()
from_rendered_raw = Block.from_signed_raw(rendered_raw)
assert from_rendered_raw.version == 1
assert from_rendered_raw.currency == "zeta_brouzouf"
assert from_rendered_raw.noonce == 45079
assert from_rendered_raw.number == 15
assert from_rendered_raw.powmin == 4
assert from_rendered_raw.time == 1418083330
assert from_rendered_raw.mediantime == 1418080208
assert from_rendered_raw.issuer == "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk"
assert from_rendered_raw.prev_hash == "0000E73C340601ACA1AD5AAA5B5E56B03E178EF8"
assert from_rendered_raw.prev_issuer == "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk"
assert from_rendered_raw.members_count == 4
assert from_rendered_raw.identities == []
assert from_rendered_raw.joiners == []
assert from_rendered_raw.actives == []
assert from_rendered_raw.leavers == []
assert from_rendered_raw.excluded == []
assert from_rendered_raw.certifications == []
assert from_rendered_raw.transactions == []
def test_to_raw_from_signed_raw_zero(self):
block = Block.from_signed_raw(raw_block_zero)
rendered_raw = block.signed_raw()
from_rendered_raw = block.from_signed_raw(rendered_raw)
assert from_rendered_raw.version == 1
assert from_rendered_raw.currency == "zeta_brouzouf"
assert from_rendered_raw.noonce == 2125
assert from_rendered_raw.number == 0
assert from_rendered_raw.powmin == 3
assert from_rendered_raw.time == 1418077277
assert from_rendered_raw.mediantime == 1418077277
assert from_rendered_raw.issuer == "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk"
assert from_rendered_raw.parameters == ('0.01','302400','100','5259600','2629800','3','5',
'2629800','3','11','600','10','20','0.67')
assert from_rendered_raw.members_count == 4
assert len(from_rendered_raw.identities) == 4
assert len(from_rendered_raw.joiners) == 4
assert from_rendered_raw.actives == []
assert from_rendered_raw.leavers == []
assert from_rendered_raw.excluded == []
assert len(from_rendered_raw.certifications) == 12
assert from_rendered_raw.transactions == []
...@@ -33,13 +33,13 @@ class Test_SelfCertification: ...@@ -33,13 +33,13 @@ class Test_SelfCertification:
assert selfcert.pubkey == "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk" assert selfcert.pubkey == "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk"
assert selfcert.signatures[0] == "h/H8tDIEbfA4yxMQcvfOXVDQhi1sUa9qYtPKrM59Bulv97ouwbAvAsEkC1Uyit1IOpeAV+CQQs4IaAyjE8F1Cw==" assert selfcert.signatures[0] == "h/H8tDIEbfA4yxMQcvfOXVDQhi1sUa9qYtPKrM59Bulv97ouwbAvAsEkC1Uyit1IOpeAV+CQQs4IaAyjE8F1Cw=="
assert selfcert.timestamp == 1416335620 assert selfcert.timestamp == 1416335620
assert selfcert.identifier == "cgeek" assert selfcert.uid == "cgeek"
selfcert = SelfCertification.from_inline(version, currency, selfcert_inlines[1]) selfcert = SelfCertification.from_inline(version, currency, selfcert_inlines[1])
assert selfcert.pubkey == "RdrHvL179Rw62UuyBrqy2M1crx7RPajaViBatS59EGS" assert selfcert.pubkey == "RdrHvL179Rw62UuyBrqy2M1crx7RPajaViBatS59EGS"
assert selfcert.signatures[0] == "Ah55O8cvdkGS4at6AGOKUjy+wrFwAq8iKRJ5xLIb6Xdi3M8WfGOUdMjwZA6GlSkdtlMgEhQPm+r2PMebxKrCBg==" assert selfcert.signatures[0] == "Ah55O8cvdkGS4at6AGOKUjy+wrFwAq8iKRJ5xLIb6Xdi3M8WfGOUdMjwZA6GlSkdtlMgEhQPm+r2PMebxKrCBg=="
assert selfcert.timestamp == 1416428323 assert selfcert.timestamp == 1416428323
assert selfcert.identifier == "vit" assert selfcert.uid == "vit"
def test_certifications(self): def test_certifications(self):
version = 1 version = 1
......
...@@ -7,12 +7,39 @@ import pytest ...@@ -7,12 +7,39 @@ import pytest
from ucoinpy.documents.membership import Membership from ucoinpy.documents.membership import Membership
from mock import Mock from mock import Mock
inline_membership = "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk:\ membership_inline = "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk:\
dkaXIiCYUJtCg8Feh/BKvPYf4uFH9CJ/zY6J4MlA9BsjmcMe4YAblvNt/gJy31b1aGq3ue3h14mLMCu84rraDg==:\ dkaXIiCYUJtCg8Feh/BKvPYf4uFH9CJ/zY6J4MlA9BsjmcMe4YAblvNt/gJy31b1aGq3ue3h14mLMCu84rraDg==:\
0:DA39A3EE5E6B4B0D3255BFEF95601890AFD80709:1416335620:cgeek\n" 0:DA39A3EE5E6B4B0D3255BFEF95601890AFD80709:1416335620:cgeek\n"
membership_raw = """Version: 1
Type: Membership
Currency: beta_brousouf
Issuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk
Block: 0-DA39A3EE5E6B4B0D3255BFEF95601890AFD80709
Membership: IN
UserID: cgeek
CertTS: 1416335620
dkaXIiCYUJtCg8Feh/BKvPYf4uFH9CJ/zY6J4MlA9BsjmcMe4YAblvNt/gJy31b1aGq3ue3h14mLMCu84rraDg==
"""
class Test_Membership: class Test_Membership:
def test_frominline(self): def test_frominline(self):
membership = Membership.from_inline(1, "zeta_brousouf", 'IN', inline_membership) membership = Membership.from_inline(1, "zeta_brousouf", 'IN', membership_inline)
assert membership.issuer == "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk"
assert membership.block_number == 0
assert membership.block_hash == "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709"
assert membership.cert_ts == 1416335620
assert membership.uid == "cgeek"
assert membership.signatures[0] == "dkaXIiCYUJtCg8Feh/BKvPYf4uFH9CJ/zY6J4MlA9BsjmcMe4YAblvNt/gJy31b1aGq3ue3h14mLMCu84rraDg=="
assert membership.membership_type == 'IN'
def test_fromraw(self):
membership = Membership.from_signed_raw(membership_raw)
assert membership.issuer == "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk"
assert membership.block_number == 0
assert membership.block_hash == "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709"
assert membership.cert_ts == 1416335620
assert membership.uid == "cgeek"
assert membership.signatures[0] == "dkaXIiCYUJtCg8Feh/BKvPYf4uFH9CJ/zY6J4MlA9BsjmcMe4YAblvNt/gJy31b1aGq3ue3h14mLMCu84rraDg=="
assert membership.membership_type == 'IN'
'''
Created on 13 déc. 2014
@author: inso
'''
import pytest
from ucoinpy.documents.peer import Peer, BMAEndpoint, UnknownEndpoint
rawpeer = """Version: 1
Type: Peer
Currency: beta_brousouf
PublicKey: HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY
Block: 8-1922C324ABC4AF7EF7656734A31F5197888DDD52
Endpoints:
BASIC_MERKLED_API some.dns.name 88.77.66.55 2001:0db8:0000:85a3:0000:0000:ac1f 9001
BASIC_MERKLED_API some.dns.name 88.77.66.55 2001:0db8:0000:85a3:0000:0000:ac1f 9002
OTHER_PROTOCOL 88.77.66.55 9001
dkaXIiCYUJtCg8Feh/BKvPYf4uFH9CJ/zY6J4MlA9BsjmcMe4YAblvNt/gJy31b1aGq3ue3h14mLMCu84rraDg==
"""
class TestPeer:
def test_fromraw(self):
peer = Peer.from_signed_raw(rawpeer)
assert peer.currency == "beta_brousouf"
assert peer.pubkey == "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY"
assert peer.blockid == "8-1922C324ABC4AF7EF7656734A31F5197888DDD52"
assert len(peer.endpoints) == 3
assert type(peer.endpoints[0]) is BMAEndpoint
assert type(peer.endpoints[1]) is BMAEndpoint
assert type(peer.endpoints[2]) is UnknownEndpoint
assert peer.endpoints[0].server == "some.dns.name"
assert peer.endpoints[0].ipv4 == "88.77.66.55"
assert peer.endpoints[0].ipv6 == "2001:0db8:0000:85a3:0000:0000:ac1f"
assert peer.endpoints[0].port == 9001
assert peer.endpoints[1].server == "some.dns.name"
assert peer.endpoints[1].ipv4 == "88.77.66.55"
assert peer.endpoints[1].ipv6 == "2001:0db8:0000:85a3:0000:0000:ac1f"
assert peer.endpoints[1].port == 9002
assert peer.signatures[0] == "dkaXIiCYUJtCg8Feh/BKvPYf4uFH9CJ/zY6J4MlA9BsjmcMe4YAblvNt/gJy31b1aGq3ue3h14mLMCu84rraDg=="
'''
Created on 13 déc. 2014
@author: inso
'''
import pytest
from ucoinpy.documents.status import Status
raw_status = """Version: 1
Type: Status
Currency: beta_brousouf
Status: UP
Block: 8-1922C324ABC4AF7EF7656734A31F5197888DDD52
From: HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY
To: 8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU
dkaXIiCYUJtCg8Feh/BKvPYf4uFH9CJ/zY6J4MlA9BsjmcMe4YAblvNt/gJy31b1aGq3ue3h14mLMCu84rraDg==
"""
class Test_Status:
def test_fromraw(self):
status = Status.from_signed_raw(raw_status)
assert status.status == 'UP'
assert status.blockid == "8-1922C324ABC4AF7EF7656734A31F5197888DDD52"
assert status.sender == "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY"
assert status.recipient == "8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU"
assert status.signatures[0] == "dkaXIiCYUJtCg8Feh/BKvPYf4uFH9CJ/zY6J4MlA9BsjmcMe4YAblvNt/gJy31b1aGq3ue3h14mLMCu84rraDg=="
...@@ -48,3 +48,5 @@ class Test_Transaction: ...@@ -48,3 +48,5 @@ class Test_Transaction:
assert tx.outputs[0].pubkey == "BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g" assert tx.outputs[0].pubkey == "BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g"
assert tx.outputs[0].amount == 30 assert tx.outputs[0].amount == 30
assert tx.signatures[0] == "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r"
...@@ -6,13 +6,36 @@ Created on 3 déc. 2014 ...@@ -6,13 +6,36 @@ Created on 3 déc. 2014
import base58 import base58
import re import re
from ..key import Base58Encoder from ..key import Base58Encoder
from nacl.encoding import Base64Encoder
class Document: class Document:
re_version = re.compile("Version: ([0-9]+)\n") re_version = re.compile("Version: ([0-9]+)\n")
re_currency = re.compile("Currency: ([^\n]+)\n") re_currency = re.compile("Currency: ([^\n]+)\n")
re_signature = re.compile("([A-Za-z0-9+/]+(?:=|==)?)\n")
def __init__(self, version, currency, signatures): def __init__(self, version, currency, signatures):
self.version = version self.version = version
self.currency = currency self.currency = currency
self.signatures = signatures self.signatures = signatures
def sign(self, keys):
'''
Sign the current document.
Warning : current signatures will be replaced with the new ones.
'''
self.signatures = []
for k in keys:
self.signatures.append(k.sign(self.raw(), Base64Encoder))
def signed_raw(self):
'''
If keys are None, returns the raw + current signatures
If keys are present, returns the raw signed by these keys
'''
raw = self.raw()
signed_raw = raw
for s in self.signatures:
if s is not None:
signed_raw += s + "\n"
return signed_raw
...@@ -74,7 +74,6 @@ BOTTOM_SIGNATURE ...@@ -74,7 +74,6 @@ BOTTOM_SIGNATURE
re_excluded = re.compile("Excluded:\n") re_excluded = re.compile("Excluded:\n")
re_certifications = re.compile("Certifications:\n") re_certifications = re.compile("Certifications:\n")
re_transactions = re.compile("Transactions:\n") re_transactions = re.compile("Transactions:\n")
re_sign = re.compile("([A-Za-z0-9+/]+)")
def __init__(self, version, currency, noonce, number, powmin, time, def __init__(self, version, currency, noonce, number, powmin, time,
mediantime, ud, issuer, prev_hash, prev_issuer, mediantime, ud, issuer, prev_hash, prev_issuer,
...@@ -84,7 +83,10 @@ BOTTOM_SIGNATURE ...@@ -84,7 +83,10 @@ BOTTOM_SIGNATURE
''' '''
Constructor Constructor
''' '''
super(Block, self).__init__(version, currency, [signature]) if signature:
super().__init__(version, currency, [signature])
else:
super().__init__(version, currency, [])
self.noonce = noonce self.noonce = noonce
self.number = number self.number = number
self.powmin = powmin self.powmin = powmin
...@@ -105,14 +107,14 @@ BOTTOM_SIGNATURE ...@@ -105,14 +107,14 @@ BOTTOM_SIGNATURE
self.transactions = transactions self.transactions = transactions
@classmethod @classmethod
def from_raw(cls, raw): def from_signed_raw(cls, raw, signature=None):
lines = raw.splitlines(True) lines = raw.splitlines(True)
n = 0 n = 0
version = int(Block.re_version.match(lines[n]).group(1)) version = int(Block.re_version.match(lines[n]).group(1))
n = n + 1 n = n + 1
doctype = Block.re_type.match(lines[n]).group(1) Block.re_type.match(lines[n]).group(1)
n = n + 1 n = n + 1
currency = Block.re_currency.match(lines[n]).group(1) currency = Block.re_currency.match(lines[n]).group(1)
...@@ -211,16 +213,12 @@ BOTTOM_SIGNATURE ...@@ -211,16 +213,12 @@ BOTTOM_SIGNATURE
if Block.re_transactions.match(lines[n]): if Block.re_transactions.match(lines[n]):
n = n + 1 n = n + 1
while n < len(lines) and not Block.re_sign.match(lines[n]): while not Block.re_signature.match(lines[n]):
transaction = Transaction.from_compact(version, lines[n]) transaction = Transaction.from_compact(version, lines[n])
transactions.append(transaction) transactions.append(transaction)
n = n + 1 n = n + 1
signature = None signature = Block.re_signature.match(lines[n]).group(1)
if n < len(lines):
signature = Block.re_sign.match(lines[n])
n = n + 1
return cls(version, currency, noonce, number, powmin, time, return cls(version, currency, noonce, number, powmin, time,
mediantime, ud, issuer, prev_hash, prev_issuer, mediantime, ud, issuer, prev_hash, prev_issuer,
...@@ -229,8 +227,7 @@ BOTTOM_SIGNATURE ...@@ -229,8 +227,7 @@ BOTTOM_SIGNATURE
transactions, signature) transactions, signature)
def raw(self): def raw(self):
doc = """ doc = """Version: {0}
Version: {0}
Type: Block Type: Block
Currency: {1} Currency: {1}
Nonce: {2} Nonce: {2}
...@@ -238,26 +235,28 @@ Number: {3} ...@@ -238,26 +235,28 @@ Number: {3}
PoWMin: {4} PoWMin: {4}
Time: {5} Time: {5}
MedianTime: {6} MedianTime: {6}
UniversalDividend: {7} """.format(self.version,
Issuer: {8}
PreviousHash: {9}
PreviousIssuer: {10}
Parameters: {11}
MembersCount: {12}
Identities:""".format(self.version,
self.currency, self.currency,
self.noonce, self.noonce,
self.number, self.number,
self.powmin, self.powmin,
self.time, self.time,
self.mediantime, self.mediantime)
self.ud, if self.ud:
self.issuer, doc += "UniversalDividend: {0}\n".format(self.ud)
self.prev_hash,
self.prev_issuer, doc += "Issuer: {0}\n".format(self.issuer)
self.parameters,
self.members_count) if self.number == 0:
str_params = ":".join(self.parameters)
doc += "Parameters: {0}\n".format(str_params)
else:
doc += "PreviousHash: {0}\n\
PreviousIssuer: {1}\n".format(self.prev_hash, self.prev_issuer)
doc += "MembersCount: {0}\n".format(self.members_count)
doc += "Identities:\n"
for identity in self.identities: for identity in self.identities:
doc += "{0}\n".format(identity.inline()) doc += "{0}\n".format(identity.inline())
...@@ -274,7 +273,7 @@ Identities:""".format(self.version, ...@@ -274,7 +273,7 @@ Identities:""".format(self.version,
doc += "{0]\n".format(leaver.inline()) doc += "{0]\n".format(leaver.inline())
doc += "Excluded:\n" doc += "Excluded:\n"
for exclude in self.exclude: for exclude in self.excluded:
doc += "{0}\n".format(exclude.inline()) doc += "{0}\n".format(exclude.inline())
doc += "Certifications:\n" doc += "Certifications:\n"
...@@ -285,4 +284,4 @@ Identities:""".format(self.version, ...@@ -285,4 +284,4 @@ Identities:""".format(self.version,
for transaction in self.transactions: for transaction in self.transactions:
doc += "{0}\n".format(transaction.inline()) doc += "{0}\n".format(transaction.inline())
doc += self.signatures[0] return doc
...@@ -14,12 +14,17 @@ class SelfCertification(Document): ...@@ -14,12 +14,17 @@ class SelfCertification(Document):
''' '''
re_inline = re.compile("([1-9A-Za-z][^OIl]{42,45}):([A-Za-z0-9+/]+(?:=|==)?):([0-9]+):([^\n]+)\n") re_inline = re.compile("([1-9A-Za-z][^OIl]{42,45}):([A-Za-z0-9+/]+(?:=|==)?):([0-9]+):([^\n]+)\n")
re_uid = re.compile("UID:([^\n]+)\n")
re_timestamp = re.compile("META:TS:([0-9]+)\n")
def __init__(self, version, currency, pubkey, ts, identifier, signature): def __init__(self, version, currency, pubkey, ts, uid, signature):
if signature:
super().__init__(version, currency, [signature]) super().__init__(version, currency, [signature])
else:
super().__init__(version, currency, [])
self.pubkey = pubkey self.pubkey = pubkey
self.timestamp = ts self.timestamp = ts
self.identifier = identifier self.uid = uid
@classmethod @classmethod
def from_inline(cls, version, currency, inline): def from_inline(cls, version, currency, inline):
...@@ -27,22 +32,16 @@ class SelfCertification(Document): ...@@ -27,22 +32,16 @@ class SelfCertification(Document):
pubkey = selfcert_data.group(1) pubkey = selfcert_data.group(1)
signature = selfcert_data.group(2) signature = selfcert_data.group(2)
ts = int(selfcert_data.group(3)) ts = int(selfcert_data.group(3))
identifier = selfcert_data.group(4) uid = selfcert_data.group(4)
return cls(version, currency, pubkey, ts, identifier, signature) return cls(version, currency, pubkey, ts, uid, signature)
@classmethod
def from_raw(cls, raw):
#TODO : Parsing
return cls()
def ts(self):
return "META:TS:{0}".format(self.timestamp)
def uid(self):
return "UID:{0}".format(self.identifier)
def raw(self): def raw(self):
return "{0}\n{1}\n{2}".format(self.uid(), self.ts(), self.signatures[0]) return """UID:{0}
META:TS:{1}""".format(self.uid(), self.ts())
def inline(self):
return "{0}:{1}:{2}:{3}".format(self.pubkey, self.signatures[0],
self.timestamp, self.uid)
class Certification(Document): class Certification(Document):
...@@ -52,6 +51,7 @@ class Certification(Document): ...@@ -52,6 +51,7 @@ class Certification(Document):
re_inline = re.compile("([1-9A-Za-z][^OIl]{42,45}):\ re_inline = re.compile("([1-9A-Za-z][^OIl]{42,45}):\
([1-9A-Za-z][^OIl]{42,45}):([0-9]+):([A-Za-z0-9+/]+(?:=|==)?)\n") ([1-9A-Za-z][^OIl]{42,45}):([0-9]+):([A-Za-z0-9+/]+(?:=|==)?)\n")
re_timestamp = re.compile("META:TS:([0-9]+)-([0-9a-fA-F]{5,40})\n")
def __init__(self, version, currency, pubkey_from, pubkey_to, def __init__(self, version, currency, pubkey_from, pubkey_to,
blockhash, blocknumber, signature): blockhash, blocknumber, signature):
...@@ -76,8 +76,11 @@ class Certification(Document): ...@@ -76,8 +76,11 @@ class Certification(Document):
return cls(version, currency, pubkey_from, pubkey_to, return cls(version, currency, pubkey_from, pubkey_to,
blockhash, blocknumber, signature) blockhash, blocknumber, signature)
def ts(self):
return "META:TS:{0}-{1}".format(self.blockhash, self.blocknumber)
def raw(self, selfcert): def raw(self, selfcert):
return "{0}\n{1}\n{2}".format(selfcert.raw(), self.ts(), self.signatures[0]) return """{0}
META:TS:{1}-{2}""".format(selfcert.signed_raw(), self.blockhash, self.blocknumber)
def inline(self):
return "{0}:{1}:{2}:{3}".format(self.pubkey_from, self.pubkey_to,
self.blocknumber, self.signatures[0])
...@@ -25,18 +25,29 @@ class Membership(Document): ...@@ -25,18 +25,29 @@ class Membership(Document):
# PUBLIC_KEY:SIGNATURE:NUMBER:HASH:TIMESTAMP:USER_ID # PUBLIC_KEY:SIGNATURE:NUMBER:HASH:TIMESTAMP:USER_ID
re_inline = re.compile("([1-9A-Za-z][^OIl]{42,45}):([A-Za-z0-9+/]+(?:=|==)?):\ re_inline = re.compile("([1-9A-Za-z][^OIl]{42,45}):([A-Za-z0-9+/]+(?:=|==)?):\
([0-9]+):([0-9a-fA-F]{5,40}):([0-9]+):([^\n]+)\n") ([0-9]+):([0-9a-fA-F]{5,40}):([0-9]+):([^\n]+)\n")
re_type = re.compile("Type: (Membership)")
re_issuer = re.compile("Issuer: ([1-9A-Za-z][^OIl]{42,45})\n")
re_block = re.compile("Block: ([0-9]+)-([0-9a-fA-F]{5,40})\n")
re_membership_type = re.compile("Membership: (IN|OUT)")
re_userid = re.compile("UserID: ([^\n]+)\n")
re_certts = re.compile("CertTS: ([0-9]+)\n")
def __init__(self, version, currency, issuer, block_number, block_hash, def __init__(self, version, currency, issuer, block_number, block_hash,
membership_type, userid, cert_ts, signature): membership_type, uid, cert_ts, signature):
''' '''
Constructor Constructor
''' '''
if signature:
super().__init__(version, currency, [signature]) super().__init__(version, currency, [signature])
else:
super().__init__(version, currency, [])
self.issuer = issuer self.issuer = issuer
self.block_number = block_number self.block_number = block_number
self.block_hash = block_hash self.block_hash = block_hash
self.membership_type = membership_type self.membership_type = membership_type
self.userid = userid self.uid = uid
self.cert_ts = cert_ts self.cert_ts = cert_ts
@classmethod @classmethod
...@@ -44,17 +55,49 @@ class Membership(Document): ...@@ -44,17 +55,49 @@ class Membership(Document):
data = Membership.re_inline.match(inline) data = Membership.re_inline.match(inline)
issuer = data.group(1) issuer = data.group(1)
signature = data.group(2) signature = data.group(2)
block_number = data.group(3) block_number = int(data.group(3))
block_hash = data.group(4) block_hash = data.group(4)
cert_ts = data.group(5) cert_ts = int(data.group(5))
userid = data.group(6) uid = data.group(6)
return cls(version, currency, issuer, block_number, return cls(version, currency, issuer, block_number,
block_hash, membership_type, userid, cert_ts, signature) block_hash, membership_type, uid, cert_ts, signature)
@classmethod @classmethod
def from_raw(cls, raw): def from_signed_raw(cls, raw, signature=None):
#TODO : Parsing lines = raw.splitlines(True)
return cls() n = 0
version = int(Membership.re_version.match(lines[n]).group(1))
n = n + 1
Membership.re_type.match(lines[n]).group(1)
n = n + 1
currency = Membership.re_currency.match(lines[n]).group(1)
n = n + 1
issuer = Membership.re_issuer.match(lines[n]).group(1)
n = n + 1
blockid = Membership.re_block.match(lines[n])
blocknumber = int(blockid.group(1))
blockhash = blockid.group(2)
n = n + 1
membership_type = Membership.re_membership_type.match(lines[n]).group(1)
n = n + 1
uid = Membership.re_userid.match(lines[n]).group(1)
n = n + 1
cert_ts = int(Membership.re_certts.match(lines[n]).group(1))
n = n + 1
signature = Membership.re_signature.match(lines[n]).group(1)
n = n + 1
return cls(version, currency, issuer, blocknumber, blockhash,
membership_type, uid, cert_ts, signature)
def raw(self): def raw(self):
return """ return """
...@@ -65,19 +108,18 @@ Issuer: {2} ...@@ -65,19 +108,18 @@ Issuer: {2}
Block: {3}-{4} Block: {3}-{4}
Membership: {5} Membership: {5}
UserID: {6} UserID: {6}
CertTS: {7} CertTS: {7}""".format(self.version,
{8}""".format(self.version,
self.currency, self.currency,
self.issuer, self.issuer,
self.block_number, self.block_hash, self.block_number, self.block_hash,
self.membership_type, self.membership_type,
self.userid, self.uid,
self.cert_ts, self.cert_ts)
self.signatures[0])
def inline(self): def inline(self):
return "{0}:{1}:{2}:{3}".format(self.issuer, return "{0}:{1}:{2}:{3}:{4}:{5}".format(self.issuer,
self.sign, self.signatures[0],
self.block_number, self.block_number,
self.block_hash, self.block_hash,
self.cert_ts) self.cert_ts,
self.uid)
...@@ -24,16 +24,54 @@ class Peer(Document): ...@@ -24,16 +24,54 @@ class Peer(Document):
[...] [...]
""" """
def __init__(self, version, currency, pubkey, blockid, endpoints, signature): re_type = re.compile("Type: (Peer)")
re_pubkey = re.compile("PublicKey: ([1-9A-Za-z][^OIl]{42,45})\n")
re_block = re.compile("Block: ([0-9]+-[0-9a-fA-F]{5,40})\n")
re_endpoints = re.compile("Endpoints:\n")
def __init__(self, version, currency, pubkey, blockid,
endpoints, signature):
if signature:
super().__init__(version, currency, [signature]) super().__init__(version, currency, [signature])
else:
super().__init__(version, currency, [])
self.pubkey = pubkey self.pubkey = pubkey
self.blockid = blockid self.blockid = blockid
self.endpoints = endpoints self.endpoints = endpoints
@classmethod @classmethod
def from_raw(cls, raw): def from_signed_raw(cls, raw):
#TODO : Parsing lines = raw.splitlines(True)
return cls() n = 0
version = int(Peer.re_version.match(lines[n]).group(1))
n = n + 1
Peer.re_type.match(lines[n]).group(1)
n = n + 1
currency = Peer.re_currency.match(lines[n]).group(1)
n = n + 1
pubkey = Peer.re_pubkey.match(lines[n]).group(1)
n = n + 1
blockid = Peer.re_block.match(lines[n]).group(1)
n = n + 1
Peer.re_endpoints.match(lines[n])
n = n + 1
endpoints = []
while not Peer.re_signature.match(lines[n]):
endpoint = Endpoint.from_inline(lines[n])
endpoints.append(endpoint)
n = n + 1
signature = Peer.re_signature.match(lines[n]).group(1)
return cls(version, currency, pubkey, blockid, endpoints, signature)
def raw(self): def raw(self):
doc = """ doc = """
...@@ -63,18 +101,32 @@ class Endpoint(): ...@@ -63,18 +101,32 @@ class Endpoint():
if (inline.startswith(api)): if (inline.startswith(api)):
if (api == "BASIC_MERKLED_API"): if (api == "BASIC_MERKLED_API"):
return BMAEndpoint.from_inline(inline) return BMAEndpoint.from_inline(inline)
return UnknownEndpoint.from_inline(inline)
class UnknownEndpoint(Endpoint):
def __init__(self, api, properties):
self.api = api
self.properties = properties
@classmethod
def from_inline(cls, inline):
api = inline.split()[0]
properties = inline.split()[1:]
return cls(api, properties)
class BMAEndpoint(Endpoint): class BMAEndpoint(Endpoint):
re_inline = re.compile('^BASIC_MERKLED_API( ([a-z_][a-z0-9-_.]+))?( ([0-9.]+))?( ([0-9a-f:]+))?( ([0-9]+))$') re_inline = re.compile('^BASIC_MERKLED_API(?: ([a-z_][a-z0-9-_.]+))?(?: ([0-9.]+))?(?: ([0-9a-f:]+))?(?: ([0-9]+))$')
@classmethod @classmethod
def from_inline(cls, inline): def from_inline(cls, inline):
m = BMAEndpoint.re_inline.match(inline) m = BMAEndpoint.re_inline.match(inline)
server = m.group(2) server = m.group(1)
ipv4 = m.group(4) ipv4 = m.group(2)
ipv6 = m.group(6) ipv6 = m.group(3)
port = int(m.group(8)) port = int(m.group(4))
return cls(server, ipv4, ipv6, port) return cls(server, ipv4, ipv6, port)
def __init__(self, server, ipv4, ipv6, port): def __init__(self, server, ipv4, ipv6, port):
......
...@@ -4,8 +4,8 @@ Created on 2 déc. 2014 ...@@ -4,8 +4,8 @@ Created on 2 déc. 2014
@author: inso @author: inso
''' '''
import re
from . import Document from . import Document
from .. import PROTOCOL_VERSION
class Status(Document): class Status(Document):
...@@ -19,21 +19,58 @@ class Status(Document): ...@@ -19,21 +19,58 @@ class Status(Document):
To: RECIPIENT To: RECIPIENT
''' '''
re_type = re.compile("Type: (Status)")
re_status = re.compile("Status: (NEW|NEW_BACK|UP|UP_BACK|DOWN)")
re_block = re.compile("Block: ([0-9]+-[0-9a-fA-F]{5,40})\n")
re_from = re.compile("From: ([1-9A-Za-z][^OIl]{42,45})\n")
re_to = re.compile("To: ([1-9A-Za-z][^OIl]{42,45})\n")
def __init__(self, version, currency, status, blockid, sender, def __init__(self, version, currency, status, blockid, sender,
recipient, signature): recipient, signature):
''' '''
Constructor Constructor
''' '''
if signature:
super().__init__(version, currency, [signature]) super().__init__(version, currency, [signature])
else:
super().__init__(version, currency, [])
self.status = status self.status = status
self.blockid = blockid self.blockid = blockid
self.sender = sender self.sender = sender
self.recipient = recipient self.recipient = recipient
@classmethod @classmethod
def from_raw(cls, raw): def from_signed_raw(cls, raw):
#TODO : Parsing lines = raw.splitlines(True)
return cls() n = 0
version = int(Status.re_version.match(lines[n]).group(1))
n = n + 1
Status.re_type.match(lines[n]).group(1)
n = n + 1
currency = Status.re_currency.match(lines[n]).group(1)
n = n + 1
status = Status.re_status.match(lines[n]).group(1)
n = n + 1
blockid = Status.re_block.match(lines[n]).group(1)
n = n + 1
sender = Status.re_from.match(lines[n]).group(1)
n = n + 1
recipient = Status.re_to.match(lines[n]).group(1)
n = n + 1
signature = Status.re_signature.match(lines[n]).group(1)
n = n + 1
return cls(version, currency, status, blockid,
sender, recipient, signature)
def raw(self): def raw(self):
return ''' return '''
...@@ -44,6 +81,5 @@ Status: {2} ...@@ -44,6 +81,5 @@ Status: {2}
Block: {3} Block: {3}
From: {4} From: {4}
To: {5} To: {5}
{6}
'''.format(self.version, self.currency, self.status, '''.format(self.version, self.currency, self.status,
self.blockid, self.sender, self.recipient, self.signatures[0]) self.blockid, self.sender, self.recipient)
...@@ -45,6 +45,8 @@ SIGNATURE ...@@ -45,6 +45,8 @@ SIGNATURE
re_issuers = re.compile("Issuers:\n") re_issuers = re.compile("Issuers:\n")
re_inputs = re.compile("Inputs:\n") re_inputs = re.compile("Inputs:\n")
re_outputs = re.compile("Outputs:\n") re_outputs = re.compile("Outputs:\n")
re_compact_comment = re.compile("-----@@@-----([^\n]+)\n")
re_comment = re.compile("Comment: ([^\n]+)\n")
re_pubkey = re.compile("([1-9A-Za-z][^OIl]{42,45})\n") re_pubkey = re.compile("([1-9A-Za-z][^OIl]{42,45})\n")
def __init__(self, version, currency, issuers, inputs, outputs, def __init__(self, version, currency, issuers, inputs, outputs,
...@@ -52,7 +54,11 @@ SIGNATURE ...@@ -52,7 +54,11 @@ SIGNATURE
''' '''
Constructor Constructor
''' '''
if signatures:
super().__init__(version, currency, signatures) super().__init__(version, currency, signatures)
else:
super().__init__(version, currency, [])
self.issuers = issuers self.issuers = issuers
self.inputs = inputs self.inputs = inputs
self.outputs = outputs self.outputs = outputs
...@@ -90,10 +96,19 @@ SIGNATURE ...@@ -90,10 +96,19 @@ SIGNATURE
outputs.append(output_source) outputs.append(output_source)
n = n + 1 n = n + 1
return cls(version, currency, issuers, inputs, outputs, None, signatures) comment = None
if Transaction.re_comment.match(lines[n]):
comment = Transaction.re_compact_comment.match(lines[n]).group(1)
n = n + 1
while n < len(lines):
signatures.append(Transaction.re_signature.match(lines[n]).group(1))
n = n + 1
return cls(version, currency, issuers, inputs, outputs, comment, signatures)
@classmethod @classmethod
def from_raw(cls, raw): def from_signed_raw(cls, raw):
lines = raw.splitlines(True) lines = raw.splitlines(True)
n = 0 n = 0
...@@ -126,18 +141,21 @@ SIGNATURE ...@@ -126,18 +141,21 @@ SIGNATURE
lines = lines + 1 lines = lines + 1
if Transaction.re_outputs.match(lines[n]) is not None: if Transaction.re_outputs.match(lines[n]) is not None:
while Transaction.re_sign.match(lines[n]) is None: while not Transaction.re_comment.match(lines[n]):
output = OutputSource.from_inline(lines[n]) output = OutputSource.from_inline(lines[n])
outputs.append(output) outputs.append(output)
lines = lines + 1 lines = lines + 1
comment = Transaction.re_comment.match(lines[n]).group(1)
if Transaction.re_sign.match(lines[n]) is not None: if Transaction.re_sign.match(lines[n]) is not None:
while n < lines.len: while n < lines.len:
sign = Transaction.re_sign.match(lines[n]).group(1) sign = Transaction.re_sign.match(lines[n]).group(1)
signatures.append(sign) signatures.append(sign)
lines = lines + 1 lines = lines + 1
return cls(version, currency, issuers, inputs, outputs, signatures) return cls(version, currency, issuers, inputs, outputs,
comment, signatures)
def raw(self): def raw(self):
doc = """ doc = """
...@@ -242,15 +260,6 @@ class InputSource(): ...@@ -242,15 +260,6 @@ class InputSource():
amount = int(data.group(5)) amount = int(data.group(5))
return cls(index, source, number, txhash, amount) return cls(index, source, number, txhash, amount)
@classmethod
def from_compact(cls, number, compact):
data = InputSource.re_compact.match(compact)
index = int(data.group(1))
source = data.group(2)
txhash = data.group(3)
amount = int(data.group(4))
return cls(index, source, number, txhash, amount)
def inline(self): def inline(self):
return "{0}:{1}:{2}:{3}:{4}".format(self.index, return "{0}:{1}:{2}:{3}:{4}".format(self.index,
self.source, self.source,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment