diff --git a/src/sakia/core/net/network.py b/src/sakia/core/net/network.py index 320bc435996883bd932202ba5d4c9aa4a79d362a..7cb64c1d9634f299ce7e55f7cdda65980040d0c4 100644 --- a/src/sakia/core/net/network.py +++ b/src/sakia/core/net/network.py @@ -255,18 +255,6 @@ class Network(QObject): self._nodes = unique_nodes - def fork_window(self, members_pubkeys): - """ - Get the medium of the fork window of the nodes members of a community - :return: the medium fork window of knew network - """ - fork_windows = [n.fork_window for n in self.online_nodes if n.software != "" - and n.pubkey in members_pubkeys] - if len(fork_windows) > 0: - return int(statistics.median(fork_windows)) - else: - return 0 - def confirmations(self, block_number): """ Get the number of confirmations of a data diff --git a/src/sakia/core/txhistory.py b/src/sakia/core/txhistory.py index 0b412accc0f6f1c73ea4d52a9e2029230e9a43f8..2a53a0047ee689f53fb88b9560065bbdbf7e016c 100644 --- a/src/sakia/core/txhistory.py +++ b/src/sakia/core/txhistory.py @@ -1,11 +1,12 @@ import asyncio import logging import hashlib -from .transfer import Transfer, TransferState -from ucoinpy.documents.transaction import InputSource, OutputSource +from ucoinpy.documents.transaction import InputSource from ucoinpy.documents.block import Block -from ..tools.exceptions import LookupFailureError, NoPeerAvailable from ucoinpy.api import bma +from .transfer import Transfer, TransferState +from .net.network import MAX_CONFIRMATIONS +from ..tools.exceptions import LookupFailureError, NoPeerAvailable class TxHistory(): @@ -241,13 +242,11 @@ class TxHistory(): logging.debug("Refresh from : {0} to {1}".format(block_number_from, block_to['number'])) dividends = await self.request_dividends(community, block_number_from) with_tx_data = await community.bma_access.future_request(bma.blockchain.TX) - members_pubkeys = await community.members_pubkeys() - fork_window = community.network.fork_window(members_pubkeys) blocks_with_tx = with_tx_data['result']['blocks'] while block_number_from <= block_to['number']: udid = 0 for d in [ud for ud in dividends if ud['block_number'] == block_number_from]: - state = TransferState.VALIDATED if block_number_from + fork_window <= block_to['number'] \ + state = TransferState.VALIDATED if block_number_from + MAX_CONFIRMATIONS <= block_to['number'] \ else TransferState.VALIDATING if d['block_number'] not in [ud['block_number'] for ud in self._dividends]: @@ -275,7 +274,7 @@ class TxHistory(): block_to['signature']) block_to = Block.from_signed_raw(signed_raw) for transfer in [t for t in self._transfers + new_transfers if t.state == TransferState.VALIDATING]: - transfer.run_state_transitions((False, block_to, fork_window)) + transfer.run_state_transitions((False, block_to, MAX_CONFIRMATIONS)) # We check if latest parsed block_number is a new high number if block_number_from > self.latest_block: @@ -337,11 +336,10 @@ class TxHistory(): current_block = await self._get_block_doc(community, community.network.current_blockid.number) members_pubkeys = await community.members_pubkeys() - fork_window = community.network.fork_window(members_pubkeys) # We check if transactions VALIDATED are in the fork window now for transfer in [t for t in self._transfers if t.state == TransferState.VALIDATED]: - transfer.run_state_transitions((True, current_block, fork_window)) + transfer.run_state_transitions((True, current_block, MAX_CONFIRMATIONS)) except NoPeerAvailable: logging.debug("No peer available") diff --git a/src/sakia/core/txhistory_indexation.py b/src/sakia/core/txhistory_indexation.py deleted file mode 100644 index aa3cd4a61ccff8cef3b7db524fda3d21bf93732b..0000000000000000000000000000000000000000 --- a/src/sakia/core/txhistory_indexation.py +++ /dev/null @@ -1,252 +0,0 @@ -import asyncio -import logging -from .transfer import Transfer -from ucoinpy.documents.transaction import InputSource, OutputSource -from ..tools.exceptions import LookupFailureError -from ucoinpy.api import bma - - -class TxHistory(): - def __init__(self, app, wallet): - self._latest_block = 0 - self.wallet = wallet - self.app = app - self._stop_coroutines = False - - self._transfers = [] - self.available_sources = [] - self._dividends = [] - - @property - def latest_block(self): - return self._latest_block - - @latest_block.setter - def latest_block(self, value): - self._latest_block = value - - def load_from_json(self, data): - self._transfers = [] - - data_sent = data['transfers'] - for s in data_sent: - self._transfers.append(Transfer.load(s)) - - for s in data['sources']: - self.available_sources.append(InputSource.from_inline(s['inline'])) - - for d in data['dividends']: - self._dividends.append(d) - - self.latest_block = data['latest_block'] - - def jsonify(self): - data_transfer = [] - for s in self.transfers: - data_transfer.append(s.jsonify()) - - data_sources = [] - for s in self.available_sources: - s.index = 0 - data_sources.append({'inline': "{0}\n".format(s.inline())}) - - data_dividends = [] - for d in self._dividends: - data_dividends.append(d) - - return {'latest_block': self.latest_block, - 'transfers': data_transfer, - 'sources': data_sources, - 'dividends': data_dividends} - - @property - def transfers(self): - return [t for t in self._transfers if t.state != Transfer.DROPPED] - - @property - def dividends(self): - return self._dividends.copy() - - def stop_coroutines(self): - self._stop_coroutines = True - - @staticmethod - async def _validation_state(community, block_number, current_block): - members_pubkeys = await community.members_pubkeys() - if block_number + community.network.fork_window(members_pubkeys) + 1 < current_block["number"]: - state = Transfer.VALIDATED - else: - state = Transfer.VALIDATING - return state - - async def _parse_transaction(self, community, txdata, received_list, txid, current_block): - tx_outputs = [OutputSource.from_inline(o) for o in txdata['outputs']] - receivers = [o.pubkey for o in tx_outputs - if o.pubkey != txdata['issuers'][0]] - - block_number = txdata['block_number'] - - mediantime = txdata['time'] - state = await TxHistory._validation_state(community, block_number, current_block) - - if len(receivers) == 0: - receivers = [txdata['issuers'][0]] - - try: - issuer = await self.wallet._identities_registry.future_find(txdata['issuers'][0], community) - issuer_uid = issuer.uid - except LookupFailureError: - issuer_uid = "" - - try: - receiver = await self.wallet._identities_registry.future_find(receivers[0], community) - receiver_uid = receiver.uid - except LookupFailureError: - receiver_uid = "" - - metadata = {'block': block_number, - 'time': mediantime, - 'comment': txdata['comment'], - 'issuer': txdata['issuers'][0], - 'issuer_uid': issuer_uid, - 'receiver': receivers[0], - 'receiver_uid': receiver_uid, - 'txid': txid} - - in_issuers = len([i for i in txdata['issuers'] - if i == self.wallet.pubkey]) > 0 - in_outputs = len([o for o in tx_outputs - if o.pubkey == self.wallet.pubkey]) > 0 - awaiting = [t for t in self._transfers - if t.state in (Transfer.AWAITING, Transfer.VALIDATING)] - - # We check if the transaction correspond to one we sent - # but not from this sakia Instance - if txdata['hash'] not in [t.hash for t in awaiting]: - # If the wallet pubkey is in the issuers we sent this transaction - if in_issuers: - outputs = [o for o in tx_outputs - if o.pubkey != self.wallet.pubkey] - amount = 0 - for o in outputs: - amount += o.amount - metadata['amount'] = amount - transfer = Transfer.create_from_blockchain(txdata['hash'], - state, - metadata.copy()) - return transfer - # If we are not in the issuers, - # maybe it we are in the recipients of this transaction - elif in_outputs: - outputs = [o for o in tx_outputs - if o.pubkey == self.wallet.pubkey] - amount = 0 - for o in outputs: - amount += o.amount - metadata['amount'] = amount - - if txdata['hash'] not in [t.hash for t in awaiting]: - transfer = Transfer.create_from_blockchain(txdata['hash'], - state, - metadata.copy()) - received_list.append(transfer) - return transfer - else: - transfer = [t for t in awaiting if t.hash == txdata['hash']][0] - transfer.check_registered(txdata['hash'], current_block['number'], mediantime, - community.network.fork_window(community.members_pubkeys()) + 1) - - async def refresh(self, community, received_list): - """ - Refresh last transactions - - :param sakia.core.Community community: The community - :param list received_list: List of transactions received - """ - current_block = await community.bma_access.future_request(bma.blockchain.Block, - req_args={'number': community.network.current_blockid.number}) - members_pubkeys = await community.members_pubkeys() - # We look for the first block to parse, depending on awaiting and validating transfers and ud... - blocks = [tx.metadata['block'] for tx in self._transfers - if tx.state in (Transfer.AWAITING, Transfer.VALIDATING)] +\ - [ud['block_number'] for ud in self._dividends - if ud['state'] in (Transfer.AWAITING, Transfer.VALIDATING)] +\ - [max(0, self.latest_block - community.network.fork_window(members_pubkeys))] - parsed_block = min(set(blocks)) - logging.debug("Refresh from : {0} to {1}".format(self.latest_block, current_block['number'])) - dividends_data = bma.ud.History.null_value - for i in range(0, 6): - if dividends_data == bma.ud.History.null_value: - dividends_data = await community.bma_access.future_request(bma.ud.History, - req_args={'pubkey': self.wallet.pubkey}) - - dividends = dividends_data['history']['history'] - for d in dividends: - if d['block_number'] < parsed_block: - dividends.remove(d) - - new_transfers = [] - new_dividends = [] - # Lets look if transactions took too long to be validated - awaiting = [t for t in self._transfers - if t.state == Transfer.AWAITING] - while parsed_block < current_block['number']: - udid = 0 - for d in [ud for ud in dividends if ud['block_number'] in range(parsed_block, parsed_block+100)]: - state = await TxHistory._validation_state(community, d['block_number'], current_block) - - if d['block_number'] not in [ud['block_number'] for ud in self._dividends]: - d['id'] = udid - d['state'] = state - new_dividends.append(d) - udid += 1 - else: - known_dividend = [ud for ud in self._dividends - if ud['block_number'] == d['block_number']][0] - known_dividend['state'] = state - - tx_history = bma.tx.history.Blocks.null_value - for i in range(0, 6): - if tx_history == bma.tx.history.Blocks.null_value: - tx_history = await community.bma_access.future_request(bma.tx.history.Blocks, - req_args={'pubkey': self.wallet.pubkey, - 'from_':str(parsed_block), - 'to_': str(parsed_block + 99)}) - # If after 6 requests we still get wrong data - # we continue to next loop - if tx_history == bma.tx.history.Blocks.null_value: - continue - - # We parse only blocks with transactions - transactions = tx_history['history']['received'] + tx_history['history']['sent'] - for (txid, txdata) in enumerate(transactions): - if self._stop_coroutines: - return - if len(txdata['issuers']) == 0: - logging.debug("Error with : {0}, from {1} to {2}".format(self.wallet.pubkey, - parsed_block, - current_block['number'])) - else: - transfer = await self._parse_transaction(community, txdata, received_list, - udid + txid, current_block) - if transfer: - new_transfers.append(transfer) - - self.wallet.refresh_progressed.emit(parsed_block, current_block['number'], self.wallet.pubkey) - parsed_block += 100 - - if current_block['number'] > self.latest_block: - self.available_sources = await self.wallet.sources(community) - if self._stop_coroutines: - return - self.latest_block = current_block['number'] - - for transfer in awaiting: - transfer.check_refused(current_block['medianTime'], - community.parameters['avgGenTime'], - community.parameters['medianTimeBlocks']) - - self._transfers = self._transfers + new_transfers - self._dividends = self._dividends + new_dividends - - self.wallet.refresh_finished.emit(received_list) diff --git a/src/sakia/gui/community_view.py b/src/sakia/gui/community_view.py index 37810b88f2e981790a5ded9c850325d7f96f48b0..c977d615aacf1293ec865b96ca9b0575eaf6445d 100644 --- a/src/sakia/gui/community_view.py +++ b/src/sakia/gui/community_view.py @@ -266,16 +266,6 @@ class CommunityWidget(QWidget, Ui_CommunityWidget): if status_infotext != "": label_text += " - {0}".format(status_infotext) - if self.app.preferences['expert_mode']: - try: - members_pubkeys = await self.community.members_pubkeys() - label_text += self.tr(" - Median fork window : {0}")\ - .format(self.community.network.fork_window(members_pubkeys)) - except NoPeerAvailable as e: - logging.debug(str(e)) - label_text += self.tr(" - Median fork window : {0}")\ - .format("#") - self.status_label.setText(label_text) self.label_icon.setPixmap(QPixmap(icon).scaled(24, 24, Qt.KeepAspectRatio, Qt.SmoothTransformation)) diff --git a/src/sakia/models/txhistory.py b/src/sakia/models/txhistory.py index 5bea986af16723e039923a3fcc852c568e6a993a..a463b6af36634251ba82e88ad58df11cb988328e 100644 --- a/src/sakia/models/txhistory.py +++ b/src/sakia/models/txhistory.py @@ -8,6 +8,7 @@ import datetime import logging import asyncio from ..core.transfer import Transfer, TransferState +from ..core.net.network import MAX_CONFIRMATIONS from ..tools.exceptions import NoPeerAvailable from ..tools.decorators import asyncify, once_at_a_time, cancel_once_task from PyQt5.QtCore import QAbstractTableModel, Qt, QVariant, QSortFilterProxyModel, \ @@ -187,7 +188,6 @@ class HistoryTableModel(QAbstractTableModel): self.community = community self.transfers_data = [] self.refresh_transfers() - self._max_confirmations = 0 self.columns_types = ( 'date', @@ -311,17 +311,11 @@ class HistoryTableModel(QAbstractTableModel): data = await self.data_dividend(transfer) if data: transfers_data.append(data) - try: - members_pubkeys = await self.community.members_pubkeys() - self._max_confirmations = self.community.network.fork_window(members_pubkeys) + 1 - except NoPeerAvailable as e: - logging.debug(str(e)) - self._max_confirmations = 0 self.transfers_data = transfers_data self.endResetModel() def max_confirmations(self): - return self._max_confirmations + return MAX_CONFIRMATIONS def rowCount(self, parent): return len(self.transfers_data)