Skip to content
Snippets Groups Projects
Commit 2777208d authored by inso's avatar inso
Browse files

Detect blockchain rollback

parent 21219463
No related branches found
No related tags found
No related merge requests found
......@@ -12,7 +12,7 @@ import asyncio
from ucoinpy.documents.peer import Peer
from ucoinpy.documents.block import Block
from ucoinpy.api import bma
from ...tools.decorators import asyncify
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QTimer
from collections import Counter
......@@ -25,6 +25,7 @@ class Network(QObject):
"""
nodes_changed = pyqtSignal()
new_block_mined = pyqtSignal(int)
blockchain_rollback = pyqtSignal(int)
def __init__(self, currency, nodes):
"""
......@@ -40,7 +41,7 @@ class Network(QObject):
self.add_node(n)
self.currency = currency
self._must_crawl = False
self._block_found = self.latest_block_hash
self._refresh_block_found()
self._timer = QTimer()
@classmethod
......@@ -189,6 +190,10 @@ class Network(QObject):
else:
return Block.Empty_Hash
def _refresh_block_found(self):
self._block_found = {'hash': self.latest_block_hash,
'number': self.latest_block_number}
def check_nodes_sync(self):
"""
Check nodes sync with the following rules :
......@@ -334,10 +339,19 @@ class Network(QObject):
self.nodes.remove(node)
self.nodes_changed.emit()
logging.debug("{0} -> {1}".format(self._block_found[:10], self.latest_block_hash[:10]))
if self._block_found != self.latest_block_hash and node.state == Node.ONLINE:
logging.debug("Latest block changed : {0}".format(self.latest_block_number))
self._block_found = self.latest_block_hash
# Do not emit block change for empty block
self.new_block_mined.emit(self.latest_block_number)
if node.state == Node.ONLINE:
logging.debug("{0} -> {1}".format(self._block_found['hash'][:10], self.latest_block_hash[:10]))
if self._block_found['hash'] != self.latest_block_hash:
logging.debug("Latest block changed : {0}".format(self.latest_block_number))
# If new latest block is lower than the previously found one
# or if the previously found block is different locally
# than in the main chain, we declare a rollback
if self._block_found['number'] and \
self.latest_block_number <= self._block_found['number'] \
or node.main_chain_previous_block and \
node.main_chain_previous_block['hash'] != self._block_found['hash']:
self._refresh_block_found()
self.blockchain_rollback.emit(self.latest_block_number)
else:
self._refresh_block_found()
self.new_block_mined.emit(self.latest_block_number)
......@@ -5,7 +5,6 @@ Created on 21 févr. 2015
"""
from ucoinpy.documents.peer import Peer, Endpoint, BMAEndpoint
from ucoinpy.documents.block import Block
from ...tools.exceptions import InvalidNodeCurrency
from ...tools.decorators import asyncify
from ucoinpy.api import bma as bma
......@@ -49,6 +48,7 @@ class Node(QObject):
self._uid = uid
self._pubkey = pubkey
self._block = block
self.main_chain_previous_block = None
self._state = state
self._neighbours = []
self._currency = currency
......@@ -295,12 +295,29 @@ class Node(QObject):
self.state = Node.ONLINE
if not self.block or block_hash != self.block['hash']:
self.set_block(block_data)
logging.debug("Changed block {0} -> {1}".format(self.block['number'],
block_data['number']))
self.changed.emit()
try:
#TODO: Check previous block
self.main_chain_previous_block = yield from bma.blockchain.Block(conn_handler,
self.block['number']).get()
except ValueError as e:
if '404' in str(e):
self.main_chain_previous_block = None
logging.debug("Error in block reply")
self.changed.emit()
except ClientError:
logging.debug("Client error : {0}".format(self.pubkey))
self.state = Node.OFFLINE
except asyncio.TimeoutError:
logging.debug("Timeout error : {0}".format(self.pubkey))
self.state = Node.OFFLINE
finally:
self.set_block(block_data)
logging.debug("Changed block {0} -> {1}".format(self.block['number'],
block_data['number']))
self.changed.emit()
except ValueError as e:
if '404' in str(e):
self.main_chain_previous_block = None
self.set_block(None)
logging.debug("Error in block reply")
self.changed.emit()
......
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