Skip to content
Snippets Groups Projects
Commit 5c5f1bba authored by inso's avatar inso
Browse files

Implement data validation

parent 7b7eafe3
No related branches found
No related tags found
No related merge requests found
doc/uml/api.png

13.8 KiB | W: | H:

doc/uml/api.png

14 KiB | W: | H:

doc/uml/api.png
doc/uml/api.png
doc/uml/api.png
doc/uml/api.png
  • 2-up
  • Swipe
  • Onion skin
doc/uml/core-classes.png

55.5 KiB | W: | H:

doc/uml/core-classes.png

55.2 KiB | W: | H:

doc/uml/core-classes.png
doc/uml/core-classes.png
doc/uml/core-classes.png
doc/uml/core-classes.png
  • 2-up
  • Swipe
  • Onion skin
doc/uml/cutecoin.png

261 KiB | W: | H:

doc/uml/cutecoin.png

261 KiB | W: | H:

doc/uml/cutecoin.png
doc/uml/cutecoin.png
doc/uml/cutecoin.png
doc/uml/cutecoin.png
  • 2-up
  • Swipe
  • Onion skin
doc/uml/gui-classes.png

38.8 KiB | W: | H:

doc/uml/gui-classes.png

38.8 KiB | W: | H:

doc/uml/gui-classes.png
doc/uml/gui-classes.png
doc/uml/gui-classes.png
doc/uml/gui-classes.png
  • 2-up
  • Swipe
  • Onion skin
doc/uml/models-classes.png

14.8 KiB | W: | H:

doc/uml/models-classes.png

14.8 KiB | W: | H:

doc/uml/models-classes.png
doc/uml/models-classes.png
doc/uml/models-classes.png
doc/uml/models-classes.png
  • 2-up
  • Swipe
  • Onion skin
doc/uml/network.png

45.7 KiB | W: | H:

doc/uml/network.png

23 KiB | W: | H:

doc/uml/network.png
doc/uml/network.png
doc/uml/network.png
doc/uml/network.png
  • 2-up
  • Swipe
  • Onion skin
...@@ -3,29 +3,13 @@ ...@@ -3,29 +3,13 @@
Network -->o Node : Connect to node_received() Network -->o Node : Connect to node_received()
Network -> Node : Starts network discovery Network -> Node : Starts network discovery
activate Node activate Node
Node -> QNetworkManager : HTTP GET peering/peers?leaves=true Node -> ucoinpy : HTTP GET peering/peers?leaves=true
create QNetworkReply
QNetworkManager -> QNetworkReply : Instantiate
Node <- QNetworkManager : QNetworkReply
Node -->o QNetworkReply : Connect to finished()
Network <- Node
deactivate Node
... Request is processed ...
Node <-- QNetworkReply : finished()
destroy QNetworkReply
alt "root" hash changed alt "root" hash changed
loop "for all leaves changed" loop "for all leaves changed"
activate Node activate Node
Node -> QNetworkManager : HTTP GET peering/peers/leaf=leaf_hash Node -> ucoinpy : HTTP GET peering/peers/leaf=leaf_hash
create QNetworkReply
QNetworkManager -> QNetworkReply : Instantiate
Node <- QNetworkManager : QNetworkReply
Node -->o QNetworkReply : Connect to finished()
end end
end end
... Requests is processed ...
Node <-- QNetworkReply : finished()
destroy QNetworkReply
Network <-- Node : node_received() Network <-- Node : node_received()
ref over Network ref over Network
New node is instanciated New node is instanciated
......
doc/uml/requests.png

57.4 KiB | W: | H:

doc/uml/requests.png

28.4 KiB | W: | H:

doc/uml/requests.png
doc/uml/requests.png
doc/uml/requests.png
doc/uml/requests.png
  • 2-up
  • Swipe
  • Onion skin
@startuml @startuml
QModel -->o "Core Component" : Connect to data_changed()
QModel -> "Core Component" : Data access
activate "Core Component" activate "Core Component"
"Core Component" -> Community : Request data "Core Component" -> BmaAccess : Request data
Community -> Cache : Request cache BmaAccess -> BmaAccess : Request cache
ref over Cache ref over BmaAccess
Data is obsolete Data is obsolete
(new block mined (new block mined
since last caching) since last caching)
end ref end ref
Cache -> QNetworkManager : HTTP GET BmaAccess -> ucoinpy : HTTP GET
create QNetworkReply alt Rollback
QNetworkManager -> QNetworkReply : Instantiate BmaAccess -> BmaAccess : Find last block number rollbacked
Cache <- QNetworkManager : QNetworkReply ref over BmaAccess
create ReceiverSlot If the request is a bma/blockchain/Block, we check if the hash answered is the same
Cache -> ReceiverSlot : Instantiate Slot as our hash, in which case, we know that the rollback didn't reset blocks before
QNetworkReply o<-- ReceiverSlot : Connect to finished() this one.
Community <- Cache : Cached data Blocks from this one to the current block are considered obsolete
"Core Component" <- Community : Cached data
"Core Component" -> "Core Component" : Compute data
QModel <- "Core Component" : Data
deactivate "Core Component"
...Network request is processed...
ReceiverSlot <-- QNetworkReply : finished()
activate ReceiverSlot
ReceiverSlot -> Cache : Update cache data
ReceiverSlot -> "Core Component" : emit data_changed()
deactivate ReceiverSlot
destroy ReceiverSlot
destroy QNetworkReply
|||
QModel <-- "Core Component" : data_changed()
QModel -> "Core Component" : Data access
activate "Core Component"
ref over "Core Component", Community
Community is requested again,
and last cached data are returned
No new block mined, so no HTTP GET
initialized between cache
and QNetworkManager
end ref end ref
QModel <- "Core Component" : Data end
BmaAccess -> BmaAccess : Update cache data
"Core Component" <- BmaAccess : Return data data
deactivate "Core Component" deactivate "Core Component"
......
doc/uml/tx_lifecycle.png

65.7 KiB | W: | H:

doc/uml/tx_lifecycle.png

65.7 KiB | W: | H:

doc/uml/tx_lifecycle.png
doc/uml/tx_lifecycle.png
doc/uml/tx_lifecycle.png
doc/uml/tx_lifecycle.png
  • 2-up
  • Swipe
  • Onion skin
from PyQt5.QtCore import QObject, pyqtSlot from PyQt5.QtCore import QObject, pyqtSlot
from PyQt5.QtNetwork import QNetworkReply from PyQt5.QtNetwork import QNetworkReply
from ucoinpy.api import bma from ucoinpy.api import bma
from ucoinpy.documents import Block, BlockId
from .....tools.exceptions import NoPeerAvailable from .....tools.exceptions import NoPeerAvailable
from ..... import __version__ from ..... import __version__
import logging import logging
from aiohttp.errors import ClientError from aiohttp.errors import ClientError
import asyncio import asyncio
import random import random
import jsonschema
from distutils.version import StrictVersion from distutils.version import StrictVersion
...@@ -136,6 +136,10 @@ class BmaAccess(QObject): ...@@ -136,6 +136,10 @@ class BmaAccess(QObject):
def _update_rollback(self, request, req_args, get_args, data): def _update_rollback(self, request, req_args, get_args, data):
""" """
Update the rollback Update the rollback
If the request is a bma/blockchain/Block, we check if
the hash answered is the same as our hash, in which case,
we know that the rollback didn't reset blocks before this one
:param class request: A bma request class calling for data :param class request: A bma request class calling for data
:param dict req_args: Arguments to pass to the request constructor :param dict req_args: Arguments to pass to the request constructor
:param dict get_args: Arguments to pass to the request __get__ method :param dict get_args: Arguments to pass to the request __get__ method
...@@ -240,6 +244,9 @@ class BmaAccess(QObject): ...@@ -240,6 +244,9 @@ class BmaAccess(QObject):
tries += 1 tries += 1
except asyncio.TimeoutError: except asyncio.TimeoutError:
tries += 1 tries += 1
except jsonschema.ValidationError as e:
logging.debug(str(e))
tries += 1
if len(nodes) == 0 or json_data is None: if len(nodes) == 0 or json_data is None:
raise NoPeerAvailable("", len(nodes)) raise NoPeerAvailable("", len(nodes))
return json_data return json_data
...@@ -271,6 +278,9 @@ class BmaAccess(QObject): ...@@ -271,6 +278,9 @@ class BmaAccess(QObject):
tries += 1 tries += 1
except asyncio.TimeoutError: except asyncio.TimeoutError:
tries += 1 tries += 1
except jsonschema.ValidationError as e:
logging.debug(str(e))
tries += 1
else: else:
raise NoPeerAvailable("", len(nodes)) raise NoPeerAvailable("", len(nodes))
......
...@@ -14,10 +14,9 @@ import asyncio ...@@ -14,10 +14,9 @@ import asyncio
from aiohttp.errors import ClientError from aiohttp.errors import ClientError
import logging import logging
import time import time
import json import jsonschema
from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot from PyQt5.QtCore import QObject, pyqtSignal
from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest
class Node(QObject): class Node(QObject):
...@@ -321,6 +320,9 @@ class Node(QObject): ...@@ -321,6 +320,9 @@ class Node(QObject):
except asyncio.TimeoutError: except asyncio.TimeoutError:
logging.debug("Timeout error : {0}".format(self.pubkey)) logging.debug("Timeout error : {0}".format(self.pubkey))
self.state = Node.OFFLINE self.state = Node.OFFLINE
except jsonschema.ValidationError:
logging.debug("Validation error : {0}".format(self.pubkey))
self.state = Node.CORRUPTED
finally: finally:
self.set_block(block_data) self.set_block(block_data)
logging.debug("Changed block {0} -> {1}".format(self.block['number'], logging.debug("Changed block {0} -> {1}".format(self.block['number'],
...@@ -373,6 +375,9 @@ class Node(QObject): ...@@ -373,6 +375,9 @@ class Node(QObject):
except asyncio.TimeoutError: except asyncio.TimeoutError:
logging.debug("Timeout error : {0}".format(self.pubkey)) logging.debug("Timeout error : {0}".format(self.pubkey))
self.state = Node.OFFLINE self.state = Node.OFFLINE
except jsonschema.ValidationError:
logging.debug("Validation error : {0}".format(self.pubkey))
self.state = Node.CORRUPTED
@asyncify @asyncify
@asyncio.coroutine @asyncio.coroutine
...@@ -400,6 +405,9 @@ class Node(QObject): ...@@ -400,6 +405,9 @@ class Node(QObject):
except asyncio.TimeoutError: except asyncio.TimeoutError:
logging.debug("Timeout error : {0}".format(self.pubkey)) logging.debug("Timeout error : {0}".format(self.pubkey))
self.state = Node.OFFLINE self.state = Node.OFFLINE
except jsonschema.ValidationError:
logging.debug("Validation error : {0}".format(self.pubkey))
self.state = Node.CORRUPTED
@asyncify @asyncify
@asyncio.coroutine @asyncio.coroutine
...@@ -435,6 +443,9 @@ class Node(QObject): ...@@ -435,6 +443,9 @@ class Node(QObject):
except asyncio.TimeoutError: except asyncio.TimeoutError:
logging.debug("Timeout error : {0}".format(self.pubkey)) logging.debug("Timeout error : {0}".format(self.pubkey))
self.state = Node.OFFLINE self.state = Node.OFFLINE
except jsonschema.ValidationError:
logging.debug("Validation error : {0}".format(self.pubkey))
self.state = Node.CORRUPTED
@asyncify @asyncify
@asyncio.coroutine @asyncio.coroutine
...@@ -469,6 +480,9 @@ class Node(QObject): ...@@ -469,6 +480,9 @@ class Node(QObject):
except asyncio.TimeoutError: except asyncio.TimeoutError:
logging.debug("Timeout error : {0}".format(self.pubkey)) logging.debug("Timeout error : {0}".format(self.pubkey))
self.state = Node.OFFLINE self.state = Node.OFFLINE
except jsonschema.ValidationError:
logging.debug("Validation error : {0}".format(self.pubkey))
self.state = Node.CORRUPTED
self._last_merkle = {'root' : peers_data['root'], self._last_merkle = {'root' : peers_data['root'],
'leaves': peers_data['leaves']} 'leaves': peers_data['leaves']}
except ValueError as e: except ValueError as e:
...@@ -480,6 +494,9 @@ class Node(QObject): ...@@ -480,6 +494,9 @@ class Node(QObject):
except asyncio.TimeoutError: except asyncio.TimeoutError:
logging.debug("Timeout error : {0}".format(self.pubkey)) logging.debug("Timeout error : {0}".format(self.pubkey))
self.state = Node.OFFLINE self.state = Node.OFFLINE
except jsonschema.ValidationError:
logging.debug("Validation error : {0}".format(self.pubkey))
self.state = Node.CORRUPTED
def __str__(self): def __str__(self):
return ','.join([str(self.pubkey), str(self.endpoint.server), return ','.join([str(self.pubkey), str(self.endpoint.server),
......
...@@ -197,8 +197,6 @@ class Identity(QObject): ...@@ -197,8 +197,6 @@ class Identity(QObject):
except NoPeerAvailable as e: except NoPeerAvailable as e:
logging.debug(str(e)) logging.debug(str(e))
raise MembershipNotFoundError(self.pubkey, community.name) raise MembershipNotFoundError(self.pubkey, community.name)
except UnboundLocalError:
raise
@asyncio.coroutine @asyncio.coroutine
def published_uid(self, community): def published_uid(self, community):
......
...@@ -5,6 +5,7 @@ Created on 2 févr. 2014 ...@@ -5,6 +5,7 @@ Created on 2 févr. 2014
""" """
import asyncio import asyncio
import logging
from PyQt5.QtCore import Qt, pyqtSignal, QEvent from PyQt5.QtCore import Qt, pyqtSignal, QEvent
from PyQt5.QtGui import QCursor from PyQt5.QtGui import QCursor
...@@ -186,15 +187,19 @@ class IdentitiesTabWidget(QWidget, Ui_IdentitiesTab): ...@@ -186,15 +187,19 @@ class IdentitiesTabWidget(QWidget, Ui_IdentitiesTab):
text = self.edit_textsearch.text() text = self.edit_textsearch.text()
if len(text) < 2: if len(text) < 2:
return return
response = yield from self.community.bma_access.future_request(bma.wot.Lookup, {'search': text}) try:
identities = [] response = yield from self.community.bma_access.future_request(bma.wot.Lookup, {'search': text})
for identity_data in response['results']: identities = []
identity = yield from self.app.identities_registry.future_find(identity_data['pubkey'], self.community) for identity_data in response['results']:
identities.append(identity) identity = yield from self.app.identities_registry.future_find(identity_data['pubkey'], self.community)
identities.append(identity)
self.edit_textsearch.clear()
yield from self.refresh_identities(identities) self.edit_textsearch.clear()
self.busy.hide() yield from self.refresh_identities(identities)
except ValueError as e:
logging.debug(str(e))
finally:
self.busy.hide()
@once_at_a_time @once_at_a_time
@asyncify @asyncify
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment