diff --git a/config b/config new file mode 100644 index 0000000000000000000000000000000000000000..6bc8cd1680a70ccb9858283be3ef95c223f729bb --- /dev/null +++ b/config @@ -0,0 +1 @@ +{"prefer_hash_algorithm":8,"encryption_cipher":9,"compression":1,"show_version":true,"show_comment":true,"integrity_protect":true,"composition_behavior":0,"keyserver":"keyserver.linux.it"} \ No newline at end of file diff --git a/ucoinpy/api/bma/__init__.py b/ucoinpy/api/bma/__init__.py index d126a82a74357e4acacdc898e432b48b9f4270c1..464d65613523d4364e4de9698c4c824e7b81f301 100644 --- a/ucoinpy/api/bma/__init__.py +++ b/ucoinpy/api/bma/__init__.py @@ -20,11 +20,12 @@ __all__ = ['api'] __author__ = 'Caner Candan' -__version__ = '0.10.0' +__version__ = '0.11.0' __nonsense__ = 'uCoin' -import requests, logging, json -# import pylibscrypt +PROTOCOL_VERSION = "1" + +import aiohttp, requests, asyncio, logging, json logger = logging.getLogger("ucoin") @@ -93,14 +94,13 @@ class API(object): def __get__(self, **kwargs): """interface purpose for GET request""" - pass def __post__(self, **kwargs): """interface purpose for POST request""" - pass + @asyncio.coroutine def requests_get(self, path, **kwargs): """ Requests GET wrapper in order to use API parameters. @@ -108,12 +108,12 @@ class API(object): Arguments: - `path`: the request path """ + logging.debug("Request : {0}".format(self.reverse_url(path))) + response = yield from asyncio.wait_for(aiohttp.get(self.reverse_url(path), params=kwargs, + headers=self.headers), 15) - response = requests.get(self.reverse_url(path), params=kwargs, - headers=self.headers, timeout=15) - - if response.status_code != 200: - raise ValueError('status code != 200 => %d (%s)' % (response.status_code, response.text)) + if response.status != 200: + raise ValueError('status code != 200 => %d (%s)' % (response.status, (yield from response.text()))) return response @@ -128,17 +128,13 @@ class API(object): kwargs['self'] = kwargs.pop('self_') logging.debug("POST : {0}".format(kwargs)) - response = requests.post(self.reverse_url(path), data=kwargs, headers=self.headers, + response = yield from asyncio.wait_for( + aiohttp.post(self.reverse_url(path), data=kwargs, headers=self.headers), timeout=15) - if response.status_code != 200: - raise ValueError('status code != 200 => %d (%s)' % (response.status_code, response.text)) + if response.status != 200: + raise ValueError('status code != 200 => %d (%s)' % (response.status, (yield from (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, node +from . import network, blockchain, tx, wot, node, ud diff --git a/ucoinpy/api/bma/blockchain/__init__.py b/ucoinpy/api/bma/blockchain/__init__.py index f594d7f1b91aaaeb0717d6a2d77ca469478e275e..8edd830d857737fa4e104d9e4d7b9ed555efa9e9 100644 --- a/ucoinpy/api/bma/blockchain/__init__.py +++ b/ucoinpy/api/bma/blockchain/__init__.py @@ -30,7 +30,8 @@ class Parameters(Blockchain): """GET the blockchain parameters used by this node.""" def __get__(self, **kwargs): - return self.requests_get('/parameters', **kwargs).json() + r = yield from self.requests_get('/parameters', **kwargs) + return (yield from r.json()) class Membership(Blockchain): @@ -42,11 +43,13 @@ class Membership(Blockchain): def __post__(self, **kwargs): assert 'membership' in kwargs - return self.requests_post('/membership', **kwargs).json() + r = yield from self.requests_post('/membership', **kwargs) + return (yield from r.text()) def __get__(self, **kwargs): assert self.search is not None - return self.requests_get('/memberships/%s' % self.search, **kwargs).json() + r = yield from self.requests_get('/memberships/%s' % self.search, **kwargs) + return (yield from r.json()) class Block(Blockchain): @@ -66,20 +69,23 @@ class Block(Blockchain): def __get__(self, **kwargs): assert self.number is not None - return self.requests_get('/block/%d' % self.number, **kwargs).json() + r = yield from self.requests_get('/block/%d' % self.number, **kwargs) + return (yield from r.json()) def __post__(self, **kwargs): assert 'block' in kwargs assert 'signature' in kwargs - return self.requests_post('/block', **kwargs).json() + r = yield from self.requests_post('/block', **kwargs) + return (yield from r.text()) class Current(Blockchain): """GET, same as block/[number], but return last accepted block.""" def __get__(self, **kwargs): - return self.requests_get('/current', **kwargs).json() + r = yield from self.requests_get('/current', **kwargs) + return (yield from r.json()) class Hardship(Blockchain): @@ -99,60 +105,69 @@ class Hardship(Blockchain): def __get__(self, **kwargs): assert self.fingerprint is not None - return self.requests_get('/hardship/%s' % self.fingerprint.upper(), **kwargs).json() + r = yield from self.requests_get('/hardship/%s' % self.fingerprint.upper(), **kwargs) + return (yield from r.json()) class Newcomers(Blockchain): """GET, return block numbers containing newcomers.""" def __get__(self, **kwargs): - return self.requests_get('/with/newcomers', **kwargs).json() + r = yield from self.requests_get('/with/newcomers', **kwargs) + return (yield from r.json()) class Certifications(Blockchain): """GET, return block numbers containing certifications.""" def __get__(self, **kwargs): - return self.requests_get('/with/certs', **kwargs).json() + r = yield from self.requests_get('/with/certs', **kwargs) + return (yield from r.json()) class Joiners(Blockchain): """GET, return block numbers containing joiners.""" def __get__(self, **kwargs): - return self.requests_get('/with/joiners', **kwargs).json() + r = yield from self.requests_get('/with/joiners', **kwargs) + return (yield from r.json()) class Actives(Blockchain): """GET, return block numbers containing actives.""" def __get__(self, **kwargs): - return self.requests_get('/with/actives', **kwargs).json() + r = yield from self.requests_get('/with/actives', **kwargs) + return (yield from r.json()) class Leavers(Blockchain): """GET, return block numbers containing leavers.""" def __get__(self, **kwargs): - return self.requests_get('/with/leavers', **kwargs).json() + r = yield from self.requests_get('/with/leavers', **kwargs) + return (yield from r.json()) class Excluded(Blockchain): """GET, return block numbers containing excluded.""" def __get__(self, **kwargs): - return self.requests_get('/with/excluded', **kwargs).json() + r = yield from self.requests_get('/with/excluded', **kwargs) + return (yield from r.json()) class UD(Blockchain): """GET, return block numbers containing universal dividend.""" def __get__(self, **kwargs): - return self.requests_get('/with/ud', **kwargs).json() + r = yield from self.requests_get('/with/ud', **kwargs) + return (yield from r.json()) class TX(Blockchain): """GET, return block numbers containing transactions.""" def __get__(self, **kwargs): - return self.requests_get('/with/tx', **kwargs).json() + r = yield from self.requests_get('/with/tx', **kwargs) + return (yield from r.json()) diff --git a/ucoinpy/api/bma/network/__init__.py b/ucoinpy/api/bma/network/__init__.py index 3d6c73ec6eebd9d0f96f32c94457c0b4084e3685..860674c98ea6749d7593f2ff7da10dd6f0f6fff0 100644 --- a/ucoinpy/api/bma/network/__init__.py +++ b/ucoinpy/api/bma/network/__init__.py @@ -30,6 +30,7 @@ class Peering(Network): """GET peering information about a peer.""" def __get__(self, **kwargs): - return self.requests_get('/peering', **kwargs).json() + r = yield from self.requests_get('/peering', **kwargs) + return (yield from r.json()) from . import peering diff --git a/ucoinpy/api/bma/network/peering/__init__.py b/ucoinpy/api/bma/network/peering/__init__.py index 3ad7cde34997eed39cced842659f2af92b0fe37d..8150cec1ac6b6e8cb7245560fc8f0f0d664937f9 100644 --- a/ucoinpy/api/bma/network/peering/__init__.py +++ b/ucoinpy/api/bma/network/peering/__init__.py @@ -32,13 +32,15 @@ class Peers(Base): def __get__(self, **kwargs): """creates a generator with one peering entry per iteration.""" - return self.merkle_easy_parser('/peers') + r = yield from self.requests_get('/peers', **kwargs) + return (yield from r.json()) def __post__(self, **kwargs): assert 'entry' in kwargs assert 'signature' in kwargs - return self.requests_post('/peers', **kwargs).json() + r = yield from self.requests_post('/peers', **kwargs) + return (yield from r.json()) class Status(Base): @@ -48,4 +50,5 @@ class Status(Base): assert 'status' in kwargs assert 'signature' in kwargs - return self.requests_post('/status', **kwargs).json() + r = yield from self.requests_post('/status', **kwargs) + return (yield from r.json()) diff --git a/ucoinpy/api/bma/node/__init__.py b/ucoinpy/api/bma/node/__init__.py index fac217c619ff2a7a514c508df363aa05237f9402..f156578757aeb3056e404490a1629ce1c3659790 100644 --- a/ucoinpy/api/bma/node/__init__.py +++ b/ucoinpy/api/bma/node/__init__.py @@ -20,6 +20,7 @@ from .. import API, logging logger = logging.getLogger("ucoin/node") + class Node(API): def __init__(self, connection_handler, module='node'): super(Node, self).__init__(connection_handler, module) @@ -31,7 +32,7 @@ class Summary(Node): def __init__(self, connection_handler, module='node'): super(Summary, self).__init__(connection_handler, module) - def __get__(self, **kwargs): - return self.requests_get('/summary', **kwargs).json() + r = yield from self.requests_get('/summary', **kwargs) + return (yield from r.json()) diff --git a/ucoinpy/api/bma/tx/__init__.py b/ucoinpy/api/bma/tx/__init__.py index 0242efaec698c54a9f53307b5cd0931101477ec0..8199d2d8d49a56016424c14b30a653f7211b5f5b 100644 --- a/ucoinpy/api/bma/tx/__init__.py +++ b/ucoinpy/api/bma/tx/__init__.py @@ -26,13 +26,26 @@ class Tx(API): super(Tx, self).__init__(connection_handler, module) +class History(Tx): + """Get transaction sources.""" + def __init__(self, conn_handler, pubkey, module='tx'): + super(Tx, self).__init__(conn_handler, module) + self.pubkey = pubkey + + def __get__(self, **kwargs): + assert self.pubkey is not None + r = yield from self.requests_get('/history/%s' % self.pubkey, **kwargs) + return (yield from r.json()) + + class Process(Tx): """POST a transaction.""" def __post__(self, **kwargs): assert 'transaction' in kwargs - return self.requests_post('/process', **kwargs).json() + r = yield from self.requests_post('/process', **kwargs) + return (yield from r.text()) class Sources(Tx): @@ -43,4 +56,7 @@ class Sources(Tx): def __get__(self, **kwargs): assert self.pubkey is not None - return self.requests_get('/sources/%s' % self.pubkey, **kwargs).json() + r = yield from self.requests_get('/sources/%s' % self.pubkey, **kwargs) + return (yield from r.json()) + +from . import history \ No newline at end of file diff --git a/ucoinpy/api/bma/tx/history/__init__.py b/ucoinpy/api/bma/tx/history/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..b0e42968a817b6560c80602afca9587738640d00 --- /dev/null +++ b/ucoinpy/api/bma/tx/history/__init__.py @@ -0,0 +1,32 @@ +# +# 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 History, logging + +logger = logging.getLogger("ucoin/tx") + + +class Blocks(History): + def __init__(self, conn_handler, pubkey, from_, to_, module='tx'): + super(Blocks, self).__init__(conn_handler, pubkey, module) + self.from_ = from_ + self.to_ = to_ + + def __get__(self, **kwargs): + r = yield from self.requests_get('/history/%s/blocks/%s/%s' % (self.pubkey, self.from_, self.to_), **kwargs) + return (yield from r.json()) \ No newline at end of file diff --git a/ucoinpy/api/bma/ud/__init__.py b/ucoinpy/api/bma/ud/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..33f51b2ff52f9b1faaa1bf7ae2e718aec82783cf --- /dev/null +++ b/ucoinpy/api/bma/ud/__init__.py @@ -0,0 +1,39 @@ +# +# 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/ud") + + +class Ud(API): + def __init__(self, conn_handler, module='ud'): + super(Ud, self).__init__(conn_handler, module) + + +class History(Ud): + """Get UD history.""" + + def __init__(self, conn_handler, pubkey, module='ud'): + super(Ud, self).__init__(conn_handler, module) + self.pubkey = pubkey + + def __get__(self, **kwargs): + assert self.pubkey is not None + r = yield from self.requests_get('/history/%s' % self.pubkey, **kwargs) + return (yield from r.json()) diff --git a/ucoinpy/api/bma/wot/__init__.py b/ucoinpy/api/bma/wot/__init__.py index ea9b9a236959a0def6cc9e28daac73a1df6f1446..ca9c97bcab3433eda75a28fc17c4d3b8b5d8de05 100644 --- a/ucoinpy/api/bma/wot/__init__.py +++ b/ucoinpy/api/bma/wot/__init__.py @@ -34,7 +34,8 @@ class Add(WOT): assert 'self_' in kwargs assert 'other' in kwargs - return self.requests_post('/add', **kwargs).json() + r = yield from self.requests_post('/add', **kwargs) + return (yield from r.text()) class Revoke(WOT): @@ -44,7 +45,8 @@ class Revoke(WOT): assert 'pubkey' in kwargs assert 'self_' in kwargs - return self.requests_post('/revoke', **kwargs).json() + r = yield from self.requests_post('/revoke', **kwargs) + return (yield from r.text()) class Lookup(WOT): @@ -58,7 +60,8 @@ class Lookup(WOT): def __get__(self, **kwargs): assert self.search is not None - return self.requests_get('/lookup/%s' % self.search, **kwargs).json() + r = yield from self.requests_get('/lookup/%s' % self.search, **kwargs) + return (yield from r.json()) class CertifiersOf(WOT): @@ -72,7 +75,8 @@ class CertifiersOf(WOT): def __get__(self, **kwargs): assert self.search is not None - return self.requests_get('/certifiers-of/%s' % self.search, **kwargs).json() + r = yield from self.requests_get('/certifiers-of/%s' % self.search, **kwargs) + return (yield from r.json()) class CertifiedBy(WOT): @@ -86,7 +90,8 @@ class CertifiedBy(WOT): def __get__(self, **kwargs): assert self.search is not None - return self.requests_get('/certified-by/%s' % self.search, **kwargs).json() + r = yield from self.requests_get('/certified-by/%s' % self.search, **kwargs) + return (yield from r.json()) class Members(WOT): @@ -96,4 +101,5 @@ class Members(WOT): super(WOT, self).__init__(connection_handler, module) def __get__(self, **kwargs): - return self.requests_get('/members', **kwargs).json() + r = yield from self.requests_get('/members', **kwargs) + return (yield from r.json()) diff --git a/ucoinpy/documents/block.py b/ucoinpy/documents/block.py index a02a550dac8f71302bf3140503ceae7c98a40bd6..00ce0f779ce1fc9cef56a5f5b41ecabedf6bd2bd 100644 --- a/ucoinpy/documents/block.py +++ b/ucoinpy/documents/block.py @@ -77,6 +77,8 @@ BOTTOM_SIGNATURE re_certifications = re.compile("Certifications:\n") re_transactions = re.compile("Transactions:\n") + Empty_Hash = "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709" + def __init__(self, version, currency, noonce, number, powmin, time, mediantime, ud, issuer, prev_hash, prev_issuer, parameters, members_count, identities, joiners,