From 5d4b84e3363a317511e88f3e1bb3c9b7041fdb3a Mon Sep 17 00:00:00 2001 From: Inso <insomniak.fr@gmail.com> Date: Sun, 14 Dec 2014 16:43:29 +0100 Subject: [PATCH] Removing old ucoinpy lib --- lib/ucoinpy/__init__.py | 21 - lib/ucoinpy/api/__init__.py | 0 lib/ucoinpy/api/bma/__init__.py | 139 ------- lib/ucoinpy/api/bma/blockchain/__init__.py | 151 ------- lib/ucoinpy/api/bma/network/__init__.py | 35 -- .../api/bma/network/peering/__init__.py | 51 --- lib/ucoinpy/api/bma/tx/__init__.py | 44 -- lib/ucoinpy/api/bma/wot/__init__.py | 89 ----- lib/ucoinpy/documents/__init__.py | 41 -- .../documents/test_transaction.py | 137 ------- lib/ucoinpy/documents/block.py | 287 ------------- lib/ucoinpy/documents/certification.py | 86 ---- lib/ucoinpy/documents/membership.py | 125 ------ lib/ucoinpy/documents/peer.py | 148 ------- lib/ucoinpy/documents/status.py | 84 ---- lib/ucoinpy/documents/transaction.py | 297 -------------- lib/ucoinpy/documents/ucoinpy/key/__init__.py | 39 -- lib/ucoinpy/key/__init__.py | 36 -- lib/ucoinpy/key/hdwallet.py | 378 ------------------ src/cutecoin/gui/processConfigureAccount.py | 2 +- src/cutecoin/models/account/__init__.py | 4 +- 21 files changed, 3 insertions(+), 2191 deletions(-) delete mode 100644 lib/ucoinpy/__init__.py delete mode 100644 lib/ucoinpy/api/__init__.py delete mode 100644 lib/ucoinpy/api/bma/__init__.py delete mode 100644 lib/ucoinpy/api/bma/blockchain/__init__.py delete mode 100644 lib/ucoinpy/api/bma/network/__init__.py delete mode 100644 lib/ucoinpy/api/bma/network/peering/__init__.py delete mode 100644 lib/ucoinpy/api/bma/tx/__init__.py delete mode 100644 lib/ucoinpy/api/bma/wot/__init__.py delete mode 100644 lib/ucoinpy/documents/__init__.py delete mode 100644 lib/ucoinpy/documents/_ucoinpy_test/documents/test_transaction.py delete mode 100644 lib/ucoinpy/documents/block.py delete mode 100644 lib/ucoinpy/documents/certification.py delete mode 100644 lib/ucoinpy/documents/membership.py delete mode 100644 lib/ucoinpy/documents/peer.py delete mode 100644 lib/ucoinpy/documents/status.py delete mode 100644 lib/ucoinpy/documents/transaction.py delete mode 100644 lib/ucoinpy/documents/ucoinpy/key/__init__.py delete mode 100644 lib/ucoinpy/key/__init__.py delete mode 100644 lib/ucoinpy/key/hdwallet.py diff --git a/lib/ucoinpy/__init__.py b/lib/ucoinpy/__init__.py deleted file mode 100644 index 354362cd..00000000 --- a/lib/ucoinpy/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# Authors: -# Caner Candan <caner@candan.fr>, http://caner.candan.fr -# - -PROTOCOL_VERSION="1" - -MANAGED_API=["BASIC_MERKLED_API"] diff --git a/lib/ucoinpy/api/__init__.py b/lib/ucoinpy/api/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/lib/ucoinpy/api/bma/__init__.py b/lib/ucoinpy/api/bma/__init__.py deleted file mode 100644 index fbd95eaa..00000000 --- a/lib/ucoinpy/api/bma/__init__.py +++ /dev/null @@ -1,139 +0,0 @@ -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# Authors: -# Caner Candan <caner@candan.fr>, http://caner.candan.fr -# - - -__all__ = ['api'] - -__author__ = 'Caner Candan' -__version__ = '0.10.0' -__nonsense__ = 'uCoin' - -import requests, logging, json -# import pylibscrypt - -logger = logging.getLogger("ucoin") - - -class ConnectionHandler(object): - """Helper class used by other API classes to ease passing server connection information.""" - - def __init__(self, server, port): - """ - Arguments: - - `server`: server hostname - - `port`: port number - """ - - self.server = server - self.port = port - - def __str__(self): - return 'connection info: %s:%d' % (self.server, self.port) - - -class API(object): - """APIRequest is a class used as an interface. The intermediate derivated classes are the modules and the leaf classes are the API requests.""" - - def __init__(self, connection_handler, module): - """ - Asks a module in order to create the url used then by derivated classes. - - Arguments: - - `module`: module name - - `connection_handler`: connection handler - """ - - self.module = module - self.connection_handler = connection_handler - self.headers = {} - - def reverse_url(self, path): - """ - Reverses the url using self.url and path given in parameter. - - Arguments: - - `path`: the request path - """ - - server, port = self.connection_handler.server, self.connection_handler.port - - url = 'http://%s:%d/%s' % (server, port, self.module) - return url + path - - def get(self, **kwargs): - """wrapper of overloaded __get__ method.""" - - return self.__get__(**kwargs) - - def post(self, **kwargs): - """wrapper of overloaded __post__ method.""" - - logger.debug('do some work with') - - data = self.__post__(**kwargs) - - logger.debug('and send back') - - return data - - def __get__(self, **kwargs): - """interface purpose for GET request""" - - pass - - def __post__(self, **kwargs): - """interface purpose for POST request""" - - pass - - def requests_get(self, path, **kwargs): - """ - Requests GET wrapper in order to use API parameters. - - Arguments: - - `path`: the request path - """ - - response = requests.get(self.reverse_url(path), params=kwargs, headers=self.headers) - - if response.status_code != 200: - raise ValueError('status code != 200 => %d (%s)' % (response.status_code, response.text)) - - return response - - def requests_post(self, path, **kwargs): - """ - Requests POST wrapper in order to use API parameters. - - Arguments: - - `path`: the request path - """ - - response = requests.post(self.reverse_url(path), data=kwargs, headers=self.headers) - - if response.status_code != 200: - raise ValueError('status code != 200 => %d (%s)' % (response.status_code, response.text)) - - return response - - def merkle_easy_parser(self, path, begin=None, end=None): - root = self.requests_get(path, leaves='true').json() - for leaf in root['leaves'][begin:end]: - yield self.requests_get(path, leaf=leaf).json()['leaf'] - -from . import network, blockchain, tx, wot diff --git a/lib/ucoinpy/api/bma/blockchain/__init__.py b/lib/ucoinpy/api/bma/blockchain/__init__.py deleted file mode 100644 index 03890265..00000000 --- a/lib/ucoinpy/api/bma/blockchain/__init__.py +++ /dev/null @@ -1,151 +0,0 @@ -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# Authors: -# Caner Candan <caner@candan.fr>, http://caner.candan.fr -# - -from .. import API, logging - -logger = logging.getLogger("ucoin/blockchain") - - -class Blockchain(API): - def __init__(self, connection_handler, module='blockchain'): - super(Blockchain, self).__init__(connection_handler, module) - - -class Parameters(Blockchain): - """GET the blockchain parameters used by this node.""" - - def __get__(self, **kwargs): - return self.requests_get('/parameters', **kwargs).json() - - -class Membership(Blockchain): - """POST a Membership document.""" - - def __post__(self, **kwargs): - assert 'membership' in kwargs - - return self.requests_post('/membership', **kwargs).json() - - -class Block(Blockchain): - """GET/POST a block from/to the blockchain.""" - - def __init__(self, connection_handler, number=None): - """ - Use the number parameter in order to select a block number. - - Arguments: - - `number`: block number to select - """ - - super(Block, self).__init__(connection_handler) - - self.number = number - - def __get__(self, **kwargs): - assert self.number is not None - return self.requests_get('/block/%d' % self.number, **kwargs).json() - - def __post__(self, **kwargs): - assert 'block' in kwargs - assert 'signature' in kwargs - - return self.requests_post('/block', **kwargs).json() - - -class Current(Blockchain): - """GET, same as block/[number], but return last accepted block.""" - - def __get__(self, **kwargs): - return self.requests_get('/current', **kwargs).json() - - -class Hardship(Blockchain): - """GET hardship level for given member's fingerprint for writing next block.""" - - def __init__(self, connection_handler, fingerprint): - """ - Use the number parameter in order to select a block number. - - Arguments: - - `fingerprint`: member fingerprint - """ - - super(Hardship, self).__init__(connection_handler) - - self.fingerprint = fingerprint - - def __get__(self, **kwargs): - assert self.fingerprint is not None - return self.requests_get('/hardship/%s' % self.fingerprint.upper(), **kwargs).json() - - -class Newcomers(Blockchain): - """GET, return block numbers containing newcomers.""" - - def __get__(self, **kwargs): - return self.requests_get('/with/newcomers', **kwargs).json() - - -class Certifications(Blockchain): - """GET, return block numbers containing certifications.""" - - def __get__(self, **kwargs): - return self.requests_get('/with/certs', **kwargs).json() - - -class Joiners(Blockchain): - """GET, return block numbers containing joiners.""" - - def __get__(self, **kwargs): - return self.requests_get('/with/joiners', **kwargs).json() - - -class Actives(Blockchain): - """GET, return block numbers containing actives.""" - - def __get__(self, **kwargs): - return self.requests_get('/with/actives', **kwargs).json() - - -class Leavers(Blockchain): - """GET, return block numbers containing leavers.""" - - def __get__(self, **kwargs): - return self.requests_get('/with/leavers', **kwargs).json() - - -class Excluded(Blockchain): - """GET, return block numbers containing excluded.""" - - def __get__(self, **kwargs): - return self.requests_get('/with/excluded', **kwargs).json() - - -class UD(Blockchain): - """GET, return block numbers containing universal dividend.""" - - def __get__(self, **kwargs): - return self.requests_get('/with/ud', **kwargs).json() - - -class TX(Blockchain): - """GET, return block numbers containing transactions.""" - - def __get__(self, **kwargs): - return self.requests_get('/with/tx', **kwargs).json() diff --git a/lib/ucoinpy/api/bma/network/__init__.py b/lib/ucoinpy/api/bma/network/__init__.py deleted file mode 100644 index 3d6c73ec..00000000 --- a/lib/ucoinpy/api/bma/network/__init__.py +++ /dev/null @@ -1,35 +0,0 @@ -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# Authors: -# Caner Candan <caner@candan.fr>, http://caner.candan.fr -# - -from .. import API, logging - -logger = logging.getLogger("ucoin/network") - - -class Network(API): - def __init__(self, connection_handler, module='network'): - super(Network, self).__init__(connection_handler, module) - - -class Peering(Network): - """GET peering information about a peer.""" - - def __get__(self, **kwargs): - return self.requests_get('/peering', **kwargs).json() - -from . import peering diff --git a/lib/ucoinpy/api/bma/network/peering/__init__.py b/lib/ucoinpy/api/bma/network/peering/__init__.py deleted file mode 100644 index 3ad7cde3..00000000 --- a/lib/ucoinpy/api/bma/network/peering/__init__.py +++ /dev/null @@ -1,51 +0,0 @@ -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# Authors: -# Caner Candan <caner@candan.fr>, http://caner.candan.fr -# - -from .. import Network, logging - -logger = logging.getLogger("ucoin/network/peering") - - -class Base(Network): - def __init__(self, connection_handler): - super(Base, self).__init__(connection_handler, 'network/peering') - - -class Peers(Base): - """GET peering entries of every node inside the currency network.""" - - def __get__(self, **kwargs): - """creates a generator with one peering entry per iteration.""" - - return self.merkle_easy_parser('/peers') - - def __post__(self, **kwargs): - assert 'entry' in kwargs - assert 'signature' in kwargs - - return self.requests_post('/peers', **kwargs).json() - - -class Status(Base): - """POST a network status document to this node in order notify of its status.""" - - def __post__(self, **kwargs): - assert 'status' in kwargs - assert 'signature' in kwargs - - return self.requests_post('/status', **kwargs).json() diff --git a/lib/ucoinpy/api/bma/tx/__init__.py b/lib/ucoinpy/api/bma/tx/__init__.py deleted file mode 100644 index a7adc5f3..00000000 --- a/lib/ucoinpy/api/bma/tx/__init__.py +++ /dev/null @@ -1,44 +0,0 @@ -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# Authors: -# Caner Candan <caner@candan.fr>, http://caner.candan.fr -# - -from .. import API, logging - -logger = logging.getLogger("ucoin/tx") - - -class Tx(API): - def __init__(self, connection_handler, module='tx'): - super(Tx, self).__init__(connection_handler, module) - - -class Process(Tx): - """POST a transaction.""" - - def __post__(self, **kwargs): - assert 'transaction' in kwargs - assert 'signature' in kwargs - - return self.requests_post('/process', **kwargs).json() - - -class Sources(Tx): - """Get transaction sources.""" - - def __get__(self, **kwargs): - assert self.pubkey is not None - return self.requests_get('/sources/%d' % self.pubkey, **kwargs).json() diff --git a/lib/ucoinpy/api/bma/wot/__init__.py b/lib/ucoinpy/api/bma/wot/__init__.py deleted file mode 100644 index 3e1c694a..00000000 --- a/lib/ucoinpy/api/bma/wot/__init__.py +++ /dev/null @@ -1,89 +0,0 @@ -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# Authors: -# Caner Candan <caner@candan.fr>, http://caner.candan.fr -# - -from .. import API, logging - -logger = logging.getLogger("ucoin/wot") - - -class WOT(API): - def __init__(self, connection_handler, module='wot'): - super(WOT, self).__init__(connection_handler, module) - - -class Add(WOT): - """POST Public key data.""" - - def __post__(self, **kwargs): - assert 'pubkey' in kwargs - assert 'self' in kwargs - assert 'other' in kwargs - - return self.requests_post('/add', **kwargs).json() - - -class Lookup(WOT): - """GET Public key data.""" - - def __init__(self, connection_handler, search, module='wot'): - super(WOT, self).__init__(connection_handler, module) - - self.search = search - - def __get__(self, **kwargs): - assert self.search is not None - - return self.requests_get('/lookup/%s' % self.search, **kwargs).json() - - -class CertifiersOf(WOT): - """GET Certification data over a member.""" - - def __init__(self, connection_handler, search, module='wot'): - super(WOT, self).__init__(connection_handler, module) - - self.search = search - - def __get__(self, **kwargs): - assert self.search is not None - - return self.requests_get('/certifiers-of/%s' % self.search, **kwargs).json() - - -class CertifiedBy(WOT): - """GET Certification data from a member.""" - - def __init__(self, connection_handler, search, module='wot'): - super(WOT, self).__init__(connection_handler, module) - - self.search = search - - def __get__(self, **kwargs): - assert self.search is not None - - return self.requests_get('/certified-by/%s' % self.search, **kwargs).json() - - -class Members(WOT): - """GET List all current members of the Web of Trust.""" - - def __init__(self, connection_handler, module='wot'): - super(WOT, self).__init__(connection_handler, module) - - def __get__(self, **kwargs): - return self.requests_get('/members', **kwargs).json() diff --git a/lib/ucoinpy/documents/__init__.py b/lib/ucoinpy/documents/__init__.py deleted file mode 100644 index 14a7f83d..00000000 --- a/lib/ucoinpy/documents/__init__.py +++ /dev/null @@ -1,41 +0,0 @@ -''' -Created on 3 déc. 2014 - -@author: inso -''' -import base58 -import re -from ..key import Base58Encoder -from nacl.encoding import Base64Encoder - - -class Document: - re_version = re.compile("Version: ([0-9]+)\n") - re_currency = re.compile("Currency: ([^\n]+)\n") - re_signature = re.compile("([A-Za-z0-9+/]+(?:=|==)?)\n") - - def __init__(self, version, currency, signatures): - self.version = version - self.currency = currency - 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 diff --git a/lib/ucoinpy/documents/_ucoinpy_test/documents/test_transaction.py b/lib/ucoinpy/documents/_ucoinpy_test/documents/test_transaction.py deleted file mode 100644 index ea169143..00000000 --- a/lib/ucoinpy/documents/_ucoinpy_test/documents/test_transaction.py +++ /dev/null @@ -1,137 +0,0 @@ -''' -Created on 12 déc. 2014 - -@author: inso -''' -import pytest -from ucoinpy.documents.transaction import Transaction -from mock import Mock - - -tx_compact = """TX:1:1:3:1:0 -HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY -0:T:65:D717FEC1993554F8EAE4CEA88DE5FBB6887CFAE8:4 -0:T:77:F80993776FB55154A60B3E58910C942A347964AD:15 -0:D:88:F4A47E39BC2A20EE69DCD5CAB0A9EB3C92FD8F7B:11 -BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g:30 -42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r -""" - -tx_raw = """Version: 1 -Type: Transaction -Currency: beta_brousouf -Issuers: -HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY -Inputs: -0:T:65:D717FEC1993554F8EAE4CEA88DE5FBB6887CFAE8:4 -0:T:77:F80993776FB55154A60B3E58910C942A347964AD:15 -0:D:88:F4A47E39BC2A20EE69DCD5CAB0A9EB3C92FD8F7B:11 -Outputs: -BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g:30 -Comment: -42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r -""" - - -class Test_Transaction: - def test_fromcompact(self): - tx = Transaction.from_compact("zeta_brousouf", tx_compact) - assert tx.version == 1 - assert tx.currency == "zeta_brousouf" - assert len(tx.issuers) == 1 - assert len(tx.inputs) == 3 - assert len(tx.outputs) == 1 - - assert tx.issuers[0] == "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY" - - assert tx.inputs[0].index == 0 - assert tx.inputs[0].source == 'T' - assert tx.inputs[0].number == 65 - assert tx.inputs[0].txhash == "D717FEC1993554F8EAE4CEA88DE5FBB6887CFAE8" - assert tx.inputs[0].amount == 4 - - assert tx.inputs[1].index == 0 - assert tx.inputs[1].source == 'T' - assert tx.inputs[1].number == 77 - assert tx.inputs[1].txhash == "F80993776FB55154A60B3E58910C942A347964AD" - assert tx.inputs[1].amount == 15 - - assert tx.inputs[2].index == 0 - assert tx.inputs[2].source == 'D' - assert tx.inputs[2].number == 88 - assert tx.inputs[2].txhash == "F4A47E39BC2A20EE69DCD5CAB0A9EB3C92FD8F7B" - assert tx.inputs[2].amount == 11 - - assert tx.outputs[0].pubkey == "BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g" - assert tx.outputs[0].amount == 30 - - assert tx.signatures[0] == "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r" - - def test_fromraw(self): - tx = Transaction.from_signed_raw(tx_raw) - assert tx.version == 1 - assert tx.currency == "beta_brousouf" - assert len(tx.issuers) == 1 - assert len(tx.inputs) == 3 - assert len(tx.outputs) == 1 - - assert tx.issuers[0] == "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY" - - assert tx.inputs[0].index == 0 - assert tx.inputs[0].source == 'T' - assert tx.inputs[0].number == 65 - assert tx.inputs[0].txhash == "D717FEC1993554F8EAE4CEA88DE5FBB6887CFAE8" - assert tx.inputs[0].amount == 4 - - assert tx.inputs[1].index == 0 - assert tx.inputs[1].source == 'T' - assert tx.inputs[1].number == 77 - assert tx.inputs[1].txhash == "F80993776FB55154A60B3E58910C942A347964AD" - assert tx.inputs[1].amount == 15 - - assert tx.inputs[2].index == 0 - assert tx.inputs[2].source == 'D' - assert tx.inputs[2].number == 88 - assert tx.inputs[2].txhash == "F4A47E39BC2A20EE69DCD5CAB0A9EB3C92FD8F7B" - assert tx.inputs[2].amount == 11 - - assert tx.outputs[0].pubkey == "BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g" - assert tx.outputs[0].amount == 30 - - assert tx.signatures[0] == "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r" - - def test_fromraw_toraw(self): - tx = Transaction.from_signed_raw(tx_raw) - rendered_tx = tx.signed_raw() - from_rendered_tx = Transaction.from_signed_raw(rendered_tx) - - assert from_rendered_tx.version == 1 - assert len(from_rendered_tx.issuers) == 1 - assert len(from_rendered_tx.inputs) == 3 - assert len(from_rendered_tx.outputs) == 1 - - assert from_rendered_tx.issuers[0] == "HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY" - - assert from_rendered_tx.inputs[0].index == 0 - assert from_rendered_tx.inputs[0].source == 'T' - assert from_rendered_tx.inputs[0].number == 65 - assert from_rendered_tx.inputs[0].txhash == "D717FEC1993554F8EAE4CEA88DE5FBB6887CFAE8" - assert from_rendered_tx.inputs[0].amount == 4 - - assert from_rendered_tx.inputs[1].index == 0 - assert from_rendered_tx.inputs[1].source == 'T' - assert from_rendered_tx.inputs[1].number == 77 - assert from_rendered_tx.inputs[1].txhash == "F80993776FB55154A60B3E58910C942A347964AD" - assert from_rendered_tx.inputs[1].amount == 15 - - assert from_rendered_tx.inputs[2].index == 0 - assert from_rendered_tx.inputs[2].source == 'D' - assert from_rendered_tx.inputs[2].number == 88 - assert from_rendered_tx.inputs[2].txhash == "F4A47E39BC2A20EE69DCD5CAB0A9EB3C92FD8F7B" - assert from_rendered_tx.inputs[2].amount == 11 - - assert from_rendered_tx.outputs[0].pubkey == "BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g" - assert from_rendered_tx.outputs[0].amount == 30 - - assert from_rendered_tx.signatures[0] == "42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r" - diff --git a/lib/ucoinpy/documents/block.py b/lib/ucoinpy/documents/block.py deleted file mode 100644 index 1bf08afe..00000000 --- a/lib/ucoinpy/documents/block.py +++ /dev/null @@ -1,287 +0,0 @@ -''' -Created on 2 déc. 2014 - -@author: inso -''' - -from .. import PROTOCOL_VERSION -from . import Document -from .certification import SelfCertification, Certification -from .membership import Membership -from .transaction import Transaction - -import re - - -class Block(Document): - ''' -Version: VERSION -Type: Block -Currency: CURRENCY -Nonce: NONCE -Number: BLOCK_NUMBER -PoWMin: NUMBER_OF_ZEROS -Time: GENERATED_ON -MedianTime: MEDIAN_DATE -UniversalDividend: DIVIDEND_AMOUNT -Issuer: ISSUER_KEY -PreviousHash: PREVIOUS_HASH -PreviousIssuer: PREVIOUS_ISSUER_KEY -Parameters: PARAMETERS -MembersCount: WOT_MEM_COUNT -Identities: -PUBLIC_KEY:SIGNATURE:TIMESTAMP:USER_ID -... -Joiners: -PUBLIC_KEY:SIGNATURE:NUMBER:HASH:TIMESTAMP:USER_ID -... -Actives: -PUBLIC_KEY:SIGNATURE:NUMBER:HASH:TIMESTAMP:USER_ID -... -Leavers: -PUBLIC_KEY:SIGNATURE:NUMBER:HASH:TIMESTAMP:USER_ID -... -Excluded: -PUBLIC_KEY -... -Certifications: -PUBKEY_FROM:PUBKEY_TO:BLOCK_NUMBER:SIGNATURE -... -Transactions: -COMPACT_TRANSACTION -... -BOTTOM_SIGNATURE - ''' - - re_type = re.compile("Type: (Block)\n") - re_noonce = re.compile("Nonce: ([0-9]+)\n") - re_number = re.compile("Number: ([0-9]+)\n") - re_powmin = re.compile("PoWMin: ([0-9]+)\n") - re_time = re.compile("Time: ([0-9]+)\n") - re_mediantime = re.compile("MedianTime: ([0-9]+)\n") - re_universaldividend = re.compile("UniversalDividend: ([0-9]+)\n") - re_issuer = re.compile("Issuer: ([1-9A-Za-z][^OIl]{42,45})\n") - re_previoushash = re.compile("PreviousHash: ([0-9a-fA-F]{5,40})\n") - re_previousissuer = re.compile("PreviousIssuer: ([1-9A-Za-z][^OIl]{42,45})\n") - re_parameters = re.compile("Parameters: ([0-9]+\.[0-9]+):([0-9]+):([0-9]+):([0-9]+):\ -([0-9]+):([0-9]+):([0-9]+):([0-9]+):([0-9]+):([0-9]+):([0-9]+):([0-9]+):([0-9]+):\ -([0-9]+\.[0-9]+)\n") - re_memberscount = re.compile("MembersCount: ([0-9]+)\n") - re_identities = re.compile("Identities:\n") - re_joiners = re.compile("Joiners:\n") - re_actives = re.compile("Actives:\n") - re_leavers = re.compile("Leavers:\n") - re_excluded = re.compile("Excluded:\n") - re_certifications = re.compile("Certifications:\n") - re_transactions = re.compile("Transactions:\n") - - 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, signature): - ''' - Constructor - ''' - if signature: - super().__init__(version, currency, [signature]) - else: - super().__init__(version, currency, []) - self.noonce = noonce - self.number = number - self.powmin = powmin - self.time = time - self.mediantime = mediantime - self.ud = ud - self.issuer = issuer - self.prev_hash = prev_hash - self.prev_issuer = prev_issuer - self.parameters = parameters - self.members_count = members_count - self.identities = identities - self.joiners = joiners - self.actives = actives - self.leavers = leavers - self.excluded = excluded - self.certifications = certifications - self.transactions = transactions - - @classmethod - def from_signed_raw(cls, raw, signature=None): - lines = raw.splitlines(True) - n = 0 - - version = int(Block.re_version.match(lines[n]).group(1)) - n = n + 1 - - Block.re_type.match(lines[n]).group(1) - n = n + 1 - - currency = Block.re_currency.match(lines[n]).group(1) - n = n + 1 - - noonce = int(Block.re_noonce.match(lines[n]).group(1)) - n = n + 1 - - number = int(Block.re_number.match(lines[n]).group(1)) - n = n + 1 - - powmin = int(Block.re_powmin.match(lines[n]).group(1)) - n = n + 1 - - time = int(Block.re_time.match(lines[n]).group(1)) - n = n + 1 - - mediantime = int(Block.re_mediantime.match(lines[n]).group(1)) - n = n + 1 - - ud = Block.re_universaldividend.match(lines[n]) - if ud is not None: - ud = int(ud.group(1)) - n = n + 1 - - issuer = Block.re_issuer.match(lines[n]).group(1) - n = n + 1 - - prev_hash = None - prev_issuer = None - if number > 0: - prev_hash = Block.re_previoushash.match(lines[n]).group(1) - n = n + 1 - - prev_issuer = Block.re_previousissuer.match(lines[n]).group(1) - n = n + 1 - - parameters = None - if number == 0: - parameters = Block.re_parameters.match(lines[n]).groups() - n = n + 1 - - members_count = int(Block.re_memberscount.match(lines[n]).group(1)) - n = n + 1 - - identities = [] - joiners = [] - actives = [] - leavers = [] - excluded = [] - certifications = [] - transactions = [] - - if Block.re_identities.match(lines[n]) is not None: - n = n + 1 - while Block.re_joiners.match(lines[n]) is None: - selfcert = SelfCertification.from_inline(version, currency, lines[n]) - identities.append(selfcert) - n = n + 1 - - if Block.re_joiners.match(lines[n]): - n = n + 1 - while Block.re_actives.match(lines[n]) is None: - membership = Membership.from_inline(version, currency, "IN", lines[n]) - joiners.append(membership) - n = n + 1 - - if Block.re_actives.match(lines[n]): - n = n + 1 - while Block.re_leavers.match(lines[n]) is None: - membership = Membership.from_inline(version, currency, "IN", lines[n]) - actives.append(membership) - n = n + 1 - - if Block.re_leavers.match(lines[n]): - n = n + 1 - while Block.re_excluded.match(lines[n]) is None: - membership = Membership.from_inline(version, currency, "OUT", lines[n]) - leavers.append(membership) - n = n + 1 - - if Block.re_excluded.match(lines[n]): - n = n + 1 - while Block.re_certifications.match(lines[n]) is None: - membership = Membership.from_inline(version, currency, "OUT", lines[n]) - excluded.append(membership) - n = n + 1 - - if Block.re_certifications.match(lines[n]): - n = n + 1 - while Block.re_transactions.match(lines[n]) is None: - certification = Certification.from_inline(version, currency, - prev_hash, lines[n]) - certifications.append(certification) - n = n + 1 - - if Block.re_transactions.match(lines[n]): - n = n + 1 - while not Block.re_signature.match(lines[n]): - transaction = Transaction.from_compact(version, lines[n]) - transactions.append(transaction) - n = n + 1 - - signature = Block.re_signature.match(lines[n]).group(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, signature) - - def raw(self): - doc = """Version: {0} -Type: Block -Currency: {1} -Nonce: {2} -Number: {3} -PoWMin: {4} -Time: {5} -MedianTime: {6} -""".format(self.version, - self.currency, - self.noonce, - self.number, - self.powmin, - self.time, - self.mediantime) - if self.ud: - doc += "UniversalDividend: {0}\n".format(self.ud) - - doc += "Issuer: {0}\n".format(self.issuer) - - 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: - doc += "{0}\n".format(identity.inline()) - - doc += "Joiners:\n" - for joiner in self.joiners: - doc += "{0}\n".format(joiner.inline()) - - doc += "Actives:\n" - for active in self.actives: - doc += "{0}\n".format(active.inline()) - - doc += "Leavers:\n" - for leaver in self.leavers: - doc += "{0]\n".format(leaver.inline()) - - doc += "Excluded:\n" - for exclude in self.excluded: - doc += "{0}\n".format(exclude.inline()) - - doc += "Certifications:\n" - for cert in self.certifications: - doc += "{0}\n".format(cert.inline()) - - doc += "Transactions:\n" - for transaction in self.transactions: - doc += "{0}\n".format(transaction.inline()) - - return doc diff --git a/lib/ucoinpy/documents/certification.py b/lib/ucoinpy/documents/certification.py deleted file mode 100644 index 3d758409..00000000 --- a/lib/ucoinpy/documents/certification.py +++ /dev/null @@ -1,86 +0,0 @@ -''' -Created on 2 déc. 2014 - -@author: inso -''' -import re - -from . import Document - - -class SelfCertification(Document): - ''' - A document discribing a self certification. - ''' - - 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, uid, signature): - if signature: - super().__init__(version, currency, [signature]) - else: - super().__init__(version, currency, []) - self.pubkey = pubkey - self.timestamp = ts - self.uid = uid - - @classmethod - def from_inline(cls, version, currency, inline): - selfcert_data = SelfCertification.re_inline.match(inline) - pubkey = selfcert_data.group(1) - signature = selfcert_data.group(2) - ts = int(selfcert_data.group(3)) - uid = selfcert_data.group(4) - return cls(version, currency, pubkey, ts, uid, signature) - - def raw(self): - 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): - ''' - A document describing a certification. - ''' - - 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") - re_timestamp = re.compile("META:TS:([0-9]+)-([0-9a-fA-F]{5,40})\n") - - def __init__(self, version, currency, pubkey_from, pubkey_to, - blockhash, blocknumber, signature): - ''' - Constructor - ''' - super().__init__(version, currency, [signature]) - self.pubkey_from = pubkey_from - self.pubkey_to = pubkey_to - self.blockhash = blockhash - self.blocknumber = blocknumber - - @classmethod - def from_inline(cls, version, currency, blockhash, inline): - cert_data = Certification.re_inline.match(inline) - pubkey_from = cert_data.group(1) - pubkey_to = cert_data.group(2) - blocknumber = int(cert_data.group(3)) - if blocknumber == 0: - blockhash = "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709" - signature = cert_data.group(4) - return cls(version, currency, pubkey_from, pubkey_to, - blockhash, blocknumber, signature) - - def raw(self, selfcert): - 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]) - diff --git a/lib/ucoinpy/documents/membership.py b/lib/ucoinpy/documents/membership.py deleted file mode 100644 index 3f142a7f..00000000 --- a/lib/ucoinpy/documents/membership.py +++ /dev/null @@ -1,125 +0,0 @@ -''' -Created on 2 déc. 2014 - -@author: inso -''' -from .. import PROTOCOL_VERSION -from . import Document - -import re - - -class Membership(Document): - ''' - This is a utility class to generate membership documents : - Version: VERSION - Type: Membership - Currency: CURRENCY_NAME - Issuer: ISSUER - Block: NUMBER-HASH - Membership: MEMBERSHIP_TYPE - UserID: USER_ID - CertTS: CERTIFICATION_TS - ''' - - # PUBLIC_KEY:SIGNATURE:NUMBER:HASH:TIMESTAMP:USER_ID - 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") - 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, - membership_type, uid, cert_ts, signature): - ''' - Constructor - ''' - if signature: - super().__init__(version, currency, [signature]) - else: - super().__init__(version, currency, []) - self.issuer = issuer - self.block_number = block_number - self.block_hash = block_hash - self.membership_type = membership_type - self.uid = uid - self.cert_ts = cert_ts - - @classmethod - def from_inline(cls, version, currency, membership_type, inline): - data = Membership.re_inline.match(inline) - issuer = data.group(1) - signature = data.group(2) - block_number = int(data.group(3)) - block_hash = data.group(4) - cert_ts = int(data.group(5)) - uid = data.group(6) - return cls(version, currency, issuer, block_number, - block_hash, membership_type, uid, cert_ts, signature) - - @classmethod - def from_signed_raw(cls, raw, signature=None): - lines = raw.splitlines(True) - 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): - return """Version: {0} -Type: Membership -Currency: {1} -Issuer: {2} -Block: {3}-{4} -Membership: {5} -UserID: {6} -CertTS: {7} -""".format(self.version, - self.currency, - self.issuer, - self.block_number, self.block_hash, - self.membership_type, - self.uid, - self.cert_ts) - - def inline(self): - return "{0}:{1}:{2}:{3}:{4}:{5}".format(self.issuer, - self.signatures[0], - self.block_number, - self.block_hash, - self.cert_ts, - self.uid) diff --git a/lib/ucoinpy/documents/peer.py b/lib/ucoinpy/documents/peer.py deleted file mode 100644 index 1148785a..00000000 --- a/lib/ucoinpy/documents/peer.py +++ /dev/null @@ -1,148 +0,0 @@ -''' -Created on 2 déc. 2014 - -@author: inso -''' - -import re - -from . import Document -from .. import PROTOCOL_VERSION, MANAGED_API - - -class Peer(Document): - """ - Version: VERSION - Type: Peer - Currency: CURRENCY_NAME - PublicKey: NODE_PUBLICKEY - Block: BLOCK - Endpoints: - END_POINT_1 - END_POINT_2 - END_POINT_3 - [...] - """ - - 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]) - else: - super().__init__(version, currency, []) - - self.pubkey = pubkey - self.blockid = blockid - self.endpoints = endpoints - - @classmethod - def from_signed_raw(cls, raw): - lines = raw.splitlines(True) - 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): - doc = """Version: {0} -Type: Peer -Currency: {1} -PublicKey: {2} -Block: {3} -Endpoints: -""".format(self.version, self.currency, self.pubkey, self.blockid) - - for endpoint in self.endpoints: - doc += "{0}\n".format(endpoint.inline()) - - doc += "{0}\n".format(self.signatures[0]) - return doc - - -class Endpoint(): - """ - Describing endpoints - """ - - @staticmethod - def from_inline(inline): - for api in MANAGED_API: - if (inline.startswith(api)): - if (api == "BASIC_MERKLED_API"): - 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) - - def inline(self): - doc = self.api - for p in self.properties: - doc += " {0}".format(p) - return doc - - -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(1) - ipv4 = m.group(2) - ipv6 = m.group(3) - port = int(m.group(4)) - return cls(server, ipv4, ipv6, port) - - def __init__(self, server, ipv4, ipv6, port): - self.server = server - self.ipv4 = ipv4 - self.ipv6 = ipv6 - self.port = port - - def inline(self): - return "BASIC_MERKLED_API {DNS} {IPv4} {IPv6} {PORT}" \ - .format(DNS=self.server, - IPv4=self.ipv4, - IPv6=self.ipv6, - PORT=self.port) diff --git a/lib/ucoinpy/documents/status.py b/lib/ucoinpy/documents/status.py deleted file mode 100644 index 5b25bfae..00000000 --- a/lib/ucoinpy/documents/status.py +++ /dev/null @@ -1,84 +0,0 @@ -''' -Created on 2 déc. 2014 - -@author: inso -''' - -import re -from . import Document - - -class Status(Document): - ''' - Version: VERSION - Type: Status - Currency: CURRENCY_NAME - Status: STATUS - Block: BLOCK - From: SENDER - 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, - recipient, signature): - ''' - Constructor - ''' - if signature: - super().__init__(version, currency, [signature]) - else: - super().__init__(version, currency, []) - - self.status = status - self.blockid = blockid - self.sender = sender - self.recipient = recipient - - @classmethod - def from_signed_raw(cls, raw): - lines = raw.splitlines(True) - 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): - return '''Version: {0} -Type: Status -Currency: {1} -Status: {2} -Block: {3} -From: {4} -To: {5} -'''.format(self.version, self.currency, self.status, - self.blockid, self.sender, self.recipient) diff --git a/lib/ucoinpy/documents/transaction.py b/lib/ucoinpy/documents/transaction.py deleted file mode 100644 index e5fd76ed..00000000 --- a/lib/ucoinpy/documents/transaction.py +++ /dev/null @@ -1,297 +0,0 @@ -''' -Created on 2 déc. 2014 - -@author: inso -''' - -from . import Document -import re - - -class Transaction(Document): - ''' -Document format : -Version: VERSION -Type: Transaction -Currency: CURRENCY_NAME -Issuers: -PUBLIC_KEY -... -Inputs: -INDEX:SOURCE:NUMBER:FINGERPRINT:AMOUNT -... -Outputs: -PUBLIC_KEY:AMOUNT -... -Comment: COMMENT -... - - -Compact format : -TX:VERSION:NB_ISSUERS:NB_INPUTS:NB_OUTPUTS:HAS_COMMENT -PUBLIC_KEY:INDEX -... -INDEX:SOURCE:FINGERPRINT:AMOUNT -... -PUBLIC_KEY:AMOUNT -... -COMMENT -SIGNATURE -... - ''' - - re_type = re.compile("Type: (Transaction)\n") - re_header = re.compile("TX:([0-9])+:([0-9])+:([0-9])+:([0-9])+:(0|1)\n") - re_issuers = re.compile("Issuers:\n") - re_inputs = re.compile("Inputs:\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") - - def __init__(self, version, currency, issuers, inputs, outputs, - comment, signatures): - ''' - Constructor - ''' - if signatures: - super().__init__(version, currency, signatures) - else: - super().__init__(version, currency, []) - - self.issuers = issuers - self.inputs = inputs - self.outputs = outputs - self.comment = comment - - @classmethod - def from_compact(cls, currency, compact): - lines = compact.splitlines(True) - n = 0 - - header_data = Transaction.re_header.match(lines[n]) - version = int(header_data.group(1)) - issuers_num = int(header_data.group(2)) - inputs_num = int(header_data.group(3)) - outputs_num = int(header_data.group(4)) - n = n + 1 - - issuers = [] - inputs = [] - outputs = [] - signatures = [] - - for i in range(0, issuers_num): - issuer = Transaction.re_pubkey.match(lines[n]).group(1) - issuers.append(issuer) - n = n + 1 - - for i in range(0, inputs_num): - input_source = InputSource.from_inline(lines[n]) - inputs.append(input_source) - n = n + 1 - - for i in range(0, outputs_num): - output_source = OutputSource.from_inline(lines[n]) - outputs.append(output_source) - n = n + 1 - - 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 - def from_signed_raw(cls, raw): - lines = raw.splitlines(True) - n = 0 - - version = int(Transaction.re_version.match(lines[n]).group(1)) - n = n + 1 - - Transaction.re_type.match(lines[n]).group(1) - n = n + 1 - - currency = Transaction.re_currency.match(lines[n]).group(1) - n = n + 1 - - issuers = [] - inputs = [] - outputs = [] - signatures = [] - - if Transaction.re_issuers.match(lines[n]): - n = n + 1 - while Transaction.re_inputs.match(lines[n]) is None: - issuer = Transaction.re_pubkey.match(lines[n]).group(1) - issuers.append(issuer) - n = n + 1 - - if Transaction.re_inputs.match(lines[n]): - n = n + 1 - while Transaction.re_outputs.match(lines[n]) is None: - input_source = InputSource.from_inline(lines[n]) - inputs.append(input_source) - n = n + 1 - - if Transaction.re_outputs.match(lines[n]) is not None: - n = n + 1 - while not Transaction.re_comment.match(lines[n]): - output = OutputSource.from_inline(lines[n]) - outputs.append(output) - n = n + 1 - - comment = Transaction.re_comment.match(lines[n]).group(1) - n = n + 1 - - if Transaction.re_signature.match(lines[n]) is not None: - while n < len(lines): - sign = Transaction.re_signature.match(lines[n]).group(1) - signatures.append(sign) - n = n + 1 - - return cls(version, currency, issuers, inputs, outputs, - comment, signatures) - - def raw(self): - doc = """Version: {0} -Type: Transaction -Currency: {1} -Issuers: -""".format(self.version, - self.currency) - - for p in self.issuers: - doc += "{0}\n".format(p) - - doc += "Inputs:\n" - for i in self.inputs: - doc += "{0}\n".format(i.inline()) - - doc += "Outputs:\n" - for o in self.outputs: - doc += "{0}\n".format(o.inline()) - - doc += "Comment: " - if self.comment: - doc += "{0}".format(self.comment) - doc += "\n" - - for signature in self.signatures: - doc += "{0}\n".format(signature) - - return doc - - def compact(self): - ''' - Return a transaction in its compact format. - ''' - """TX:VERSION:NB_ISSUERS:NB_INPUTS:NB_OUTPUTS:HAS_COMMENT -PUBLIC_KEY:INDEX -... -INDEX:SOURCE:FINGERPRINT:AMOUNT -... -PUBLIC_KEY:AMOUNT -... -COMMENT -""" - doc = "TX:{0}:{1}:{2}:{3}:{4}".format(self.version, - self.issuers.len, - self.inputs.len, - self.outputs.len, - '1' if self.Comment else '0') - for pubkey in self.issuers: - doc += "{0}\n".format(pubkey) - for i in self.inputs: - doc += "{0}\n".format(i.compact()) - for o in self.outputs: - doc += "{0}\n".format(o.inline()) - if self.comment: - doc += "-----@@@----- {0}\n".format(self.comment) - for s in self.signatures: - doc += "{0}\n".format(s) - - return doc - - -class SimpleTransaction(Transaction): - ''' -As transaction class, but for only one issuer. -... - ''' - def __init__(self, version, currency, issuer, - single_input, outputs, comment, signature): - ''' - Constructor - ''' - super().__init__(version, currency, [issuer], [single_input], - outputs, comment, [signature]) - - -class InputSource(): - ''' - A Transaction INPUT - - Compact : - INDEX:SOURCE:FINGERPRINT:AMOUNT - ''' - re_inline = re.compile("([0-9]+):(D|T):([0-9]+):\ -([0-9a-fA-F]{5,40}):([0-9]+)\n") - re_compact = re.compile("([0-9]+):(D|T):([0-9a-fA-F]{5,40}):([0-9]+)\n") - - def __init__(self, index, source, number, txhash, amount): - self.index = index - self.source = source - self.number = number - self.txhash = txhash - self.amount = amount - - @classmethod - def from_inline(cls, inline): - data = InputSource.re_inline.match(inline) - index = int(data.group(1)) - source = data.group(2) - number = int(data.group(3)) - txhash = data.group(4) - amount = int(data.group(5)) - return cls(index, source, number, txhash, amount) - - def inline(self): - return "{0}:{1}:{2}:{3}:{4}".format(self.index, - self.source, - self.number, - self.txhash, - self.amount) - - def compact(self): - return "{0}:{1}:{2}:{3}".format(self.index, - self.source, - self.txhash, - self.amount) - - -class OutputSource(): - ''' - A Transaction OUTPUT - ''' - re_inline = re.compile("([1-9A-Za-z][^OIl]{42,45}):([0-9]+)") - - def __init__(self, pubkey, amount): - self.pubkey = pubkey - self.amount = amount - - @classmethod - def from_inline(cls, inline): - data = OutputSource.re_inline.match(inline) - pubkey = data.group(1) - amount = int(data.group(2)) - return cls(pubkey, amount) - - def inline(self): - return "{0}:{1}".format(self.pubkey, self.amount) diff --git a/lib/ucoinpy/documents/ucoinpy/key/__init__.py b/lib/ucoinpy/documents/ucoinpy/key/__init__.py deleted file mode 100644 index d28d328f..00000000 --- a/lib/ucoinpy/documents/ucoinpy/key/__init__.py +++ /dev/null @@ -1,39 +0,0 @@ -''' -Ucoin public and private keys - -@author: inso -''' - -import base58 -import base64 -import scrypt -from nacl.signing import SigningKey as NaclSigningKey -from nacl.encoding import Base64Encoder - - -SEED_LENGTH = 32 # Length of the key -crypto_sign_BYTES = 64 -SCRYPT_PARAMS = {'N': 4096, - 'r': 16, - 'p': 1 - } - - -class SigningKey(NaclSigningKey): - def __init__(self, password, salt): - seed = scrypt.hash(password, salt, - SCRYPT_PARAMS['N'], SCRYPT_PARAMS['r'], SCRYPT_PARAMS['p'], - SEED_LENGTH) - seedb64 = base64.b64encode(seed) - super.__init__(seedb64, Base64Encoder) - self.pubkey = Base58Encoder.encode(self.verify_key.key) - - -class Base58Encoder(object): - @staticmethod - def encode(data): - return base58.b58encode(data) - - @staticmethod - def decode(data): - return base58.b58decode(data) diff --git a/lib/ucoinpy/key/__init__.py b/lib/ucoinpy/key/__init__.py deleted file mode 100644 index 1733e547..00000000 --- a/lib/ucoinpy/key/__init__.py +++ /dev/null @@ -1,36 +0,0 @@ -''' -Ucoin public and private keys - -@author: inso -''' - -import base58 -import base64 -import scrypt -from nacl.signing import SigningKey as NaclSigningKey - - -SEED_LENGTH = 32 # Length of the key -crypto_sign_BYTES = 64 -SCRYPT_PARAMS = {'N': 4096, - 'r': 16, - 'p': 1 - } - - -class SigningKey(NaclSigningKey): - def __init__(self, password, salt): - seed = scrypt.hash(password, salt, - SCRYPT_PARAMS['N'], SCRYPT_PARAMS['r'], SCRYPT_PARAMS['p'], - SEED_LENGTH) - seedb64 = base64.b64encode(seed) - - -class Base58Encoder(object): - @staticmethod - def encode(data): - return base58.b58encode(data) - - @staticmethod - def decode(data): - return base58.b58decode(data) diff --git a/lib/ucoinpy/key/hdwallet.py b/lib/ucoinpy/key/hdwallet.py deleted file mode 100644 index dffb5fff..00000000 --- a/lib/ucoinpy/key/hdwallet.py +++ /dev/null @@ -1,378 +0,0 @@ -''' -HD Wallet inspired from Bip32 wallets. - -@author: inso -''' -''' -import os -import hmac -import hashlib -import ed25519 -import struct -import base58 -import base64 - -from hashlib import sha256 -from ecdsa.curves import SECP256k1 -from ecdsa.ecdsa import int_to_string, string_to_int -from ecdsa.numbertheory import square_root_mod_prime as sqrt_mod - -MIN_ENTROPY_LEN = 128 # bits -HDWALLET_HARDENED = 0x80000000 # choose from hardened set of child keys -CURVE_GEN = ecdsa.ecdsa.generator_secp256k1 -CURVE_ORDER = CURVE_GEN.order() -FIELD_ORDER = SECP256k1.curve.p() -INFINITY = ecdsa.ellipticcurve.INFINITY - - -class HDWalletKey(object): - - # Static initializers to create from entropy or external formats - # - @staticmethod - def fromEntropy(entropy, public=False): - "Create a HDWallet using supplied entropy >= MIN_ENTROPY_LEN" - if entropy == None: - entropy = os.urandom(MIN_ENTROPY_LEN/8) # Python doesn't have os.random() - if not len(entropy) >= MIN_ENTROPY_LEN/8: - raise ValueError("Initial entropy %i must be at least %i bits" % - (len(entropy), MIN_ENTROPY_LEN)) - I = hmac.new("UCoin seed", entropy, hashlib.sha512).digest() - - Il, Ir = I[:32], I[32:] - # FIXME test Il for 0 or less than SECP256k1 prime field order - key = HDWalletKey(secret=Il, chain=Ir, depth=0, index=0, fpr='\0\0\0\0', public=False) - if public: - key.SetPublic() - return key - - @staticmethod - def fromExtendedKey(xkey, public=False): - """ - Create a HDWallet by importing from extended private or public key string - - If public is True, return a public-only key regardless of input type. - """ - # Sanity checks - raw = base58.b58decode_check(xkey) - # To fix - #if len(raw) != 78: - # raise ValueError("extended key format wrong length") - - # Verify address version/type - #version = raw[:4] - #if version == EX_MAIN_PRIVATE: - # raise ValueError("unknown extended key version") - - # Extract remaining fields - depth = ord(raw[4]) - fpr = raw[5:9] - child = struct.unpack(">L", raw[9:13])[0] - chain = raw[13:45] - secret = raw[45:78] - - # Extract private key or public key point - if keytype == 'xprv': - secret = secret[1:] - else: - # Recover public curve point from compressed key - lsb = ord(secret[0]) & 1 - x = string_to_int(secret[1:]) - ys = (x**3+7) % FIELD_ORDER # y^2 = x^3 + 7 mod p - y = sqrt_mod(ys, FIELD_ORDER) - if y & 1 != lsb: - y = FIELD_ORDER-y - point = ecdsa.ellipticcurve.Point(SECP256k1.curve, x, y) - secret = ecdsa.VerifyingKey.from_public_point(point, curve=SECP256k1) - - is_pubkey = (keytype == 'xpub') - key = HDWalletKey(secret=secret, chain=chain, depth=depth, index=child, - fpr=fpr, public=is_pubkey) - if not is_pubkey and public: - key = key.SetPublic() - return key - - - # Normal class initializer - def __init__(self, secret, chain, depth, index, fpr, public=False): - """ - Create a public or private BIP32Key using key material and chain code. - - secret This is the source material to generate the keypair, either a - 32-byte string representation of a private key, or the ECDSA - library object representing a public key. - - chain This is a 32-byte string representation of the chain code - - depth Child depth; parent increments its own by one when assigning this - - index Child index - - fpr Parent fingerprint - - public If true, this keypair will only contain a public key and can only create - a public key chain. - """ - - self.public = public - if public is False: - self.k = ed25519.SigningKey(base58.b58decode(secret)) - self.K = self.k.get_verifying_key() - else: - self.k = None - self.K = secret - - self.C = chain - self.depth = depth - self.index = index - self.parent_fpr = fpr - - # Internal methods not intended to be called externally - def _hmac(self, data): - """ - Calculate the HMAC-SHA512 of input data using the chain code as key. - - Returns a tuple of the left and right halves of the HMAC - """ - I = hmac.new(self.C, data, hashlib.sha512).digest() - return (I[:32], I[32:]) - - def _CKDpriv(self, i): - """ - Create a child key of index 'i'. - - If the most significant bit of 'i' is set, then select from the - hardened key set, otherwise, select a regular child key. - - Returns a BIP32Key constructed with the child key parameters, - or None if i index would result in an invalid key. - """ - # Index as bytes, BE - i_str = struct.pack(">L", i) - - # Data to HMAC - if i & HDWALLET_HARDENED: - data = b'\0' + self.k.to_string() + i_str - else: - data = self.PublicKey() + i_str - # Get HMAC of data - (Il, Ir) = self._hmac(data) - - # Construct new key material from Il and current private key - Il_int = string_to_int(Il) - if Il_int > CURVE_ORDER: - return None - pvt_int = string_to_int(self.k.to_string()) - k_int = (Il_int + pvt_int) % CURVE_ORDER - if (k_int == 0): - return None - secret = (b'\0'*32 + int_to_string(k_int))[-32:] - - # Construct and return a new BIP32Key - return HDWalletKey(secret=secret, chain=Ir, depth=self.depth+1, - index=i, fpr=self.Fingerprint(), public=False) - - def _CKDpub(self, i): - """ - Create a publicly derived child key of index 'i'. - - If the most significant bit of 'i' is set, this is - an error. - - Returns a HDWalletKey constructed with the child key parameters, - or None if index would result in invalid key. - """ - - if i & HDWALLET_HARDENED: - raise Exception("Cannot create a hardened child key using public child derivation") - - # Data to HMAC. Same as CKDpriv() for public child key. - data = self.PublicKey() + struct.pack(">L", i) - - # Get HMAC of data - (Il, Ir) = self.hmac(data) - - # Construct curve point Il*G+K - Il_int = string_to_int(Il) - if Il_int >= CURVE_ORDER: - return None - point = Il_int*CURVE_GEN + self.K.pubkey.point - if point == INFINITY: - return None - - # Retrieve public key based on curve point - K_i = ed25519.VerifyingKey.from_public_point(point, curve=SECP256k1) - - # Construct and return a new BIP32Key - return HDWalletKey(secret=K_i, chain=Ir, depth=self.depth, index=i, fpr=self.Fingerprint(), public=True) - - - # Public methods - # - def ChildKey(self, i): - """ - Create and return a child key of this one at index 'i'. - - The index 'i' should be summed with BIP32_HARDEN to indicate - to use the private derivation algorithm. - """ - if self.public is False: - return self.CKDpriv(i) - else: - return self.CKDpub(i) - - - def SetPublic(self): - "Convert a private BIP32Key into a public one" - self.k = None - self.public = True - - - def PrivateKey(self): - "Return private key as string" - if self.public: - raise Exception("Publicly derived deterministic keys have no private half") - else: - return self.k.to_string() - - - def PublicKey(self): - "Return compressed public key encoding" - if self.K.pubkey.point.y() & 1: - ck = b'\3'+int_to_string(self.K.pubkey.point.x()) - else: - ck = b'\2'+int_to_string(self.K.pubkey.point.x()) - return ck - - - def ChainCode(self): - "Return chain code as string" - return self.C - - - def Identifier(self): - "Return key identifier as string" - cK = self.PublicKey() - return hashlib.new('ripemd160', sha256(cK).digest()).digest() - - - def Fingerprint(self): - "Return key fingerprint as string" - return self.Identifier()[:4] - - - def Address(self): - "Return compressed public key address" - vh160 = '\x00'+self.Identifier() - return Base58.check_encode(vh160) - - - def WalletImportFormat(self): - "Returns private key encoded for wallet import" - if self.public: - raise Exception("Publicly derived deterministic keys have no private half") - raw = '\x80' + self.k.to_string() + '\x01' # Always compressed - return Base58.check_encode(raw) - - - def ExtendedKey(self, private=True, encoded=True): - "Return extended private or public key as string, optionally Base58 encoded" - if self.public is True and private is True: - raise Exception("Cannot export an extended private key from a public-only deterministic key") - version = EX_MAIN_PRIVATE if private else EX_MAIN_PUBLIC - depth = chr(self.depth) - fpr = self.parent_fpr - child = struct.pack('>L', self.index) - chain = self.C - if self.public is True or private is False: - data = self.PublicKey() - else: - data = '\x00' + self.PrivateKey() - raw = version+depth+fpr+child+chain+data - if not encoded: - return raw - else: - return Base58.check_encode(raw) - - # Debugging methods - # - def dump(self): - "Dump key fields mimicking the BIP0032 test vector format" - print " * Identifier" - print " * (hex): ", self.Identifier().encode('hex') - print " * (fpr): ", self.Fingerprint().encode('hex') - print " * (main addr):", self.Address() - if self.public is False: - print " * Secret key" - print " * (hex): ", self.PrivateKey().encode('hex') - print " * (wif): ", self.WalletImportFormat() - print " * Public key" - print " * (hex): ", self.PublicKey().encode('hex') - print " * Chain code" - print " * (hex): ", self.C.encode('hex') - print " * Serialized" - print " * (pub hex): ", self.ExtendedKey(private=False, encoded=False).encode('hex') - print " * (prv hex): ", self.ExtendedKey(private=True, encoded=False).encode('hex') - print " * (pub b58): ", self.ExtendedKey(private=False, encoded=True) - print " * (prv b58): ", self.ExtendedKey(private=True, encoded=True) - - -if __name__ == "__main__": - import sys - - # BIP0032 Test vector 1 - entropy='000102030405060708090A0B0C0D0E0F'.decode('hex') - m = BIP32Key.fromEntropy(entropy) - print "Test vector 1:" - print "Master (hex):", entropy.encode('hex') - print "* [Chain m]" - m.dump() - - print "* [Chain m/0h]" - m = m.ChildKey(0+BIP32_HARDEN) - m.dump() - - print "* [Chain m/0h/1]" - m = m.ChildKey(1) - m.dump() - - print "* [Chain m/0h/1/2h]" - m = m.ChildKey(2+BIP32_HARDEN) - m.dump() - - print "* [Chain m/0h/1/2h/2]" - m = m.ChildKey(2) - m.dump() - - print "* [Chain m/0h/1/2h/2/1000000000]" - m = m.ChildKey(1000000000) - m.dump() - - # BIP0032 Test vector 2 - entropy = 'fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542'.decode('hex') - m = BIP32Key.fromEntropy(entropy) - print "Test vector 2:" - print "Master (hex):", entropy.encode('hex') - print "* [Chain m]" - m.dump() - - print "* [Chain m/0]" - m = m.ChildKey(0) - m.dump() - - print "* [Chain m/0/2147483647h]" - m = m.ChildKey(2147483647+BIP32_HARDEN) - m.dump() - - print "* [Chain m/0/2147483647h/1]" - m = m.ChildKey(1) - m.dump() - - print "* [Chain m/0/2147483647h/1/2147483646h]" - m = m.ChildKey(2147483646+BIP32_HARDEN) - m.dump() - - print "* [Chain m/0/2147483647h/1/2147483646h/2]" - m = m.ChildKey(2) - m.dump() -''' \ No newline at end of file diff --git a/src/cutecoin/gui/processConfigureAccount.py b/src/cutecoin/gui/processConfigureAccount.py index daa35b50..13c46c67 100644 --- a/src/cutecoin/gui/processConfigureAccount.py +++ b/src/cutecoin/gui/processConfigureAccount.py @@ -73,7 +73,7 @@ class StepPageKey(Step): salt = self.config_dialog.edit_email.text() password = self.config_dialog.edit_password.text() self.config_dialog.account.salt = salt - self.config_dialog.account.pubkey = SigningKey(salt, password).public_key + self.config_dialog.account.pubkey = SigningKey(salt, password).pubkey model = CommunitiesListModel(self.config_dialog.account) self.config_dialog.list_communities.setModel(model) diff --git a/src/cutecoin/models/account/__init__.py b/src/cutecoin/models/account/__init__.py index ea510836..510027f1 100644 --- a/src/cutecoin/models/account/__init__.py +++ b/src/cutecoin/models/account/__init__.py @@ -36,11 +36,11 @@ class Account(object): self.contacts = contacts @classmethod - def create(cls, salt, pubkey, name, communities, wallets, confpath): + def create(cls, name, communities, wallets, confpath): ''' Constructor ''' - account = cls(salt, pubkey, name, communities, wallets, []) + account = cls(None, None, name, communities, wallets, []) return account @classmethod -- GitLab