Skip to content
Snippets Groups Projects
Commit 456dc408 authored by inso's avatar inso
Browse files

Handle rollbacks with new table states

parent 1d8718ed
No related branches found
No related tags found
No related merge requests found
......@@ -75,7 +75,7 @@ class Transfer(QObject):
(TransferState.AWAITING, (bool, Block)):
(self._found_in_block, self._be_validating, TransferState.VALIDATING),
(TransferState.AWAITING, (bool, Block, int)):
(TransferState.AWAITING, (bool, Block, int, int)):
(self._not_found_in_blockchain, None, TransferState.REFUSED),
(TransferState.VALIDATING, (bool, Block, int)):
......@@ -146,12 +146,13 @@ class Transfer(QObject):
"""
return self._metadata
def _not_found_in_blockchain(self, rollback, block, mediantime_target):
def _not_found_in_blockchain(self, rollback, block, mediantime_target, mediantime_blocks):
"""
Check if the transaction could not be found in the blockchain
:param bool rollback: True if we are in a rollback procedure
:param ucoinpy.documents.Block block: The block to look for the tx
:param int mediantime_target: The mediantime to mine a block in the community parameters
:param int mediantime_blocks: The number of block used to derive the mediantime
:return: True if the transaction could not be found in a given time
:rtype: bool
"""
......@@ -159,7 +160,7 @@ class Transfer(QObject):
for tx in block.transactions:
if tx.hash == self.sha_hash:
return False
if block.time > self.metadata['time'] + mediantime_target*10:
if block.time > self.metadata['time'] + mediantime_target*mediantime_blocks:
return True
return False
......@@ -205,8 +206,11 @@ class Transfer(QObject):
:param ucoinpy.documents.Block block: The block to check for the transaction
:return: True if the transfer is not found in the block
"""
if rollback and block.blockid == self.blockid:
return self.sha_hash not in [t.hash for t in block.transactions]
if rollback:
if not block or block.blockid != self.blockid:
return True
else:
return self.sha_hash not in [t.hash for t in block.transactions]
return False
def _rollback_still_present(self, rollback, block):
......
......@@ -231,6 +231,8 @@ class TxHistory():
:param cutecoin.core.Community community: The community
:param list received_list: List of transactions received
"""
new_transfers = []
new_dividends = []
try:
logging.debug("Refresh from : {0} to {1}".format(block_number_from, self._block_to['number']))
dividends = yield from self.request_dividends(community, block_number_from)
......@@ -238,11 +240,6 @@ class TxHistory():
members_pubkeys = yield from community.members_pubkeys()
fork_window = community.network.fork_window(members_pubkeys)
blocks_with_tx = with_tx_data['result']['blocks']
new_transfers = []
new_dividends = []
# Lets look if transactions took too long to be validated
awaiting = [t for t in self._transfers
if t.state == TransferState.AWAITING]
while block_number_from <= self._block_to['number']:
udid = 0
for d in [ud for ud in dividends if ud['block_number'] == block_number_from]:
......@@ -284,10 +281,9 @@ class TxHistory():
self.latest_block = block_number_from
parameters = yield from community.parameters()
for transfer in awaiting:
transfer.check_refused(self._block_to['medianTime'],
parameters['avgGenTime'],
parameters['medianTimeBlocks'])
for transfer in [t for t in self._transfers if t.state == TransferState.AWAITING]:
transfer.run_state_transitions((False, self._block_to,
parameters['avgGenTime'], parameters['medianTimeBlocks']))
except NoPeerAvailable as e:
logging.debug(str(e))
self.wallet.refresh_finished.emit([])
......@@ -298,6 +294,57 @@ class TxHistory():
self.wallet.refresh_finished.emit(received_list)
@asyncio.coroutine
def _check_block(self, block_number, community):
"""
Parse a block
:param cutecoin.core.Community community: The community
:param cutecoin.core.Transfer transfer: The transfer to check the presence
"""
block = None
block_doc = None
tries = 0
while block is None and tries < 3:
try:
block = yield from community.bma_access.future_request(bma.blockchain.Block,
req_args={'number': block_number})
signed_raw = "{0}{1}\n".format(block['raw'],
block['signature'])
try:
block_doc = Block.from_signed_raw(signed_raw)
except TypeError:
logging.debug("Error in {0}".format(block_number))
block = None
tries += 1
except ValueError as e:
if '404' in str(e):
block = None
tries += 1
for transfer in [t for t in self._transfers
if t.state in (TransferState.VALIDATING, TransferState.VALIDATED)]:
return not transfer.run_state_transitions((True, block_doc))
@asyncio.coroutine
def _rollback(self, community):
"""
Rollback last transactions until we find one still present
in the main blockchain
:param cutecoin.core.Community community: The community
"""
try:
logging.debug("Rollback from : {0}".format(self._block_to['number']))
# We look for the block goal to check for rollback,
# depending on validating and validated transfers...
tx_blocks = [tx.blockid.number for tx in self._transfers
if tx.state in (TransferState.VALIDATED, TransferState.VALIDATING) \
and tx.blockid is not None]
for block_number in tx_blocks:
if (yield from self._check_block(community, block_number)):
return
except NoPeerAvailable:
logging.debug("No peer available")
@asyncio.coroutine
def refresh(self, community, received_list):
# We update the block goal
......@@ -331,4 +378,4 @@ class TxHistory():
except ValueError as e:
logging.debug("Block not found")
except NoPeerAvailable:
logging.debug("No peer available")
\ No newline at end of file
logging.debug("No peer available")
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