diff --git a/src/cutecoin/core/app.py b/src/cutecoin/core/app.py
index 33e853dbcb9db345f25d8f97f03735da3a805e43..7ef3a31d77a306ae918f8eb36d4f13df2ef64944 100644
--- a/src/cutecoin/core/app.py
+++ b/src/cutecoin/core/app.py
@@ -15,6 +15,7 @@ from PyQt5.QtCore import QObject, pyqtSignal
 from . import config
 from ..tools.exceptions import NameAlreadyExists, BadAccountFile
 from .account import Account
+from . import person
 from .. import __version__
 
 
@@ -76,8 +77,8 @@ class Application(QObject):
         self.current_account = account
 
     def load(self):
-        if (os.path.exists(config.parameters['data'])
-                and os.path.isfile(config.parameters['data'])):
+        self.load_persons()
+        try:
             logging.debug("Loading data...")
             with open(config.parameters['data'], 'r') as json_data:
                 data = json.load(json_data)
@@ -85,6 +86,18 @@ class Application(QObject):
                     self.default_account = data['default_account']
                 for account_name in data['local_accounts']:
                     self.accounts[account_name] = None
+        except FileNotFoundError:
+            pass
+
+    def load_persons(self):
+        try:
+            persons_path = os.path.join(config.parameters['home'],
+                                        '__persons__')
+            with open(persons_path, 'r') as persons_path:
+                data = json.load(persons_path)
+                person.load_cache(data)
+        except FileNotFoundError:
+            pass
 
     def load_account(self, account_name):
         account_path = os.path.join(config.parameters['home'],
@@ -100,6 +113,19 @@ class Application(QObject):
             community_path = os.path.join(config.parameters['home'],
                                         account.name, '__cache__',
                                         community.currency)
+
+            network_path = os.path.join(config.parameters['home'],
+                                        account.name, '__cache__',
+                                        community.currency + '_network')
+
+            if os.path.exists(network_path):
+                with open(network_path, 'r') as json_data:
+                    data = json.load(json_data)
+                if 'version' in data and data['version'] == __version__:
+                    community.load_network(data)
+                else:
+                    os.remove(network_path)
+
             if os.path.exists(community_path):
                 with open(community_path, 'r') as json_data:
                     data = json.load(json_data)
@@ -135,6 +161,14 @@ class Application(QObject):
             account_path = os.path.join(config.parameters['home'], account.name)
             shutil.rmtree(account_path)
 
+    def save_persons(self):
+        persons_path = os.path.join(config.parameters['home'],
+                                    '__persons__')
+        with open(persons_path, 'w')as outfile:
+            data = person.jsonify_cache()
+            data['version'] = __version__
+            json.dump(data, outfile, indent=4, sort_keys=True)
+
     def save_cache(self, account):
         if not os.path.exists(os.path.join(config.parameters['home'],
                                         account.name, '__cache__')):
@@ -152,6 +186,16 @@ class Application(QObject):
             community_path = os.path.join(config.parameters['home'],
                                         account.name, '__cache__',
                                         community.currency)
+
+            network_path = os.path.join(config.parameters['home'],
+                                        account.name, '__cache__',
+                                        community.currency + '_network')
+
+            with open(network_path, 'w') as outfile:
+                data = community.jsonify_network()
+                data['version'] = __version__
+                json.dump(data, outfile, indent=4, sort_keys=True)
+
             with open(community_path, 'w') as outfile:
                 data = community.jsonify_cache()
                 data['version'] = __version__
diff --git a/src/cutecoin/core/community.py b/src/cutecoin/core/community.py
index 018f65f1e9ecb87ebee341551657ca7ef4dd4fab..762dd50232bd01eabd5c6a9bb1d889f390a03de4 100644
--- a/src/cutecoin/core/community.py
+++ b/src/cutecoin/core/community.py
@@ -17,6 +17,9 @@ from requests.exceptions import RequestException
 
 
 class Cache():
+    _saved_requests = [hash(bma.blockchain.Block),
+                       hash(bma.wot.Lookup)]
+
     def __init__(self, community):
         self.latest_block = 0
         self.community = community
@@ -32,9 +35,8 @@ class Cache():
         self.latest_block = data['latest_block']
 
     def jsonify(self):
-        saved_requests = [hash(bma.blockchain.Block)]
         data = {k: self.data[k] for k in self.data.keys()
-                   if k[0] in saved_requests}
+                   if k[0] in Cache._saved_requests}
         entries = []
         for d in data:
             entries.append({'key': d,
@@ -44,9 +46,8 @@ class Cache():
 
     def refresh(self):
         self.latest_block = self.community.current_blockid()['number']
-        saved_requests = [hash(bma.blockchain.Block)]
         self.data = {k: self.data[k] for k in self.data.keys()
-                   if k[0] in saved_requests}
+                   if k[0] in Cache._saved_requests}
 
     def request(self, request, req_args={}, get_args={}):
         cache_key = (hash(request),
@@ -85,26 +86,31 @@ class Community(object):
         self._cache.refresh()
 
     @classmethod
-    def create(cls, currency, peer):
-        community = cls(currency, [peer])
+    def create(cls, node):
+        network = Network.create(node)
+        community = cls(node.currency, network)
         logging.debug("Creating community")
         return community
 
     @classmethod
     def load(cls, json_data):
         currency = json_data['currency']
-
         network = Network.from_json(currency, json_data['peers'])
-
         community = cls(currency, network)
         return community
 
+    def load_network(self, json_data):
+        self._network.merge_with_json(json_data['network'])
+
     def load_cache(self, json_data):
         self._cache.load_from_json(json_data)
 
     def jsonify_cache(self):
         return self._cache.jsonify()
 
+    def jsonify_network(self):
+        return {'network': self._network.jsonify()}
+
     def name(self):
         return self.currency
 
diff --git a/src/cutecoin/core/net/network.py b/src/cutecoin/core/net/network.py
index 665fe9d66a233de79e26cdaed7cd794e01a4c92c..af0c247ab4d1f6c43915f29243f2945b09f85d0b 100644
--- a/src/cutecoin/core/net/network.py
+++ b/src/cutecoin/core/net/network.py
@@ -31,10 +31,13 @@ class Network(QObject):
         for n in self._nodes:
             n.changed.connect(self.nodes_changed)
         self.must_crawl = False
-        #TODO: Crawl nodes at startup
 
     @classmethod
     def from_json(cls, currency, json_data):
+        '''
+        We load the nodes which we know for sure since we
+        used them at the community creation
+        '''
         nodes = []
         for data in json_data:
             node = Node.from_json(currency, data)
@@ -42,23 +45,34 @@ class Network(QObject):
             logging.debug("Loading : {:}".format(data['pubkey']))
         block_max = max([n.block for n in nodes])
         for node in nodes:
-            node.check_sync(currency, block_max)
+            node.check_sync(block_max)
         return cls(currency, nodes)
 
+    def merge_with_json(self, json_data):
+        '''
+        We merge with dynamic nodes detected when we
+        last stopped cutecoin
+        '''
+        for data in json_data:
+            node = Node.from_json(self.currency, data)
+            self._nodes.append(node)
+            logging.debug("Loading : {:}".format(data['pubkey']))
+        self._nodes = self.crawling()
+
     @classmethod
-    def create(cls, currency, node):
+    def create(cls, node):
         nodes = [node]
-        network = cls(currency, nodes)
-        nodes = network.crawling
+        network = cls(node.currency, nodes)
+        nodes = network.crawling()
         block_max = max([n.block for n in nodes])
         for node in nodes:
-            node.check_sync(currency, block_max)
+            node.check_sync(block_max)
         network._nodes = nodes
         return network
 
     def jsonify(self):
         data = []
-        for node in self.nodes:
+        for node in self._nodes:
             data.append(node.jsonify())
         return data
 
@@ -105,13 +119,13 @@ class Network(QObject):
             logging.debug("Peering : next to read : {0} : {1}".format(n.pubkey,
                           (n.pubkey not in traversed_pubkeys)))
             if n.pubkey not in traversed_pubkeys:
-                n.peering_traversal(self.currency, nodes,
+                n.peering_traversal(nodes,
                                     traversed_pubkeys, interval)
                 time.sleep(interval)
 
         block_max = max([n.block for n in nodes])
         for node in [n for n in nodes if n.state == Node.ONLINE]:
-            node.check_sync(self.currency, block_max)
+            node.check_sync(block_max)
 
         #TODO: Offline nodes for too long have to be removed
         #TODO: Corrupted nodes should maybe be removed faster ?
diff --git a/src/cutecoin/core/net/node.py b/src/cutecoin/core/net/node.py
index 448e14a8ca632dcad4021860a75a386c8a267e34..b7e1366e12cb7a5b4f1b6cb28315348ea1561318 100644
--- a/src/cutecoin/core/net/node.py
+++ b/src/cutecoin/core/net/node.py
@@ -6,7 +6,9 @@ Created on 21 févr. 2015
 
 from ucoinpy.documents.peer import Peer, BMAEndpoint, Endpoint
 from ucoinpy.api import bma
+from ucoinpy.api.bma import ConnectionHandler
 from requests.exceptions import RequestException
+from ...tools.exceptions import InvalidNodeCurrency
 import logging
 import time
 
@@ -25,7 +27,7 @@ class Node(QObject):
 
     changed = pyqtSignal()
 
-    def __init__(self, endpoints, pubkey, block, state):
+    def __init__(self, currency, endpoints, pubkey, block, state):
         '''
         Constructor
         '''
@@ -35,11 +37,31 @@ class Node(QObject):
         self._block = block
         self._state = state
         self._neighbours = []
+        self._currency = currency
+
+    @classmethod
+    def from_address(cls, currency, address, port):
+        peer_data = bma.network.Peering(ConnectionHandler(address, port)).get()
+
+        peer = Peer.from_signed_raw("{0}{1}\n".format(peer_data['raw'],
+                                                  peer_data['signature']))
+
+        if currency is not None:
+            if peer.currency != currency:
+                raise InvalidNodeCurrency(peer.currency, currency)
+
+        node = cls(peer.currency, peer.endpoints, peer.pubkey, 0, Node.ONLINE, 0)
+        node.refresh_state()
+        return node
 
     @classmethod
     def from_peer(cls, currency, peer):
-        node = cls(peer.endpoints, "", 0, Node.ONLINE)
-        node.refresh_state(currency)
+        if currency is not None:
+            if peer.currency != currency:
+                raise InvalidNodeCurrency(peer.currency, currency)
+
+        node = cls(peer.currency, peer.endpoints, "", 0, Node.ONLINE)
+        node.refresh_state()
         return node
 
     @classmethod
@@ -48,12 +70,15 @@ class Node(QObject):
         for endpoint_data in data['endpoints']:
             endpoints.append(Endpoint.from_inline(endpoint_data))
 
-        node = cls(endpoints, "", 0, Node.ONLINE)
-        node.refresh_state(currency)
+        currency = data['currency']
+
+        node = cls(currency, endpoints, "", 0, Node.ONLINE)
+        node.refresh_state()
         return node
 
     def jsonify(self):
-        data = {'pubkey': self._pubkey}
+        data = {'pubkey': self._pubkey,
+                'currency': self._currency}
         endpoints = []
         for e in self._endpoints:
             endpoints.append(e.inline())
@@ -76,17 +101,21 @@ class Node(QObject):
     def state(self):
         return self._state
 
+    @property
+    def currency(self):
+        return self._currency
+
     @property
     def neighbours(self):
         return self._neighbours
 
-    def check_sync(self, currency, block):
+    def check_sync(self, block):
         if self._block < block:
             self._state = Node.DESYNCED
         else:
             self._state = Node.ONLINE
 
-    def refresh_state(self, currency):
+    def refresh_state(self):
         emit_change = False
         try:
             informations = bma.network.Peering(self.endpoint.conn_handler()).get()
@@ -108,51 +137,57 @@ class Node(QObject):
             self._state = Node.OFFLINE
             emit_change = True
 
-        if node_currency != currency:
-            self.state = Node.CORRUPTED
-            emit_change = True
-
-        if block_number != self._block:
-            self._block = block_number
-            emit_change = True
-
-        if node_pubkey != self._pubkey:
-            self._pubkey = node_pubkey
-            emit_change = True
-
-        logging.debug(neighbours)
-        new_inlines = [e.inline() for n in neighbours for e in n]
-        last_inlines = [e.inline() for n in self._neighbours for e in n]
-
-        hash_new_neighbours = hash(tuple(frozenset(sorted(new_inlines))))
-        hash_last_neighbours = hash(tuple(frozenset(sorted(last_inlines))))
-        if hash_new_neighbours != hash_last_neighbours:
-            self._neighbours = neighbours
-            emit_change = True
+        # If not is offline, do not refresh last data
+        if self._state != Node.OFFLINE:
+            # If not changed its currency, consider it corrupted
+            if node_currency != self._currency:
+                self.state = Node.CORRUPTED
+                emit_change = True
+            else:
+                if block_number != self._block:
+                    self._block = block_number
+                    emit_change = True
+
+                if node_pubkey != self._pubkey:
+                    self._pubkey = node_pubkey
+                    emit_change = True
+
+                logging.debug(neighbours)
+                new_inlines = [e.inline() for n in neighbours for e in n]
+                last_inlines = [e.inline() for n in self._neighbours for e in n]
+
+                hash_new_neighbours = hash(tuple(frozenset(sorted(new_inlines))))
+                hash_last_neighbours = hash(tuple(frozenset(sorted(last_inlines))))
+                if hash_new_neighbours != hash_last_neighbours:
+                    self._neighbours = neighbours
+                    emit_change = True
 
         if emit_change:
             self.changed.emit()
 
-    def peering_traversal(self, currency, found_nodes,
+    def peering_traversal(self, found_nodes,
                           traversed_pubkeys, interval):
         logging.debug("Read {0} peering".format(self.pubkey))
         traversed_pubkeys.append(self.pubkey)
-        self.refresh_state(currency)
-        if self.pubkey not in [n.pubkey for n in found_nodes]:
-            found_nodes.append(self)
+        self.refresh_state()
 
+        if self.pubkey not in [n.pubkey for n in found_nodes]:
+            # if node is corrupted remove it
+            if self._state != Node.CORRUPTED:
+                found_nodes.append(self)
         try:
+            logging.debug(self.neighbours)
             for n in self.neighbours:
-                e = next((e for e in self._endpoints if type(e) is BMAEndpoint))
-                peering = bma.network.Peering(self.endpoint.conn_handler()).get()
+                e = next(e for e in n if type(e) is BMAEndpoint)
+                peering = bma.network.Peering(e.conn_handler()).get()
                 peer = Peer.from_signed_raw("{0}{1}\n".format(peering['raw'],
                                                             peering['signature']))
-                node = Node.from_peer(currency, peer)
+                node = Node.from_peer(self._currency, peer)
                 logging.debug(traversed_pubkeys)
                 logging.debug("Traversing : next to read : {0} : {1}".format(node.pubkey,
                               (node.pubkey not in traversed_pubkeys)))
                 if node.pubkey not in traversed_pubkeys:
-                    node.peering_traversal(currency, found_nodes,
+                    node.peering_traversal(found_nodes,
                                         traversed_pubkeys, interval)
                     time.sleep(interval)
         except RequestException as e:
diff --git a/src/cutecoin/core/person.py b/src/cutecoin/core/person.py
index 57c6e7695ecc224cbcca7141eeb9678ae9c534da..2b40cb4e931fceae08c9752a69a2d7a3eb87b43d 100644
--- a/src/cutecoin/core/person.py
+++ b/src/cutecoin/core/person.py
@@ -5,56 +5,134 @@ Created on 11 févr. 2014
 '''
 
 import logging
+import functools
 from ucoinpy.api import bma
 from ucoinpy import PROTOCOL_VERSION
 from ucoinpy.documents.certification import SelfCertification
 from ucoinpy.documents.membership import Membership
 from cutecoin.tools.exceptions import PersonNotFoundError,\
                                         MembershipNotFoundError
+from PyQt5.QtCore import QMutex
 
 
-class Person(object):
+def load_cache(json_data):
+    for person_data in json_data['persons']:
+        person = Person.from_json(person_data)
+        Person._instances[person.pubkey] = person
+
+
+def jsonify_cache():
+    data = []
+    for person in Person._instances.values():
+        data.append(person.jsonify())
+    return {'persons': data}
 
+
+class cached(object):
+    '''
+    Decorator. Caches a function's return value each time it is called.
+    If called later with the same arguments, the cached value is returned
+    (not reevaluated).
+    Delete it to clear it from the cache
+    '''
+    def __init__(self, func):
+        self.func = func
+
+    def __call__(self, inst, community):
+        inst._cache_mutex.lock()
+        try:
+            inst._cache[community.currency]
+        except KeyError:
+            inst._cache[community.currency] = {}
+
+        try:
+            value = inst._cache[community.currency][self.func.__name__]
+        except KeyError:
+            value = self.func(inst, community)
+            inst._cache[community.currency][self.func.__name__] = value
+
+        inst._cache_mutex.unlock()
+        return value
+
+    def __repr__(self):
+        '''Return the function's docstring.'''
+        return self.func.__repr__
+
+    def __get__(self, inst, objtype):
+        if inst is None:
+            return self.func
+        return functools.partial(self, inst)
+
+
+class Person(object):
     '''
     A person with a name, a fingerprint and an email
-    Created by the person.factory
     '''
+    _instances = {}
 
-    def __init__(self, name, pubkey):
+    def __init__(self, name, pubkey, cache):
         '''
         Constructor
         '''
         self.name = name
         self.pubkey = pubkey
+        self._cache = cache
+        self._cache_mutex = QMutex()
 
     @classmethod
     def lookup(cls, pubkey, community, cached=True):
         '''
         Create a person from the pubkey found in a community
         '''
-        data = community.request(bma.wot.Lookup, req_args={'search': pubkey},
-                                 cached=cached)
-        timestamp = 0
+        if pubkey in Person._instances:
+            return Person._instances[pubkey]
+        else:
+            data = community.request(bma.wot.Lookup, req_args={'search': pubkey},
+                                     cached=cached)
+            timestamp = 0
 
-        for result in data['results']:
-            if result["pubkey"] == pubkey:
-                uids = result['uids']
-                for uid in uids:
-                    if uid["meta"]["timestamp"] > timestamp:
-                        timestamp = uid["meta"]["timestamp"]
-                        name = uid["uid"]
+            for result in data['results']:
+                if result["pubkey"] == pubkey:
+                    uids = result['uids']
+                    for uid in uids:
+                        if uid["meta"]["timestamp"] > timestamp:
+                            timestamp = uid["meta"]["timestamp"]
+                            name = uid["uid"]
 
-                return cls(name, pubkey)
+                        person = cls(name, pubkey, {})
+                        Person._instances[pubkey] = person
+                        logging.debug("{0}".format(Person._instances.keys()))
+                        return person
         raise PersonNotFoundError(pubkey, community.name())
 
     @classmethod
+    def from_metadata(cls, name, pubkey):
+        if pubkey in Person._instances:
+            return Person._instances[pubkey]
+        else:
+            person = cls(name, pubkey, {})
+            Person._instances[pubkey] = person
+            return person
+
+    @classmethod
+    #TODO: Remove name from person, contats should not use the person class
     def from_json(cls, json_person):
         '''
         Create a person from json data
         '''
-        name = json_person['name']
         pubkey = json_person['pubkey']
-        return cls(name, pubkey)
+        if pubkey in Person._instances:
+            return Person._instances[pubkey]
+        else:
+            name = json_person['name']
+            if 'cache' in json_person:
+                cache = json_person['cache']
+            else:
+                cache = {}
+
+            person = cls(name, pubkey, cache)
+            Person._instances[pubkey] = person
+            return person
 
     def selfcert(self, community):
         data = community.request(bma.wot.Lookup, req_args={'search': self.pubkey})
@@ -78,6 +156,7 @@ class Person(object):
                                              signature)
         raise PersonNotFoundError(self.pubkey, community.name())
 
+    @cached
     def membership(self, community):
         try:
             search = community.request(bma.blockchain.Membership,
@@ -97,12 +176,9 @@ class Person(object):
             if '400' in str(e):
                 raise MembershipNotFoundError(self.pubkey, community.name())
 
-        membership = Membership(PROTOCOL_VERSION, community.currency, self.pubkey,
-                                membership_data['blockNumber'],
-                                membership_data['blockHash'], 'IN', search['uid'],
-                                search['sigDate'], None)
-        return membership
+        return membership_data
 
+    @cached
     def is_member(self, community):
         try:
             certifiers = community.request(bma.wot.CertifiersOf, {'search': self.pubkey})
@@ -110,6 +186,7 @@ class Person(object):
         except ValueError:
             return False
 
+    @cached
     def certifiers_of(self, community):
         try:
             certifiers = community.request(bma.wot.CertifiersOf, {'search': self.pubkey})
@@ -141,6 +218,7 @@ class Person(object):
 
         return certifiers['certifications']
 
+    @cached
     def certified_by(self, community):
         try:
             certified_list = community.request(bma.wot.CertifiedBy, {'search': self.pubkey})
@@ -151,6 +229,7 @@ class Person(object):
             except ValueError as e:
                 logging.debug('bma.wot.Lookup request ValueError : ' + str(e))
                 return list()
+
             certified_list = list()
             for certified in data['results'][0]['signed']:
                 certified['cert_time'] = dict()
@@ -165,7 +244,35 @@ class Person(object):
 
         return certified_list['certifications']
 
+    def reload(self, func, community):
+        self._cache_mutex.lock()
+        if community.currency not in self._cache:
+            self._cache[community.currency] = {}
+
+        change = False
+        try:
+            before = self._cache[community.currency][func.__name__]
+        except KeyError:
+            change = True
+
+        value = func(self, community)
+
+        if not change:
+            if type(value) is dict:
+                hash_before = (hash(tuple(frozenset(sorted(before.keys())))),
+                             hash(tuple(frozenset(sorted(before.items())))))
+                hash_after = (hash(tuple(frozenset(sorted(value.keys())))),
+                             hash(tuple(frozenset(sorted(value.items())))))
+                change = hash_before != hash_after
+            elif type(value) is bool:
+                change = before != value
+
+        self._cache[community.currency][func.__name__] = value
+        self._cache_mutex.unlock()
+        return change
+
     def jsonify(self):
         data = {'name': self.name,
-                'pubkey': self.pubkey}
+                'pubkey': self.pubkey,
+                'cache': self._cache}
         return data
diff --git a/src/cutecoin/core/watchers/persons.py b/src/cutecoin/core/watchers/persons.py
new file mode 100644
index 0000000000000000000000000000000000000000..84e2dc8f7a12733918857358068e053b22375083
--- /dev/null
+++ b/src/cutecoin/core/watchers/persons.py
@@ -0,0 +1,37 @@
+'''
+Created on 27 févr. 2015
+
+@author: inso
+'''
+
+from PyQt5.QtCore import QObject, pyqtSlot, pyqtSignal
+from ..person import Person
+import logging
+
+
+class PersonsWatcher(QObject):
+    '''
+    This will crawl the network to always
+    have up to date informations about the nodes
+    '''
+
+    person_changed = pyqtSignal(str)
+    end_watching = pyqtSignal()
+
+    def __init__(self, community):
+        super().__init__()
+        self.community = community
+
+    @pyqtSlot()
+    def watch(self):
+        logging.debug("Watching persons")
+        for p in Person._instances.values():
+            for func in [Person.membership,
+                         Person.is_member,
+                         Person.certifiers_of,
+                         Person.certified_by]:
+                if p.reload(func, self.community):
+                    logging.debug("Change detected on {0} about {1}".format(p.pubkey,
+                                                                            func.__name__))
+                    self.person_changed.emit(p.pubkey)
+        self.end_watching.emit()
diff --git a/src/cutecoin/gui/community_tab.py b/src/cutecoin/gui/community_tab.py
index 3016af98064ef644b08b979416c88a719e659c38..69075a40d06bb8663de01e674853b5c9b8cf4be6 100644
--- a/src/cutecoin/gui/community_tab.py
+++ b/src/cutecoin/gui/community_tab.py
@@ -57,7 +57,7 @@ class CommunityTabWidget(QWidget, Ui_CommunityTabWidget):
         model = self.table_community_members.model()
         if index.row() < model.rowCount():
             source_index = model.mapToSource(index)
-            pubkey_col = model.sourceModel().columns.index('Pubkey')
+            pubkey_col = model.sourceModel().columns_ids.index('pubkey')
             pubkey_index = model.sourceModel().index(source_index.row(),
                                                    pubkey_col)
             pubkey = model.sourceModel().data(pubkey_index, Qt.DisplayRole)
@@ -183,3 +183,6 @@ The process to join back the community later will have to be done again."""
                                      "{0}".format(e),
                                      QMessageBox.Ok)
 
+    def refresh_person(self, pubkey):
+        index = self.table_community_members.model().sourceModel().person_index(pubkey)
+        self.table_community_members.model().sourceModel().dataChanged.emit(index[0], index[1])
diff --git a/src/cutecoin/gui/contact.py b/src/cutecoin/gui/contact.py
index 469b9fb88839af42fc85ed08fdc1c20c8839a92d..1f2a419cff8775507e54d7e3c1a98b45864916d7 100644
--- a/src/cutecoin/gui/contact.py
+++ b/src/cutecoin/gui/contact.py
@@ -39,7 +39,7 @@ class ConfigureContactDialog(QDialog, Ui_ConfigureContactDialog):
             self.contact.pubkey = pubkey
         else:
             try:
-                self.account.add_contact(Person(name, pubkey))
+                self.account.add_contact(Person.from_metadata(name, pubkey))
             except ContactAlreadyExists as e:
                 QMessageBox.critical(self, "Contact already exists",
                             str(e),
diff --git a/src/cutecoin/gui/currency_tab.py b/src/cutecoin/gui/currency_tab.py
index fc0da0cd398c7697b794afb6fc9b8dbf1dad065c..f6efa8ac90a4284fbf299a60c28d2fcbf5a96f94 100644
--- a/src/cutecoin/gui/currency_tab.py
+++ b/src/cutecoin/gui/currency_tab.py
@@ -22,6 +22,7 @@ from ..core.wallet import Wallet
 from ..core.person import Person
 from ..core.transfer import Transfer
 from ..core.watchers.blockchain import BlockchainWatcher
+from ..core.watchers.persons import PersonsWatcher
 
 
 class CurrencyTabWidget(QWidget, Ui_CurrencyTabWidget):
@@ -60,9 +61,17 @@ class CurrencyTabWidget(QWidget, Ui_CurrencyTabWidget):
 
         self.watcher_thread.start()
 
+        self.persons_watcher = PersonsWatcher(self.community)
+        self.persons_watcher.person_changed.connect(self.tab_community.refresh_person)
+        self.persons_watcher_thread = QThread()
+        self.persons_watcher.moveToThread(self.persons_watcher_thread)
+        self.persons_watcher_thread.started.connect(self.persons_watcher.watch)
+        self.persons_watcher.end_watching.connect(self.persons_watcher_thread.finished)
+        self.persons_watcher_thread.start()
+
         person = Person.lookup(self.app.current_account.pubkey, self.community)
         try:
-            join_block = person.membership(self.community).block_number
+            join_block = person.membership(self.community)['blockNumber']
             join_date = self.community.get_block(join_block).mediantime
             parameters = self.community.get_parameters()
             expiration_date = join_date + parameters['sigValidity']
@@ -160,11 +169,7 @@ class CurrencyTabWidget(QWidget, Ui_CurrencyTabWidget):
                                                      QModelIndex(),
                                                      [])
 
-        if self.tab_community.table_community_members.model():
-            self.tab_community.table_community_members.model().dataChanged.emit(
-                                                           QModelIndex(),
-                                                           QModelIndex(),
-                                                           [])
+        self.persons_watcher_thread.start()
 
         text = "Connected : Block {0}".format(block_number)
         self.status_label.setText(text)
diff --git a/src/cutecoin/gui/mainwindow.py b/src/cutecoin/gui/mainwindow.py
index 90d7c29db88cc8dfa782437527ec428aca9dbec9..4e0d982322792770032bf3996ac75cfc3c7eff83 100644
--- a/src/cutecoin/gui/mainwindow.py
+++ b/src/cutecoin/gui/mainwindow.py
@@ -179,7 +179,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
     def open_configure_account_dialog(self):
         dialog = ProcessConfigureAccount(self.app, self.app.current_account)
         dialog.accepted.connect(self.refresh)
-        dialog.exec_()
+        result = dialog.exec_()
+        if result == QDialog.Accepted:
+            self.action_change_account(self.app.current_account.name)
 
     def open_about_popup(self):
         """
@@ -320,6 +322,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
     def closeEvent(self, event):
         if self.app.current_account:
             self.app.save_cache(self.app.current_account)
+        self.app.save_persons()
         self.loader.deleteLater()
         self.loader_thread.deleteLater()
         super().closeEvent(event)
diff --git a/src/cutecoin/gui/process_cfg_account.py b/src/cutecoin/gui/process_cfg_account.py
index d61e3f438717642f7cbb130169fa2d1977b330cb..795d1ec265fd48a1529f9739f5cadbe88b712884 100644
--- a/src/cutecoin/gui/process_cfg_account.py
+++ b/src/cutecoin/gui/process_cfg_account.py
@@ -121,16 +121,11 @@ class StepPageCommunities(Step):
         nb_wallets = self.config_dialog.spinbox_wallets.value()
         self.config_dialog.account.set_walletpool_size(nb_wallets, password)
 
+        self.config_dialog.app.add_account(self.config_dialog.account)
         if len(self.config_dialog.app.accounts) == 1:
             self.config_dialog.app.default_account = self.config_dialog.account.name
-
-        try:
-            self.config_dialog.app.add_account(self.config_dialog.account)
-        except KeyAlreadyUsed as e:
-            QMessageBox.critical(self, "Error",
-                                 str(e), QMessageBox.Ok)
-            return
         self.config_dialog.app.save(self.config_dialog.account)
+        self.config_dialog.app.current_account = self.config_dialog.account
 
     def display_page(self):
         logging.debug("Communities DISPLAY")
diff --git a/src/cutecoin/gui/process_cfg_community.py b/src/cutecoin/gui/process_cfg_community.py
index 29a6e72b06c92c651ec387862188818c4021fa1e..f0356966c60d04181115f5a54e136b31b0abe2c6 100644
--- a/src/cutecoin/gui/process_cfg_community.py
+++ b/src/cutecoin/gui/process_cfg_community.py
@@ -17,6 +17,7 @@ from ..gen_resources.community_cfg_uic import Ui_CommunityConfigurationDialog
 from ..models.peering import PeeringTreeModel
 from ..core.community import Community
 from ..core.person import Person
+from ..core.net.node import Node
 from ..tools.exceptions import PersonNotFoundError, NoPeerAvailable
 
 
@@ -33,6 +34,7 @@ class StepPageInit(Step):
     '''
     def __init__(self, config_dialog):
         super().__init__(config_dialog)
+        self.node = None
         logging.debug("Init")
 
     def is_valid(self):
@@ -40,38 +42,21 @@ class StepPageInit(Step):
         port = self.config_dialog.spinbox_port.value()
         logging.debug("Is valid ? ")
         try:
-            peer_data = bma.network.Peering(ConnectionHandler(server, port))
-            peer_data.get()['raw']
-        except:
-            QMessageBox.critical(self.config_dialog, "Server error",
-                              "Cannot get node peering")
-            return False
+            self.node = Node.from_address(None, server, port)
+        except Exception as e:
+            QMessageBox.critical(self.config_dialog, ":(",
+                        str(e),
+                        QMessageBox.Ok)
+
         return True
 
     def process_next(self):
         '''
         We create the community
         '''
-        server = self.config_dialog.lineedit_server.text()
-        port = self.config_dialog.spinbox_port.value()
         account = self.config_dialog.account
         logging.debug("Account : {0}".format(account))
-        try:
-            peering = bma.network.Peering(ConnectionHandler(server, port))
-            peer_data = peering.get()
-            peer = Peer.from_signed_raw("{0}{1}\n".format(peer_data['raw'],
-                                                          peer_data['signature']))
-            currency = peer.currency
-            self.config_dialog.community = Community.create(currency, peer)
-        except NoPeerAvailable:
-            QMessageBox.critical(self.config_dialog, "Server Error",
-                              "Cannot join any peer in this community.")
-            raise
-        except requests.exceptions.RequestException as e:
-            QMessageBox.critical(self.config_dialog, ":(",
-                        str(e),
-                        QMessageBox.Ok)
-            raise
+        self.config_dialog.community = Community.create(self.node)
 
     def display_page(self):
         self.config_dialog.button_previous.setEnabled(False)
@@ -168,19 +153,13 @@ class ProcessConfigureCommunity(QDialog, Ui_CommunityConfigurationDialog):
         '''
         server = self.lineedit_server.text()
         port = self.spinbox_port.value()
-        try:
-            peer_data = bma.network.Peering(ConnectionHandler(server, port)).get()
 
-            peer = Peer.from_signed_raw("{0}{1}\n".format(peer_data['raw'],
-                                                      peer_data['signature']))
-            if peer.currency == self.community.currency:
-                self.community.add_peer(peer)
-            else:
-                QMessageBox.critical(self, "Error",
-                                     "This peer doesn't use this community currency.")
-        except requests.exceptions.RequestException as e:
-            QMessageBox.critical(self, "Server error",
-                              "Cannot get node peering")
+        try:
+            node = Node.from_address(self.community.currency, server, port)
+            self.community.add_node(node)
+        except Exception as e:
+            QMessageBox.critical(self, "Error",
+                                 str(e))
         self.tree_peers.setModel(PeeringTreeModel(self.community))
 
     def showContextMenu(self, point):
diff --git a/src/cutecoin/gui/wallets_tab.py b/src/cutecoin/gui/wallets_tab.py
index 3af3eb0cc8b68feef347628714c953bca2793cac..a688f162560a5268981231d1a74e3e9f30bfa212 100644
--- a/src/cutecoin/gui/wallets_tab.py
+++ b/src/cutecoin/gui/wallets_tab.py
@@ -45,7 +45,7 @@ class WalletsTabWidget(QWidget, Ui_WalletsTab):
             certified = person.certified_by(self.community)
             certifiers = person.certifiers_of(self.community)
 
-            renew_block = membership.block_number
+            renew_block = membership['blockNumber']
             last_renewal = self.community.get_block(renew_block).mediantime
             expiration = last_renewal + parameters['sigValidity']
         except MembershipNotFoundError:
diff --git a/src/cutecoin/gui/wot_tab.py b/src/cutecoin/gui/wot_tab.py
index 9933e02296d0e8b6977efebab5228977625bb75c..71a96c8b553437556d8060f2d3cef97605646c5d 100644
--- a/src/cutecoin/gui/wot_tab.py
+++ b/src/cutecoin/gui/wot_tab.py
@@ -254,4 +254,4 @@ class WotTabWidget(QWidget, Ui_WotTabWidget):
         return block.mediantime
 
     def get_person_from_metadata(self, metadata):
-        return Person(metadata['text'], metadata['id'])
+        return Person.from_metadata(metadata['text'], metadata['id'])
diff --git a/src/cutecoin/models/members.py b/src/cutecoin/models/members.py
index f2f22065020bc27a0b4b1eb98c8bd68d2e3cba10..72ce548225455de1adfbdca3728e42f11913f07f 100644
--- a/src/cutecoin/models/members.py
+++ b/src/cutecoin/models/members.py
@@ -7,7 +7,7 @@ Created on 5 févr. 2014
 from ucoinpy.api import bma
 from ..core.person import Person
 from PyQt5.QtCore import QAbstractTableModel, QSortFilterProxyModel, Qt, \
-                        QDateTime
+                        QDateTime, QModelIndex
 from PyQt5.QtGui import QColor
 import logging
 
@@ -92,7 +92,7 @@ class MembersTableModel(QAbstractTableModel):
 
     def member_data(self, pubkey):
         person = Person.lookup(pubkey, self.community)
-        join_block = person.membership(self.community).block_number
+        join_block = person.membership(self.community)['blockNumber']
         join_date = self.community.get_block(join_block).mediantime
         parameters = self.community.get_parameters()
         expiration_date = join_date + parameters['sigValidity']
@@ -104,5 +104,14 @@ class MembersTableModel(QAbstractTableModel):
             col = index.column()
             return self.member_data(self.pubkeys[row])[col]
 
+    def person_index(self, pubkey):
+        try:
+            row = self.pubkeys.index(pubkey)
+            index_start = self.index(row, 0)
+            index_end = self.index(row, len(self.columns_ids))
+            return (index_start, index_end)
+        except ValueError:
+            return (QModelIndex(), QModelIndex())
+
     def flags(self, index):
         return Qt.ItemIsSelectable | Qt.ItemIsEnabled
diff --git a/src/cutecoin/tools/exceptions.py b/src/cutecoin/tools/exceptions.py
index d063899b1812883197e96ceec3efaad1cad6d8ed..f394b397109d777550893881fd698817120ec199 100644
--- a/src/cutecoin/tools/exceptions.py
+++ b/src/cutecoin/tools/exceptions.py
@@ -163,6 +163,19 @@ class NoPeerAvailable(Error):
             .format(currency, peers))
 
 
+class InvalidNodeCurrency(Error):
+    '''
+    Exception raised when a node doesn't use the intended currency
+    '''
+    def __init__(self, currency, node_currency):
+        '''
+        Constructor
+        '''
+        super() .__init__(
+            "Node is working for {0} currency, but should be {1}"
+            .format(node_currency, currency))
+
+
 class ContactAlreadyExists(Error):
     '''
     Exception raised when a community doesn't have any