diff --git a/src/sakia/core/community.py b/src/sakia/core/community.py
deleted file mode 100644
index cb640069c0b07166b999beb2347d9ea5cefc54d7..0000000000000000000000000000000000000000
--- a/src/sakia/core/community.py
+++ /dev/null
@@ -1,343 +0,0 @@
-"""
-Created on 1 févr. 2014
-
-@author: inso
-"""
-
-import logging
-import re
-import math
-
-from PyQt5.QtCore import QObject
-
-from sakia.errors import NoPeerAvailable
-from sakia.data.processors import NodesProcessor
-from duniterpy.api import bma, errors
-from sakia.data.connectors import BmaConnector
-
-
-class Community(QObject):
-    """
-    A community is a group of nodes using the same currency.
-
-    .. warning:: The currency name is supposed to be unique in sakia
-    but nothing exists in duniter to assert that a currency name is unique.
-    """
-    def __init__(self, currency, nodes_processor, bma_connector):
-        """
-        Initialize community attributes with a currency and a network.
-
-        :param str currency: The currency name of the community.
-        :param sakia.data.processors.NodesProcessor nodes_processor: The network of the community
-        :param sakia.data.connectors.BmaConnector bma_connector: The BMA connector object
-
-        .. warning:: The community object should be created using its factory
-        class methods.
-        """
-        super().__init__()
-        self.currency = currency
-        self._nodes_processor = nodes_processor
-        self._bma_connector = bma_connector
-
-    @classmethod
-    def create(cls, node):
-        """
-        Create a community from its first node.
-
-        :param node: The first Node of the community
-        """
-        network = Network.create(node)
-        bma_access = BmaAccess.create(network)
-        community = cls(node.currency, network, bma_access)
-        logging.debug("Creating community")
-        return community
-
-    @classmethod
-    def load(cls, json_data, file_version):
-        """
-        Load a community from json
-
-        :param dict json_data: The community as a dict in json format
-        :param NormalizedVersion file_version: the file sakia version
-        """
-        currency = json_data['currency']
-        network = Network.from_json(currency, json_data['peers'], file_version)
-        bma_access = BmaAccess.create(network)
-        community = cls(currency, network, bma_access)
-        return community
-
-    @property
-    def name(self):
-        """
-        The community name is its currency name.
-
-        :return: The community name
-        """
-        return self.currency
-
-    @property
-    def short_currency(self):
-        """
-        Format the currency name to a short one
-
-        :return: The currency name in a shot format.
-        """
-        words = re.split('[_\W]+', self.currency)
-        shortened = ""
-        if len(words) > 1:
-            shortened = ''.join([w[0] for w in words])
-        else:
-            vowels = ('a', 'e', 'i', 'o', 'u', 'y')
-            shortened = self.currency
-            shortened = ''.join([c for c in shortened if c not in vowels])
-        return shortened.upper()
-
-    @property
-    def currency_symbol(self):
-        """
-        Format the currency name to a symbol one.
-
-        :return: The currency name as a utf-8 circled symbol.
-        """
-        letter = self.currency[0]
-        u = ord('\u24B6') + ord(letter) - ord('A')
-        return chr(u)
-
-    async def dividend(self, block_number=None):
-        """
-        Get the last generated community universal dividend before block_number.
-        If block_number is None, returns the last block_number.
-
-        :param int block_number: The block at which we get the latest dividend
-
-        :return: The last UD or 1 if no UD was generated.
-        """
-        block = await self.get_ud_block(block_number=block_number)
-        if block:
-            return block['dividend'] * math.pow(10, block['unitbase'])
-        else:
-            return 1
-
-    async def computed_dividend(self):
-        """
-        Get the computed community universal dividend.
-
-        Calculation based on t = last UD block time and on values from the that block :
-
-        UD(computed) = CEIL(MAX(UD(t) ; c * M(t) / N(t)))
-
-        :return: The computed UD or 1 if no UD was generated.
-        """
-        block = await self.get_ud_block()
-        if block:
-            parameters = await self.parameters()
-            return math.ceil(
-                max(
-                    (await self.dividend()),
-                    float(0) if block['membersCount'] == 0 else
-                    parameters['c'] * block['monetaryMass'] / block['membersCount']
-                )
-            )
-
-        else:
-            return 1
-
-    async def get_ud_block(self, x=0, block_number=None):
-        """
-        Get a block with universal dividend
-        If x and block_number are passed to the result,
-        it returns the 'x' older block with UD in it BEFORE block_number
-
-        :param int x: Get the 'x' older block with UD in it
-        :param int block_number: Get the latest dividend before this block number
-        :return: The last block with universal dividend.
-        :rtype: dict
-        """
-        try:
-            udblocks = await self.bma_access.future_request(bma.blockchain.UD)
-            blocks = udblocks['result']['blocks']
-            if block_number:
-                blocks = [b for b in blocks if b <= block_number]
-            if len(blocks) > 0:
-                index = len(blocks) - (1+x)
-                if index < 0:
-                    index = 0
-                block_number = blocks[index]
-                block = await self.bma_access.future_request(bma.blockchain.Block,
-                                     req_args={'number': block_number})
-                return block
-            else:
-                return None
-        except errors.DuniterError as e:
-            if e.ucode == errors.BLOCK_NOT_FOUND:
-                logging.debug(str(e))
-                return None
-        except NoPeerAvailable as e:
-            logging.debug(str(e))
-            return None
-
-    async def monetary_mass(self):
-        """
-        Get the community monetary mass
-
-        :return: The monetary mass value
-        """
-        # Get cached block by block number
-        block_number = self.network.current_blockUID.number
-        if block_number:
-            block = await self.bma_access.future_request(bma.blockchain.Block,
-                                 req_args={'number': block_number})
-            return block['monetaryMass']
-        else:
-            return 0
-
-    async def nb_members(self):
-        """
-        Get the community members number
-
-        :return: The community members number
-        """
-        try:
-            # Get cached block by block number
-            block_number = self.network.current_blockUID.number
-            block = await self.bma_access.future_request(bma.blockchain.Block,
-                                 req_args={'number': block_number})
-            return block['membersCount']
-        except errors.DuniterError as e:
-            if e.ucode == errors.BLOCK_NOT_FOUND:
-                return 0
-        except NoPeerAvailable as e:
-            logging.debug(str(e))
-            return 0
-
-    async def time(self, block_number=None):
-        """
-        Get the blockchain time
-        :param block_number: The block number, None if current block
-        :return: The community blockchain time
-        :rtype: int
-        """
-        try:
-            # Get cached block by block number
-            if block_number is None:
-                block_number = self.network.current_blockUID.number
-            block = await self.bma_access.future_request(bma.blockchain.Block,
-                                 req_args={'number': block_number})
-            return block['medianTime']
-        except errors.DuniterError as e:
-            if e.ucode == errors.BLOCK_NOT_FOUND:
-                return 0
-        except NoPeerAvailable as e:
-            logging.debug(str(e))
-            return 0
-
-    @property
-    def network(self):
-        """
-        Get the community network instance.
-
-        :return: The community network instance.
-        :rtype: sakia.core.net.Network
-        """
-        return self._network
-
-    @property
-    def bma_access(self):
-        """
-        Get the community bma_access instance
-
-        :return: The community bma_access instace
-        :rtype: sakia.core.net.api.bma.access.BmaAccess
-        """
-        return self._bma_access
-
-    async def parameters(self):
-        """
-        Return community parameters in bma format
-        """
-        return await self.bma_access.future_request(bma.blockchain.Parameters)
-
-    async def certification_expired(self, cert_time):
-        """
-        Return True if the certificaton time is too old
-
-        :param int cert_time: the timestamp of the certification
-        """
-        parameters = await self.parameters()
-        blockchain_time = await self.time()
-        return blockchain_time - cert_time > parameters['sigValidity']
-
-    async def certification_writable(self, cert_time):
-        """
-        Return True if the certificaton time is too old
-
-        :param int cert_time: the timestamp of the certification
-        """
-        parameters = await self.parameters()
-        blockchain_time = await self.time()
-        return blockchain_time - cert_time < parameters['sigWindow'] * parameters['avgGenTime']
-
-    def add_node(self, node):
-        """
-        Add a peer to the community.
-
-        :param peer: The new peer as a duniterpy Peer object.
-        """
-        self._network.add_root_node(node)
-
-    def remove_node(self, index):
-        """
-        Remove a node from the community.
-
-        :param index: The index of the removed node.
-        """
-        self._network.remove_root_node(index)
-
-    async def get_block(self, number=None):
-        """
-        Get a block
-
-        :param int number: The block number. If none, returns current block.
-        """
-        if number is None:
-            block_number = self.network.current_blockUID.number
-            data = await self.bma_access.future_request(bma.blockchain.Block,
-                                 req_args={'number': block_number})
-        else:
-            logging.debug("Requesting block {0}".format(number))
-            data = await self.bma_access.future_request(bma.blockchain.Block,
-                                req_args={'number': number})
-        return data
-
-    async def members_pubkeys(self):
-        """
-        Listing members pubkeys of a community
-
-        :return: All members pubkeys.
-        """
-        memberships = await self.bma_access.future_request(bma.wot.Members)
-        return [m['pubkey'] for m in memberships["results"]]
-
-    def start_coroutines(self):
-        self.network.start_coroutines()
-
-    async def stop_coroutines(self, closing=False):
-        await self.network.stop_coroutines(closing)
-
-    def rollback_cache(self):
-        self._bma_access.rollback()
-
-    def jsonify(self):
-        """
-        Jsonify the community datas.
-
-        :return: The community as a dict in json format.
-        """
-
-        nodes_data = []
-        for node in self._network.root_nodes:
-            nodes_data.append(node.jsonify_root_node())
-
-        data = {'currency': self.currency,
-                'peers': nodes_data}
-        return data
diff --git a/src/sakia/data/entities/blockchain.py b/src/sakia/data/entities/blockchain.py
index 72d44d383a99239aee92d7ab50345c55d3d304fe..7e5b3ef9f627a7035ee53543da2a4743475c5c53 100644
--- a/src/sakia/data/entities/blockchain.py
+++ b/src/sakia/data/entities/blockchain.py
@@ -5,37 +5,37 @@ from duniterpy.documents import block_uid, BlockUID
 @attr.s()
 class BlockchainParameters:
     # The decimal percent growth of the UD every [dt] period
-    c = attr.ib(convert=float, default=0, cmp=False)
+    c = attr.ib(convert=float, default=0, cmp=False, hash=False)
     # Time period between two UD in seconds
-    dt = attr.ib(convert=int, default=0, cmp=False)
+    dt = attr.ib(convert=int, default=0, cmp=False, hash=False)
     # UD(0), i.e. initial Universal Dividend
-    ud0 = attr.ib(convert=int, default=0, cmp=False)
+    ud0 = attr.ib(convert=int, default=0, cmp=False, hash=False)
     # Minimum delay between 2 certifications of a same issuer, in seconds. Must be positive or zero
-    sig_period = attr.ib(convert=int, default=0, cmp=False)
+    sig_period = attr.ib(convert=int, default=0, cmp=False, hash=False)
     # Maximum quantity of active certifications made by member
-    sig_stock = attr.ib(convert=int, default=0, cmp=False)
+    sig_stock = attr.ib(convert=int, default=0, cmp=False, hash=False)
     # Maximum delay in seconds a certification can wait before being expired for non-writing
-    sig_window = attr.ib(convert=int, default=0, cmp=False)
+    sig_window = attr.ib(convert=int, default=0, cmp=False, hash=False)
     # Maximum age of a active signature (in seconds)
-    sig_validity = attr.ib(convert=int, default=0, cmp=False)
+    sig_validity = attr.ib(convert=int, default=0, cmp=False, hash=False)
     # Minimum quantity of signatures to be part of the WoT
-    sig_qty = attr.ib(convert=int, default=0, cmp=False)
+    sig_qty = attr.ib(convert=int, default=0, cmp=False, hash=False)
     # Minimum decimal percent of sentries to reach to match the distance rule
-    xpercent = attr.ib(convert=float, default=0, cmp=False)
+    xpercent = attr.ib(convert=float, default=0, cmp=False, hash=False)
     # Maximum age of an active membership( in seconds)
-    ms_validity = attr.ib(convert=int, default=0, cmp=False)
+    ms_validity = attr.ib(convert=int, default=0, cmp=False, hash=False)
     # Maximum distance between each WoT member and a newcomer
-    step_max = attr.ib(convert=int, default=0, cmp=False)
+    step_max = attr.ib(convert=int, default=0, cmp=False, hash=False)
     # Number of blocks used for calculating median time
-    median_time_blocks = attr.ib(convert=int, default=0, cmp=False)
+    median_time_blocks = attr.ib(convert=int, default=0, cmp=False, hash=False)
     # The average time for writing 1 block (wished time) in seconds
-    avg_gen_time = attr.ib(convert=int, default=0, cmp=False)
+    avg_gen_time = attr.ib(convert=int, default=0, cmp=False, hash=False)
     # The number of blocks required to evaluate again PoWMin value
-    dt_diff_eval = attr.ib(convert=int, default=0, cmp=False)
+    dt_diff_eval = attr.ib(convert=int, default=0, cmp=False, hash=False)
     # The number of previous blocks to check for personalized difficulty
-    blocks_rot = attr.ib(convert=int, default=0, cmp=False)
+    blocks_rot = attr.ib(convert=int, default=0, cmp=False, hash=False)
     # The decimal percent of previous issuers to reach for personalized difficulty
-    percent_rot = attr.ib(convert=float, default=0, cmp=False)
+    percent_rot = attr.ib(convert=float, default=0, cmp=False, hash=False)
 
 
 @attr.s()
@@ -45,16 +45,18 @@ class Blockchain:
     # block number and hash
     current_buid = attr.ib(convert=block_uid, default=BlockUID.empty())
     # Number of members
-    nb_members = attr.ib(convert=int, default=0, cmp=False)
+    nb_members = attr.ib(convert=int, default=0, cmp=False, hash=False)
     # Current monetary mass in units
-    current_mass = attr.ib(convert=int, default=0, cmp=False)
+    current_mass = attr.ib(convert=int, default=0, cmp=False, hash=False)
     # Median time in seconds
-    median_time = attr.ib(convert=int, default=0, cmp=False)
+    median_time = attr.ib(convert=int, default=0, cmp=False, hash=False)
     # Last UD amount in units (multiply by 10^base)
-    last_ud = attr.ib(convert=int, default=0, cmp=False)
+    last_ud = attr.ib(convert=int, default=0, cmp=False, hash=False)
     # Last UD base
-    last_ud_base = attr.ib(convert=int, default=0, cmp=False)
+    last_ud_base = attr.ib(convert=int, default=0, cmp=False, hash=False)
+    # Last UD base
+    last_ud_time = attr.ib(convert=int, default=0, cmp=False, hash=False)
     # Previous monetary mass in units
-    previous_mass = attr.ib(convert=int, default=0, cmp=False)
+    previous_mass = attr.ib(convert=int, default=0, cmp=False, hash=False)
     # Currency name
-    currency = attr.ib(convert=str, default="", cmp=False)
+    currency = attr.ib(convert=str, default="", cmp=False, hash=False)
diff --git a/src/sakia/data/processors/blockchain.py b/src/sakia/data/processors/blockchain.py
index 2b862745ba4918b451c03b38d599191b79476e5b..358263e14539bd541fc4a58b373d86e49553862a 100644
--- a/src/sakia/data/processors/blockchain.py
+++ b/src/sakia/data/processors/blockchain.py
@@ -1,4 +1,5 @@
 import attr
+import re
 from ..entities import Blockchain
 from duniterpy.api import bma
 from duniterpy.documents import Block
@@ -18,6 +19,70 @@ class BlockchainProcessor:
         """
         return self._repo.get_one({'currency': self._currency}).current_buid
 
+    def time(self):
+        """
+        Get the local current median time
+        :rtype: int
+        """
+        return self._repo.get_one({'currency': self._currency}).median_time
+
+    def parameters(self):
+        """
+        Get the parameters of the blockchain
+        :rtype: sakia.data.entities.BlockchainParameters
+        """
+        return self._repo.get_one({'currency': self._currency}).parameters
+
+    def monetary_mass(self):
+        """
+        Get the local current monetary mass
+        :rtype: int
+        """
+        return self._repo.get_one({'currency': self._currency}).monetary_mass
+
+    def nb_members(self):
+        """
+        Get the number of members in the blockchain
+        :rtype: int
+        """
+        return self._repo.get_one({'currency': self._currency}).nb_members
+
+    def last_ud(self):
+        """
+        Get the last ud value and base
+        :rtype: int, int
+        """
+        blockchain = self._repo.get_one({'currency': self._currency})
+        return blockchain.last_ud, blockchain.last_ud_base
+
+    @property
+    def short_currency(self):
+        """
+        Format the currency name to a short one
+
+        :return: The currency name in a shot format.
+        """
+        words = re.split('[_\W]+', self.currency)
+        shortened = ""
+        if len(words) > 1:
+            shortened = ''.join([w[0] for w in words])
+        else:
+            vowels = ('a', 'e', 'i', 'o', 'u', 'y')
+            shortened = self.currency
+            shortened = ''.join([c for c in shortened if c not in vowels])
+        return shortened.upper()
+
+    @property
+    def currency_symbol(self):
+        """
+        Format the currency name to a symbol one.
+
+        :return: The currency name as a utf-8 circled symbol.
+        """
+        letter = self.currency[0]
+        u = ord('\u24B6') + ord(letter) - ord('A')
+        return chr(u)
+
     async def new_blocks_with_identities(self):
         """
         Get blocks more recent than local blockuid
diff --git a/src/sakia/services/blockchain.py b/src/sakia/services/blockchain.py
index f8936168ebadcfcd8ed872432f2cec233dfeac5b..7bbc2d4b704cc44da3b1dbd0d8e94db282d87da9 100644
--- a/src/sakia/services/blockchain.py
+++ b/src/sakia/services/blockchain.py
@@ -28,7 +28,6 @@ class BlockchainService(QObject):
         Handle a new current block uid
         :param duniterpy.documents.BlockUID new_block_uid: the new current blockuid
         """
-        local_current_buid = self._blockchain_processor.current_buid()
         with_identities = await self._blockchain_processor.new_blocks_with_identities()
         with_money = await self._blockchain_processor.new_blocks_with_money()
         blocks = await self._blockchain_processor.blocks(with_identities + with_money)
diff --git a/src/sakia/services/identities.py b/src/sakia/services/identities.py
index 85691dd6138479265d554c610c3dcfcc38c685ce..13c878add583aafd53453457bd12bf767f0abb28 100644
--- a/src/sakia/services/identities.py
+++ b/src/sakia/services/identities.py
@@ -8,21 +8,43 @@ class IdentitiesService(QObject):
     Identities service is managing identities data received
     to update data locally
     """
-    def __init__(self, currency, identities_processor, certs_processor, bma_connector):
+    def __init__(self, currency, identities_processor, certs_processor, blockchain_processor, bma_connector):
         """
         Constructor the identities service
 
         :param str currency: The currency name of the community
         :param sakia.data.processors.IdentitiesProcessor identities_processor: the identities processor for given currency
         :param sakia.data.processors.CertificationsProcessor certs_processor: the certifications processor for given currency
+        :param sakia.data.processors.BlockchainProcessor certs_processor: the blockchain processor for given currency
         :param sakia.data.connectors.BmaConnector bma_connector: The connector to BMA API
         """
         super().__init__()
         self._identities_processor = identities_processor
         self._certs_processor = certs_processor
+        self._blockchain_processor = blockchain_processor
         self._bma_connector = bma_connector
         self.currency = currency
 
+    def certification_expired(self, cert_time):
+        """
+        Return True if the certificaton time is too old
+
+        :param int cert_time: the timestamp of the certification
+        """
+        parameters = self._blockchain_processor.parameters()
+        blockchain_time = self._blockchain_processor.median_time()
+        return blockchain_time - cert_time > parameters.sig_validity
+
+    def certification_writable(self, cert_time):
+        """
+        Return True if the certificaton time is too old
+
+        :param int cert_time: the timestamp of the certification
+        """
+        parameters = self._blockchain_processor.parameters()
+        blockchain_time = self._blockchain_processor.median_time()
+        return blockchain_time - cert_time < parameters.sig_window * parameters.avg_gen_time
+
     def _parse_revocations(self, block):
         """
         Parse revoked pubkeys found in a block and refresh local data
diff --git a/src/sakia/services/network.py b/src/sakia/services/network.py
index e4d5c779fecfba887a0fe2fca1c6e1606982b581..9f12bbe1ec5525c4c983ee2c9589f91fd603529b 100644
--- a/src/sakia/services/network.py
+++ b/src/sakia/services/network.py
@@ -17,8 +17,6 @@ class NetworkService(QObject):
     """
     nodes_changed = pyqtSignal()
     root_nodes_changed = pyqtSignal()
-    blockchain_progress = pyqtSignal(int)
-    blockchain_rollback = pyqtSignal(int)
 
     def __init__(self, currency, processor, connectors, session):
         """