diff --git a/ucoinj-cesium/redirector.err b/ucoinj-cesium/redirector.err
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/ucoinj-cesium/redirector.out b/ucoinj-cesium/redirector.out
new file mode 100644
index 0000000000000000000000000000000000000000..9b92690788c7c893ccbf3355051d9bede66ffe8e
--- /dev/null
+++ b/ucoinj-cesium/redirector.out
@@ -0,0 +1,18 @@
+Running live reload server: undefined
+Watching: 0=www/**/*, 1=!www/lib/**/*
+Running dev server:  http://localhost:8100
+Ionic server commands, enter:
+  restart or r to restart the client app from the root
+  goto or g and a url to have the app navigate to the given url
+  consolelogs or c to enable/disable console log output
+  serverlogs or s to enable/disable server log output
+  quit or q to shutdown the server and exit
+
+ionic $ Ionic server commands, enter:
+  restart or r to restart the client app from the root
+  goto or g and a url to have the app navigate to the given url
+  consolelogs or c to enable/disable console log output
+  serverlogs or s to enable/disable server log output
+  quit or q to shutdown the server and exit
+
+ionic $ 
\ No newline at end of file
diff --git a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/BlockchainBlock.java b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/BlockchainBlock.java
index 32dfb34d732d3dafef624c01c5d0acd017734b18..3702ae181a24800a3736f1c9a9e108f714679753 100644
--- a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/BlockchainBlock.java
+++ b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/BlockchainBlock.java
@@ -39,29 +39,31 @@ public class BlockchainBlock implements Serializable {
     
     private String version;
     private Integer nonce;
-    private Integer powMin;
     private Integer number;
+    private Integer powMin;
 	private Integer time;
     private Integer medianTime;
     private Integer membersCount;
     private BigInteger monetaryMass;
+    private Integer unitBase;
     private String currency;
     private String issuer;
-    private String signature;
     private String hash;
     private String parameters;
     private String previousHash;
     private String previousIssuer;
+    private String inner_hash;
     private BigInteger dividend;
-    private String[] membersChanges;
     private Identity[] identities;
     private Joiner[] joiners;
-    private String[] actives;
-    private String[] leavers;
+    private Joiner[] leavers;
+    private Joiner[] actives;
+    private Revoked[] revoked;
     private String[] excluded;
     private String[] certifications;
-//            private int actives": [],
-//            private int transactions": [],
+    private Transaction[] transactions;
+    private String signature;
+
 
 //  raw": "Version: 1\nType: Block\nCurrency: zeta_brouzouf\nNonce: 8233\nNumber: 1\nDate: 1416589860\nConfirmedDate: 1416589860\nIssuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk\nPreviousHash: 00006CD96A01378465318E48310118AC6B2F3625\nPreviousIssuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk\nMembersCount: 4\nIdentities:\nJoiners:\nActives:\nLeavers:\nExcluded:\nCertifications:\nTransactions:\n"
     //private String raw;
@@ -181,9 +183,74 @@ public class BlockchainBlock implements Serializable {
         this.joiners = joiners;
     }
 
+    public Integer getUnitBase() {
+        return unitBase;
+    }
+
+    public void setUnitBase(Integer unitBase) {
+        this.unitBase = unitBase;
+    }
+
+    public String getInnerHash() {
+        return inner_hash;
+    }
+
+    public void setInnerHash(String inner_hash) {
+        this.inner_hash = inner_hash;
+    }
+
+    public Joiner[] getLeavers() {
+        return leavers;
+    }
+
+    public void setLeavers(Joiner[] leavers) {
+        this.leavers = leavers;
+    }
+
+    public Joiner[] getActives() {
+        return actives;
+    }
+
+    public void setActives(Joiner[] actives) {
+        this.actives = actives;
+    }
+
+    public Revoked[] getRevoked() {
+        return revoked;
+    }
+
+    public void setRevoked(Revoked[] revoked) {
+        this.revoked = revoked;
+    }
+
+    public String[] getExcluded() {
+        return excluded;
+    }
+
+    public void setExcluded(String[] excluded) {
+        this.excluded = excluded;
+    }
+
+    public String[] getCertifications() {
+        return certifications;
+    }
+
+    public void setCertifications(String[] certifications) {
+        this.certifications = certifications;
+    }
+
+    public Transaction[] getTransactions() {
+        return transactions;
+    }
+
+    public void setTransactions(Transaction[] transactions) {
+        this.transactions = transactions;
+    }
+
     public String toString() {
         String s = "version=" + version;
         s += "\nnonce=" + nonce;
+        s += "\ninner_hash=" + inner_hash;
         s += "\nnumber=" + number;
         s += "\npowMin" + powMin;
         s += "\ntime=" + time;
@@ -199,11 +266,6 @@ public class BlockchainBlock implements Serializable {
         s += "\npreviousIssuer=" + previousIssuer;
         s += "\ndividend=" + dividend;
         s += "\nmembersChanges:";
-        if (membersChanges != null) {
-            for (String m : membersChanges) {
-                s += "\n\t" + m;
-            }
-        }
         s += "\nidentities:";
         if (identities != null) {
             for (Identity i : identities) {
@@ -216,10 +278,22 @@ public class BlockchainBlock implements Serializable {
                 s += "\n\t" + j.toString();
             }
         }
+        s += "\nactives:";
+        if (actives != null) {
+            for (Joiner a : actives) {
+                s += "\n\t" + a.toString();
+            }
+        }
         s += "\nleavers:";
         if (leavers != null) {
-            for (String l : leavers) {
-                s += "\n\t" + l;
+            for (Joiner l : leavers) {
+                s += "\n\t" + l.toString();
+            }
+        }
+        s += "\nrevoked:";
+        if (leavers != null) {
+            for (Revoked r : revoked) {
+                s += "\n\t" + r.toString();
             }
         }
         s += "\nexcluded:";
@@ -242,20 +316,20 @@ public class BlockchainBlock implements Serializable {
 
         private static final long serialVersionUID = 8080689271400316984L;
 
-        private String pubkey;
+        private String publicKey;
 
         private String signature;
 
-        private String uid;
+        private String blockUid;
 
-        private long timestamp = -1;
+        private String userId;
 
-        public String getPubkey() {
-            return pubkey;
+        public String getPublicKey() {
+            return publicKey;
         }
 
-        public void setPubkey(String pubkey) {
-            this.pubkey = pubkey;
+        public void setPublicKey(String publicKey) {
+            this.publicKey = publicKey;
         }
 
         public String getSignature() {
@@ -266,29 +340,30 @@ public class BlockchainBlock implements Serializable {
             this.signature = signature;
         }
 
-        public String getUid() {
-            return uid;
+        public String getUserId() {
+            return userId;
         }
 
-        public void setUid(String uid) {
-            this.uid = uid;
+        public void setUserId(String uid) {
+            this.userId = uid;
         }
 
-        public long getTimestamp() {
-            return timestamp;
+
+        public String getBlockUid() {
+            return blockUid;
         }
 
-        public void setTimestamp(long timestamp) {
-            this.timestamp = timestamp;
+        public void setBlockUid(String blockUid) {
+            this.blockUid = blockUid;
         }
 
         @Override
         public String toString() {
             StringBuilder sb = new StringBuilder()
-                    .append(":").append(pubkey)
+                    .append(":").append(publicKey)
                     .append(":").append(signature)
-                    .append(":").append(timestamp)
-                    .append("").append(uid);
+                    .append(":").append(blockUid)
+                    .append("").append(userId);
 
             return sb.toString();
         }
@@ -297,24 +372,23 @@ public class BlockchainBlock implements Serializable {
     public static class Joiner extends Identity {
 
         private static final long serialVersionUID = 8448049949323699700L;
-        private String pubkey;
 
-        private String signature;
+        private String publicKey;
 
-        private String uid;
+        private String signature;
 
-        private long timestamp = -1;
+        private String userId;
 
-        private String number;
+        private String mBlockUid;
 
-        private String hash;
+        private String iBlockUid;
 
-        public String getPubkey() {
-            return pubkey;
+        public String getPublicKey() {
+            return publicKey;
         }
 
-        public void setPubkey(String pubkey) {
-            this.pubkey = pubkey;
+        public void setPublicKey(String pubkey) {
+            this.publicKey = pubkey;
         }
 
         public String getSignature() {
@@ -325,49 +399,183 @@ public class BlockchainBlock implements Serializable {
             this.signature = signature;
         }
 
-        public String getUid() {
-            return uid;
+        public String getUserId() {
+            return userId;
+        }
+
+        public void setUserId(String uid) {
+            this.userId = uid;
+        }
+
+        public String getMBlockUid() {
+            return mBlockUid;
         }
 
-        public void setUid(String uid) {
-            this.uid = uid;
+        public void setMBlockUid(String mBlockUid) {
+            this.mBlockUid = mBlockUid;
         }
 
-        public long getTimestamp() {
-            return timestamp;
+        public String getIBlockUid() {
+            return iBlockUid;
         }
 
-        public void setTimestamp(long timestamp) {
-            this.timestamp = timestamp;
+        public void setIBlockUid(String iBlockUid) {
+            this.iBlockUid = iBlockUid;
         }
 
-        public String getNumber() {
-            return number;
+        @Override
+        public String toString() {
+
+            StringBuilder sb = new StringBuilder()
+                    .append(":").append(publicKey)
+                    .append(":").append(signature)
+                    .append(":").append(mBlockUid)
+                    .append(":").append(iBlockUid)
+                    .append(":").append(userId);
+
+            return sb.toString();
         }
+    }
+
+
+    public static class Revoked implements Serializable {
+        private String signature;
+        private String userId;
 
-        public void setNumber(String number) {
-            this.number = number;
+        public String getSignature() {
+            return signature;
+        }
+        public void setSignature(String signature) {
+            this.signature = signature;
         }
 
-        public String getHash() {
-            return hash;
+        public String getUserId() {
+            return userId;
         }
 
-        public void setHash(String hash) {
-            this.hash = hash;
+        public void setUserId(String userId) {
+            this.userId = userId;
         }
 
         @Override
         public String toString() {
 
             StringBuilder sb = new StringBuilder()
-                    .append(":").append(pubkey)
                     .append(":").append(signature)
-                    .append(":").append(number)
-                    .append(":").append(hash)
-                    .append(":").append(timestamp)
-                    .append(":").append(uid);
+                    .append(":").append(userId);
+
+            return sb.toString();
+        }
+    }
+
+    public class Transaction implements Serializable {
+        private static final long serialVersionUID = 1L;
 
+        private String[] signatures;
+
+        private String version;
+
+        private String currency;
+
+        private String[] issuers;
+
+        private String[] inputs;
+
+        private String[] unlocks;
+
+        private String[] outputs;
+
+        public String[] getSignatures() {
+            return signatures;
+        }
+
+        public void setSignatures(String[] signatures) {
+            this.signatures = signatures;
+        }
+
+        public String getVersion() {
+            return version;
+        }
+
+        public void setVersion(String version) {
+            this.version = version;
+        }
+
+        public String getCurrency() {
+            return currency;
+        }
+
+        public void setCurrency(String currency) {
+            this.currency = currency;
+        }
+
+        public String[] getIssuers() {
+            return issuers;
+        }
+
+        public void setIssuers(String[] issuers) {
+            this.issuers = issuers;
+        }
+
+        public String[] getInputs() {
+            return inputs;
+        }
+
+        public void setInputs(String[] inputs) {
+            this.inputs = inputs;
+        }
+
+        public String[] getUnlocks() {
+            return unlocks;
+        }
+
+        public void setUnlocks(String[] unlocks) {
+            this.unlocks = unlocks;
+        }
+
+        public String[] getOutputs() {
+            return outputs;
+        }
+
+        public void setOutputs(String[] outputs) {
+            this.outputs = outputs;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append("\nsignatures:");
+            if (signatures != null) {
+                for (String e : signatures) {
+                    sb.append("\n\t").append(e);
+                }
+            }
+            sb.append("\nversion: ").append(version);
+            sb.append("\ncurrency: ").append(currency);
+            sb.append("\nissuers:");
+            if (issuers != null) {
+                for (String e : issuers) {
+                    sb.append("\n\t").append(e);
+                }
+            }
+            sb.append("\ninputs:");
+            if (inputs != null) {
+                for (String e : inputs) {
+                    sb.append("\n\t").append(e);
+                }
+            }
+            sb.append("\nunlocks:");
+            if (unlocks != null) {
+                for (String e : unlocks) {
+                    sb.append("\n\t").append(e);
+                }
+            }
+            sb.append("\noutputs:");
+            if (outputs != null) {
+                for (String e : outputs) {
+                    sb.append("\n\t").append(e);
+                }
+            }
             return sb.toString();
         }
     }
diff --git a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/BlockchainParameters.java b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/BlockchainParameters.java
index de3b0a8571dc9ab027989dfb1b5b98a9e2f68d87..7f30af3612cc730ef4dfaec90830366eed7aae39 100644
--- a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/BlockchainParameters.java
+++ b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/BlockchainParameters.java
@@ -53,27 +53,47 @@ public class BlockchainParameters implements Serializable{
     private Long ud0;
 
     /**
-     * Minimum delay between 2 identical certifications (same pubkeys)
+     * Minimum delay between 2 certifications of a same issuer, in seconds. Must be positive or zero.
      */
-    private Integer sigDelay;
+    private Integer sigPeriod;
 
     /**
-     * Maximum age of a valid signature (in seconds) (e.g. 2629800)
+     * Maximum quantity of active certifications made by member.
+     */
+    private Integer sigStock;
+
+    /**
+     * 	Maximum delay a certification can wait before being expired for non-writing.
+     */
+    private Integer sigWindow;
+
+    /**
+     * Maximum age of a active signature (in seconds) (e.g. 2629800)
      */
     private Integer sigValidity;
 
     /**
-     * Minimum quantity of signatures to be part of the WoT (e.g. 3)
+     * Minimum quantity of signatures to be part of the WoT(e.g. 3)
      */
     private Integer sigQty;
 
     /**
-     * Minimum quantity of valid made certifications to be part of the WoT for distance rule
+     * 	Maximum delay an identity can wait before being expired for non-writing.
+     */
+    private Integer idtyWindow;
+
+    /**
+     * Maximum delay a membership can wait before being expired for non-writing.
+     */
+    private Integer msWindow;
+
+    /**
+     * Minimum percent of sentries to reach to match the distance rule
      */
-    private Integer sigWoT;
+    private Double xpercent;
 
     /**
-     * Maximum age of a valid membership (in seconds)
+     * Maximum age of an active membership (in seconds)
      */
     private Integer msValidity;
 
@@ -139,14 +159,6 @@ public class BlockchainParameters implements Serializable{
         this.ud0 = ud0;
     }
 
-    public Integer getSigDelay() {
-        return sigDelay;
-    }
-
-    public void setSigDelay(Integer sigDelay) {
-        this.sigDelay = sigDelay;
-    }
-
     public Integer getSigValidity() {
         return sigValidity;
     }
@@ -163,13 +175,6 @@ public class BlockchainParameters implements Serializable{
         this.sigQty = sigQty;
     }
 
-    public Integer getSigWoT() {
-        return sigWoT;
-    }
-
-    public void setSigWoT(Integer sigWoT) {
-        this.sigWoT = sigWoT;
-    }
 
     public Integer getMsValidity() {
         return msValidity;
@@ -227,6 +232,54 @@ public class BlockchainParameters implements Serializable{
         this.percentRot = percentRot;
     }
 
+    public Integer getSigPeriod() {
+        return sigPeriod;
+    }
+
+    public void setSigPeriod(Integer sigPeriod) {
+        this.sigPeriod = sigPeriod;
+    }
+
+    public Integer getSigStock() {
+        return sigStock;
+    }
+
+    public void setSigStock(Integer sigStock) {
+        this.sigStock = sigStock;
+    }
+
+    public Integer getSigWindow() {
+        return sigWindow;
+    }
+
+    public void setSigWindow(Integer sigWindow) {
+        this.sigWindow = sigWindow;
+    }
+
+    public Integer getIdtyWindow() {
+        return idtyWindow;
+    }
+
+    public void setIdtyWindow(Integer idtyWindow) {
+        this.idtyWindow = idtyWindow;
+    }
+
+    public Integer getMsWindow() {
+        return msWindow;
+    }
+
+    public void setMsWindow(Integer msWindow) {
+        this.msWindow = msWindow;
+    }
+
+    public Double getXpercent() {
+        return xpercent;
+    }
+
+    public void setXpercent(Double xpercent) {
+        this.xpercent = xpercent;
+    }
+
     @Override
     public String toString() {
         return new StringBuilder()
@@ -234,10 +287,14 @@ public class BlockchainParameters implements Serializable{
                 .append("\nc=").append(c)
                 .append("\ndt=").append(dt)
                 .append("\nud0=").append(ud0)
-                .append("\nsigDelay=").append(sigDelay)
+                .append("\nsigPeriod=").append(sigPeriod)
+                .append("\nsigStock=").append(sigStock)
+                .append("\nsigWindow=").append(sigWindow)
                 .append("\nsigValidity=").append(sigValidity)
                 .append("\nsigQty=").append(sigQty)
-                .append("\nsigWoT=").append(sigWoT)
+                .append("\nidtyWindow=").append(idtyWindow)
+                .append("\nmsWindow=").append(msWindow)
+                .append("\nxpercent=").append(xpercent)
                 .append("\nmsValidity=").append(msValidity)
                 .append("\nstepMax=").append(stepMax)
                 .append("\nmedianTimeBlocks=").append(medianTimeBlocks)
diff --git a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/Error.java b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/Error.java
new file mode 100644
index 0000000000000000000000000000000000000000..37aaef759e42d077cb35415e5eba5b2a2a213827
--- /dev/null
+++ b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/Error.java
@@ -0,0 +1,35 @@
+package io.ucoin.ucoinj.core.client.model.bma;
+
+import java.io.Serializable;
+
+/**
+ * Created by blavenie on 31/03/16.
+ */
+public class Error implements Serializable {
+
+    private static final long serialVersionUID = -5598140972293478469L;
+
+    private int ucode;
+    private String message;
+
+    public int getUcode() {
+        return ucode;
+    }
+
+    public void setUcode(int ucode) {
+        this.ucode = ucode;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public String toString() {
+        return "ucode=" + ucode
+         + "\nmessage=" + message;
+    }
+}
diff --git a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/ErrorCode.java b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/ErrorCode.java
new file mode 100644
index 0000000000000000000000000000000000000000..a934c5b5320aaf35ebe4fcdeebae376bad28690a
--- /dev/null
+++ b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/ErrorCode.java
@@ -0,0 +1,10 @@
+package io.ucoin.ucoinj.core.client.model.bma;
+
+/**
+ * Created by blavenie on 31/03/16.
+ */
+public interface ErrorCode {
+
+    int UID_ALREADY_USED = 2002;
+    int MEMBERSHRIP_ALREADY_SEND = 2007;
+}
diff --git a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/NetworkPeering.java b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/NetworkPeering.java
index 30d5ce21b199c659ed76d2d4cca80f9c2202cae0..992b9a66b23ff42f46b8ed2c48e5b87c8f38e803 100644
--- a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/NetworkPeering.java
+++ b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/NetworkPeering.java
@@ -30,7 +30,6 @@ import java.io.Serializable;
 public class NetworkPeering implements Serializable {
     private String version;
     private String currency;
-    private String status;
     private String block;
     private String signature;
     // not need : private String raw
@@ -54,14 +53,6 @@ public class NetworkPeering implements Serializable {
         this.currency = currency;
     }
 
-    public String getStatus() {
-        return status;
-    }
-
-    public void setStatus(String status) {
-        this.status = status;
-    }
-
     public String getBlock() {
         return block;
     }
@@ -87,7 +78,8 @@ public class NetworkPeering implements Serializable {
     }
 
     public String toString() {
-        String s = "currency=" + currency + "\n" +
+        String s = "version=" + version + "\n" +
+                "currency=" + currency + "\n" +
                 "pubkey=" + pubkey + "\n" +
                 "signature=" + signature + "\n" +
                 "block=" + block + "\n";
diff --git a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/Protocol.java b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/Protocol.java
new file mode 100644
index 0000000000000000000000000000000000000000..8fe452de02905cd53580a4dfe72a13fe511f8586
--- /dev/null
+++ b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/Protocol.java
@@ -0,0 +1,15 @@
+package io.ucoin.ucoinj.core.client.model.bma;
+
+/**
+ * Created by blavenie on 31/03/16.
+ */
+public interface Protocol {
+
+    String VERSION = "2";
+
+    String TYPE_IDENTITY = "Identity";
+
+    String TYPE_MEMBERSHIP = "Membership";
+
+    String TYPE_TRANSACTION = "Transaction";
+}
diff --git a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/WotLookup.java b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/WotLookup.java
index 8d1f97201842658fc23a54e3b3e5c400ff7d47f2..5b98e37b8ede556cebb54fac1923f54ac9e4c66b 100644
--- a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/WotLookup.java
+++ b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/WotLookup.java
@@ -97,6 +97,8 @@ public class WotLookup {
         public String uid;
         public Meta meta;
         public String self;
+        public Boolean revoked;
+        public String revocation_sig;
         public OtherSignature[] others;
 
         public String getUid() {
@@ -130,12 +132,36 @@ public class WotLookup {
         public void setOthers(OtherSignature[] others) {
             this.others = others;
         }
+
+        public Boolean getRevoked() {
+            return revoked;
+        }
+
+        public void setRevoked(Boolean revoked) {
+            this.revoked = revoked;
+        }
+
+        public String getRevocationSig() {
+            return revocation_sig;
+        }
+
+        public void setRevocationSig(String revocationSig) {
+            this.revocation_sig = revocationSig;
+        }
     }
 
 
     public class Meta implements Serializable {
-        public Long timestamp;
+        public String timestamp;
         public Long block_number;
+
+        public String getTimestamp() {
+            return timestamp;
+        }
+
+        public void setTimestamp(String timestamp) {
+            this.timestamp = timestamp;
+        }
     }
 
     public class OtherSignature {
diff --git a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/gson/GsonUtils.java b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/gson/GsonUtils.java
index af9c432520c19973d51c72b1437cc09577f3ec3f..43a19179401a8ab324222802f583c413b79968b6 100644
--- a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/gson/GsonUtils.java
+++ b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/gson/GsonUtils.java
@@ -44,11 +44,11 @@ public class GsonUtils {
                 .setDateFormat(DATE_PATTERN)
                 // Register Multimap adapter
                 .registerTypeAdapter(Multimap.class, new MultimapTypeAdapter())
-                // Register Blockchain.identity adapter
+                // Register Blockchain.* adapter
                 .registerTypeAdapter(BlockchainBlock.Identity.class, new IdentityTypeAdapter())
-                // Register Blockchain.joiner adapter
                 .registerTypeAdapter(BlockchainBlock.Joiner.class, new JoinerTypeAdapter())
-                // Register endpoint adpater
+                .registerTypeAdapter(BlockchainBlock.Revoked.class, new RevokedTypeAdapter())
+                // Register endpoint adapter
                 .registerTypeAdapter(NetworkPeering.Endpoint.class, new EndpointAdapter())
                 ;
     }
diff --git a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/gson/IdentityTypeAdapter.java b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/gson/IdentityTypeAdapter.java
index 0f5c12c8a2a134655bea90642c40400749f0dce1..b69cee8b8dad923a4280a78168074ad05c9be306 100644
--- a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/gson/IdentityTypeAdapter.java
+++ b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/gson/IdentityTypeAdapter.java
@@ -46,10 +46,10 @@ public class IdentityTypeAdapter implements JsonDeserializer<BlockchainBlock.Ide
         BlockchainBlock.Identity result = new BlockchainBlock.Identity();
         int i = 0;
         
-        result.setPubkey(identityParts[i++]);
+        result.setPublicKey(identityParts[i++]);
         result.setSignature(identityParts[i++]);
-        result.setTimestamp(Integer.parseInt(identityParts[i++]));
-        result.setUid(identityParts[i++]);
+        result.setBlockUid(identityParts[i++]);
+        result.setUserId(identityParts[i++]);
 
         return result;
     }
@@ -57,10 +57,10 @@ public class IdentityTypeAdapter implements JsonDeserializer<BlockchainBlock.Ide
     @Override
     public JsonElement serialize(BlockchainBlock.Identity identity, Type type, JsonSerializationContext context) {
         String result = new StringBuilder()
-                .append(identity.getPubkey()).append(":")
+                .append(identity.getPublicKey()).append(":")
                 .append(identity.getSignature()).append(":")
-                .append(identity.getTimestamp()).append(":")
-                .append(identity.getUid()).toString();
+                .append(identity.getBlockUid()).append(":")
+                .append(identity.getUserId()).toString();
 
         return context.serialize(result.toString(), String.class);
     }
diff --git a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/gson/JoinerTypeAdapter.java b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/gson/JoinerTypeAdapter.java
index f1a0582a089ed9b33746adf0cb650eacff473bc2..66c90b2b99e5126bd9f026c286c13170dd7ff7c5 100644
--- a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/gson/JoinerTypeAdapter.java
+++ b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/gson/JoinerTypeAdapter.java
@@ -24,7 +24,6 @@ package io.ucoin.ucoinj.core.client.model.bma.gson;
 
 
 import com.google.gson.*;
-import io.ucoin.ucoinj.core.client.model.Member;
 import io.ucoin.ucoinj.core.client.model.bma.BlockchainBlock;
 import org.apache.commons.lang3.StringUtils;
 
@@ -40,19 +39,18 @@ public class JoinerTypeAdapter implements JsonDeserializer<BlockchainBlock.Joine
         }
         
         String[] identityParts = identityStr.split(":");
-        if (identityParts.length != 6) {
-            throw new JsonParseException(String.format("Bad format for BlockchainBlock.Identity. Should have 6 parts, but found %s.", identityParts.length));
+        if (identityParts.length != 5) {
+            throw new JsonParseException(String.format("Bad format for BlockchainBlock.Identity. Should have 5 parts, but found %s.", identityParts.length));
         }
 
         BlockchainBlock.Joiner result = new BlockchainBlock.Joiner();
         int i = 0;
         
-        result.setPubkey(identityParts[i++]);
+        result.setPublicKey(identityParts[i++]);
         result.setSignature(identityParts[i++]);
-        result.setNumber(identityParts[i++]);
-        result.setHash(identityParts[i++]);
-        result.setTimestamp(Integer.parseInt(identityParts[i++]));
-        result.setUid(identityParts[i++]);
+        result.setMBlockUid(identityParts[i++]);
+        result.setIBlockUid(identityParts[i++]);
+        result.setUserId(identityParts[i++]);
 
         return result;
     }
@@ -60,12 +58,11 @@ public class JoinerTypeAdapter implements JsonDeserializer<BlockchainBlock.Joine
     @Override
     public JsonElement serialize(BlockchainBlock.Joiner member, Type type, JsonSerializationContext context) {
         String result = new StringBuilder()
-                .append(member.getPubkey()).append(":")
+                .append(member.getPublicKey()).append(":")
                 .append(member.getSignature()).append(":")
-                .append(member.getNumber()).append(":")
-                .append(member.getHash()).append(":")
-                .append(member.getTimestamp()).append(":")
-                .append(member.getUid()).toString();
+                .append(member.getMBlockUid()).append(":")
+                .append(member.getIBlockUid()).append(":")
+                .append(member.getUserId()).toString();
 
         return context.serialize(result.toString(), String.class);
     }
diff --git a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/gson/RevokedTypeAdapter.java b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/gson/RevokedTypeAdapter.java
new file mode 100644
index 0000000000000000000000000000000000000000..1625b8110fa528992ccb8b89e405147c48f9c543
--- /dev/null
+++ b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/bma/gson/RevokedTypeAdapter.java
@@ -0,0 +1,63 @@
+package io.ucoin.ucoinj.core.client.model.bma.gson;
+
+/*
+ * #%L
+ * UCoin Java Client :: Core API
+ * %%
+ * Copyright (C) 2014 - 2015 EIS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the 
+ * License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public 
+ * License along with this program.  If not, see
+ * <http://www.gnu.org/licenses/gpl-3.0.html>.
+ * #L%
+ */
+
+
+import com.google.gson.*;
+import io.ucoin.ucoinj.core.client.model.bma.BlockchainBlock;
+import org.apache.commons.lang3.StringUtils;
+
+import java.lang.reflect.Type;
+
+public class RevokedTypeAdapter implements JsonDeserializer<BlockchainBlock.Revoked>, JsonSerializer<BlockchainBlock.Revoked>{
+
+    @Override
+    public BlockchainBlock.Revoked deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
+        String identityStr = json.getAsString();
+        if (StringUtils.isBlank(identityStr)) {
+            return null;
+        }
+        
+        String[] identityParts = identityStr.split(":");
+        if (identityParts.length != 4) {
+            throw new JsonParseException(String.format("Bad format for BlockchainBlock.Revoked. Should have 4 parts, but found %s.", identityParts.length));
+        }
+
+        BlockchainBlock.Revoked result = new BlockchainBlock.Revoked();
+        int i = 0;
+        
+        result.setSignature(identityParts[i++]);
+        result.setUserId(identityParts[i++]);
+
+        return result;
+    }
+
+    @Override
+    public JsonElement serialize(BlockchainBlock.Revoked input, Type type, JsonSerializationContext context) {
+        String result = new StringBuilder()
+                .append(input.getSignature()).append(":")
+                .append(input.getUserId()).toString();
+
+        return context.serialize(result.toString(), String.class);
+    }
+}
diff --git a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/local/Identity.java b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/local/Identity.java
index e9c326c62bc3885a2d74306f0b5db637d631670a..9aca1eac866b0d5bb3c8f0ba7ea3772f00acb5f9 100644
--- a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/local/Identity.java
+++ b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/local/Identity.java
@@ -29,21 +29,21 @@ public class Identity extends BasicIdentity {
 
     private static final long serialVersionUID = -7451079677730158794L;
 
-    private long timestamp = -1;
+    private String timestamp = null;
 
     private Boolean isMember = null;
 
     private Long currencyId;
 
     /**
-     * The timestamp value of the signature date
+     * The timestamp value of the signature date (a BLOCK_UID)
      * @return
      */
-    public long getTimestamp() {
+    public String getTimestamp() {
         return timestamp;
     }
 
-    public void setTimestamp(long timestamp) {
+    public void setTimestamp(String timestamp) {
         this.timestamp = timestamp;
     }
 
diff --git a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/local/Wallet.java b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/local/Wallet.java
index 089940923365ce6c6636f1a6bfae41b497264bd1..c84738c70bb87e86a3f2e6d14bf2df20295d768e 100644
--- a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/local/Wallet.java
+++ b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/model/local/Wallet.java
@@ -117,7 +117,7 @@ public class Wallet extends KeyPair implements LocalEntity, Serializable {
     }
 
     public boolean isSelfSend() {
-        return identity.getTimestamp() != -1;
+        return identity.getTimestamp() != null;
     }
 
     public Long getCurrencyId() {
@@ -174,11 +174,11 @@ public class Wallet extends KeyPair implements LocalEntity, Serializable {
         identity.setUid(uid);
     }
 
-    public long getCertTimestamp() {
+    public String getCertTimestamp() {
         return identity.getTimestamp();
     }
 
-    public void setCertTimestamp(long timestamp) {
+    public void setCertTimestamp(String timestamp) {
         identity.setTimestamp(timestamp);
     }
 
diff --git a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/HttpServiceImpl.java b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/HttpServiceImpl.java
index 730d6efefb25a7cefa4ee0e64283d4cf907663b1..e0ac4968ad9d1a5a24203579baa1d7135e694706 100644
--- a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/HttpServiceImpl.java
+++ b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/HttpServiceImpl.java
@@ -25,6 +25,7 @@ package io.ucoin.ucoinj.core.client.service;
 import com.google.gson.Gson;
 import io.ucoin.ucoinj.core.beans.InitializingBean;
 import io.ucoin.ucoinj.core.client.config.Configuration;
+import io.ucoin.ucoinj.core.client.model.bma.Error;
 import io.ucoin.ucoinj.core.client.model.bma.gson.GsonUtils;
 import io.ucoin.ucoinj.core.client.model.local.Peer;
 import io.ucoin.ucoinj.core.client.service.exception.HttpBadRequestException;
@@ -191,7 +192,13 @@ public class HttpServiceImpl implements HttpService, Closeable, InitializingBean
                 case HttpStatus.SC_FORBIDDEN:
                     throw new TechnicalException("ucoinj.client.authentication");
                 case HttpStatus.SC_BAD_REQUEST:
-                    throw new HttpBadRequestException("ucoinj.client.status" + response.getStatusLine().toString());
+                    try {
+                        Error error = (Error)parseResponse(response, Error.class);
+                        throw new HttpBadRequestException(error);
+                    }
+                    catch(IOException e) {
+                        throw new HttpBadRequestException("ucoinj.client.status" + response.getStatusLine().toString());
+                    }
                 default:
                     throw new TechnicalException("ucoinj.client.status" + response.getStatusLine().toString());
             }
diff --git a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/BaseRemoteServiceImpl.java b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/BaseRemoteServiceImpl.java
index a98d7ec809e9007add2198d075b723ade01a5044..5b9e9fc2a1dd2dee22ec3d2b3c422b62d46a769c 100644
--- a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/BaseRemoteServiceImpl.java
+++ b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/BaseRemoteServiceImpl.java
@@ -24,6 +24,7 @@ package io.ucoin.ucoinj.core.client.service.bma;
 
 import io.ucoin.ucoinj.core.beans.InitializingBean;
 import io.ucoin.ucoinj.core.beans.Service;
+import io.ucoin.ucoinj.core.client.model.bma.Protocol;
 import io.ucoin.ucoinj.core.client.model.local.Peer;
 import io.ucoin.ucoinj.core.client.service.HttpService;
 import io.ucoin.ucoinj.core.client.service.local.PeerService;
@@ -40,8 +41,6 @@ public abstract class BaseRemoteServiceImpl implements Service, InitializingBean
     protected HttpService httpService;
     protected PeerService peerService;
 
-    public static final String PROTOCOL_VERSION = "1";
-
     @Override
     public void afterPropertiesSet() {
         httpService = ServiceLocator.instance().getHttpService();
diff --git a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/BlockchainRemoteService.java b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/BlockchainRemoteService.java
index 75d0c6a850d6f995873aaec1baa469167a7dad35..77da05d82a4ab1b4a9267d29feb98124a296e2be 100644
--- a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/BlockchainRemoteService.java
+++ b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/BlockchainRemoteService.java
@@ -197,6 +197,8 @@ public interface BlockchainRemoteService extends Service {
      */
     void requestMembership(Wallet wallet);
 
+    void requestMembership(Peer peer, String currency, byte[] pubKey, byte[] secKey, String uid, String membershipBlockUid, String selfBlockUid);
+
     BlockchainMemberships getMembershipByPubkeyOrUid(long currencyId, String uidOrPubkey);
 
     BlockchainMemberships getMembershipByPubkeyOrUid(Peer peer, String uidOrPubkey);
diff --git a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/BlockchainRemoteServiceImpl.java b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/BlockchainRemoteServiceImpl.java
index a24867a817aacfa7454007647f350a8a8472038a..899c676fd0bebc3e4dbbc5b652fca0ff53f2d985 100644
--- a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/BlockchainRemoteServiceImpl.java
+++ b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/BlockchainRemoteServiceImpl.java
@@ -26,6 +26,7 @@ import io.ucoin.ucoinj.core.client.config.Configuration;
 import io.ucoin.ucoinj.core.client.model.bma.BlockchainBlock;
 import io.ucoin.ucoinj.core.client.model.bma.BlockchainMemberships;
 import io.ucoin.ucoinj.core.client.model.bma.BlockchainParameters;
+import io.ucoin.ucoinj.core.client.model.bma.Protocol;
 import io.ucoin.ucoinj.core.client.model.bma.gson.JsonArrayParser;
 import io.ucoin.ucoinj.core.client.model.local.Currency;
 import io.ucoin.ucoinj.core.client.model.local.Identity;
@@ -38,11 +39,11 @@ import io.ucoin.ucoinj.core.client.service.exception.UidAlreadyUsedException;
 import io.ucoin.ucoinj.core.client.service.exception.UidMatchAnotherPubkeyException;
 import io.ucoin.ucoinj.core.exception.TechnicalException;
 import io.ucoin.ucoinj.core.service.CryptoService;
-import io.ucoin.ucoinj.core.util.CollectionUtils;
 import io.ucoin.ucoinj.core.util.ObjectUtils;
 import io.ucoin.ucoinj.core.util.StringUtils;
 import io.ucoin.ucoinj.core.util.cache.Cache;
 import io.ucoin.ucoinj.core.util.cache.SimpleCache;
+import io.ucoin.ucoinj.core.util.crypto.CryptoUtils;
 import io.ucoin.ucoinj.core.util.websocket.WebsocketClientEndpoint;
 import org.apache.http.NameValuePair;
 import org.apache.http.client.entity.UrlEncodedFormEntity;
@@ -364,13 +365,14 @@ public class BlockchainRemoteServiceImpl extends BaseRemoteServiceImpl implement
     public void requestMembership(Wallet wallet) {
         ObjectUtils.checkNotNull(wallet);
         ObjectUtils.checkNotNull(wallet.getCurrencyId());
+        ObjectUtils.checkNotNull(wallet.getCertTimestamp());
 
         BlockchainBlock block = getCurrentBlock(wallet.getCurrencyId());
 
         // Compute membership document
         String membership = getMembership(wallet,
                 block,
-                true /*sideIn*/);
+                true /*side in*/);
 
         if (log.isDebugEnabled()) {
             log.debug(String.format(
@@ -396,6 +398,28 @@ public class BlockchainRemoteServiceImpl extends BaseRemoteServiceImpl implement
         executeRequest(httpPost, String.class);
     }
 
+
+    public void requestMembership(Peer peer, String currency, byte[] pubKey, byte[] secKey, String uid, String membershipBlockUid, String selfBlockUid) {
+        // http post /blockchain/membership
+        HttpPost httpPost = new HttpPost(getPath(peer, URL_MEMBERSHIP));
+
+        // compute the self-certification
+        String membership = getSignedMembership(currency, pubKey, secKey, uid, membershipBlockUid, selfBlockUid, true/*side in*/);
+
+        List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
+        urlParameters.add(new BasicNameValuePair("membership", membership));
+
+        try {
+            httpPost.setEntity(new UrlEncodedFormEntity(urlParameters));
+        }
+        catch(UnsupportedEncodingException e) {
+            throw new TechnicalException(e);
+        }
+
+        // Execute the request
+        executeRequest(httpPost, String.class);
+    }
+
     public BlockchainMemberships getMembershipByPubkeyOrUid(long currencyId, String uidOrPubkey) {
         String path = String.format(URL_MEMBERSHIP_SEARCH, uidOrPubkey);
 
@@ -428,13 +452,12 @@ public class BlockchainRemoteServiceImpl extends BaseRemoteServiceImpl implement
     ) {
 
         // Create the member ship document
-        String membership = getMembership(wallet.getUid(),
+        String membership = getUnsignedMembership( wallet.getCurrency(),
                 wallet.getPubKeyHash(),
-                wallet.getCurrency(),
-                block.getNumber(),
-                block.getHash(),
-                sideIn,
-                wallet.getCertTimestamp()
+                wallet.getUid(),
+                block.getNumber() + '-' + block.getHash(),
+                wallet.getCertTimestamp(),
+                sideIn
         );
 
         // Add signature
@@ -585,7 +608,7 @@ public class BlockchainRemoteServiceImpl extends BaseRemoteServiceImpl implement
 
                 // Self certification not exists: make sure the cert time is cleaning
                 else {
-                    identity.setTimestamp(-1);
+                    identity.setTimestamp(null);
                 }
             }
         }
@@ -593,7 +616,7 @@ public class BlockchainRemoteServiceImpl extends BaseRemoteServiceImpl implement
         // UID and pubkey is a member: fine
         else if (identity.getPubkey().equals(result.getPubkey())) {
             identity.setMember(true);
-            identity.setTimestamp(result.getSigDate());
+            //FIXME identity.setTimestamp(result.getSigDate());
         }
 
         // Something wrong on pubkey : uid already used by anither pubkey !
@@ -642,25 +665,52 @@ public class BlockchainRemoteServiceImpl extends BaseRemoteServiceImpl implement
         return result;
     }
 
-    private String getMembership(String uid,
-                                 String publicKey,
-                                 String currency,
-                                 long blockNumber,
-                                 String blockHash,
-                                 boolean sideIn,
-                                 long certificationTime
+    protected String getSignedMembership(String currency,
+                                      byte[] pubKey,
+                                      byte[] secKey,
+                                      String userId,
+                                      String membershipBlockUid,
+                                      String selfBlockUid,
+                                      boolean sideIn) {
+        // Compute the pub key hash
+        String pubKeyHash = CryptoUtils.encodeBase58(pubKey);
+
+        // Create the member ship document
+        String membership = getUnsignedMembership(currency,
+                pubKeyHash,
+                userId,
+                membershipBlockUid,
+                selfBlockUid,
+                sideIn
+        );
+
+        // Add signature
+        CryptoService cryptoService = ServiceLocator.instance().getCryptoService();
+        String signature = cryptoService.sign(membership, secKey);
+
+        return new StringBuilder().append(membership).append(signature)
+                .append('\n').toString();
+    }
+
+    protected String getUnsignedMembership(String currency,
+                                           String pubkey,
+                                           String userId,
+                                           String membershipBlockUid,
+                                           String selfBlockUid,
+                                           boolean sideIn
     ) {
-        StringBuilder result = new StringBuilder()
-                .append("Version: 1\n")
-                .append("Type: Membership\n")
-                .append("Currency: ").append(currency).append('\n')
-                .append("Issuer: ").append(publicKey).append('\n')
-                .append("Block: ").append(blockNumber).append('-').append(blockHash).append('\n')
-                .append("Membership: ").append(sideIn ? "IN" : "OUT").append('\n')
-                .append("UserID: ").append(uid).append('\n')
-                .append("CertTS: ").append(certificationTime).append('\n');
-
-        return result.toString();
+        // see https://github.com/ucoin-io/ucoin/blob/master/doc/Protocol.md#membership
+        return new StringBuilder()
+                .append("Version: ").append(Protocol.VERSION)
+                .append("\nType: ").append(Protocol.TYPE_MEMBERSHIP)
+                .append("\nCurrency: ").append(currency)
+                .append("\nIssuer: ").append(pubkey)
+                .append("\nBlock: ").append(membershipBlockUid)
+                .append("\nMembership: ").append(sideIn ? "IN" : "OUT")
+                .append("\nUserID: ").append(userId)
+                .append("\nCertTS: ").append(selfBlockUid)
+                .append("\n")
+                .toString();
     }
 
     private Integer getLastBlockNumberFromJson(final String json) {
diff --git a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/TransactionRemoteService.java b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/TransactionRemoteService.java
index 852226a67d8081e0f7c2a9f3eb90b16d6b72375c..4e0414ffb748e61b50bf35a7c9da15ed7892525f 100644
--- a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/TransactionRemoteService.java
+++ b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/TransactionRemoteService.java
@@ -33,8 +33,8 @@ import io.ucoin.ucoinj.core.client.service.exception.InsufficientCreditException
 
 public interface TransactionRemoteService extends Service {
 
-	String transfert(Wallet wallet, String destPubKey, long amount,
-							String comment) throws InsufficientCreditException;
+	String transfer(Wallet wallet, String destPubKey, long amount,
+                    String comment) throws InsufficientCreditException;
 
 	TxSource getSources(long currencyId, String pubKey);
 
diff --git a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/TransactionRemoteServiceImpl.java b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/TransactionRemoteServiceImpl.java
index 0354350abb2532bced9175b0afde0d09b7bc90bc..85a9f877bbafdfa56aa77d7f08a6bc76213f6598 100644
--- a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/TransactionRemoteServiceImpl.java
+++ b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/TransactionRemoteServiceImpl.java
@@ -24,6 +24,7 @@ package io.ucoin.ucoinj.core.client.service.bma;
 
 
 import io.ucoin.ucoinj.core.client.model.TxOutput;
+import io.ucoin.ucoinj.core.client.model.bma.Protocol;
 import io.ucoin.ucoinj.core.client.model.bma.TxHistory;
 import io.ucoin.ucoinj.core.client.model.bma.TxSource;
 import io.ucoin.ucoinj.core.client.model.local.Peer;
@@ -73,8 +74,8 @@ public class TransactionRemoteServiceImpl extends BaseRemoteServiceImpl implemen
         cryptoService = ServiceLocator.instance().getCryptoService();
 	}
 
-	public String transfert(Wallet wallet, String destPubKey, long amount,
-							String comment) throws InsufficientCreditException {
+	public String transfer(Wallet wallet, String destPubKey, long amount,
+						   String comment) throws InsufficientCreditException {
 		
 		// http post /tx/process
 		HttpPost httpPost = new HttpPost(
@@ -248,7 +249,8 @@ public class TransactionRemoteServiceImpl extends BaseRemoteServiceImpl implemen
 			String comments) {
 
 		StringBuilder sb = new StringBuilder();
-		sb.append("Version: 1\n").append("Type: Transaction\n")
+		sb.append("Version: ").append(Protocol.VERSION).append("\n")
+				.append("Type: ").append(Protocol.TYPE_TRANSACTION).append("\n")
 				.append("Currency: ").append(currency).append('\n')
 				.append("Issuers:\n")
 				// add issuer pubkey
@@ -264,6 +266,16 @@ public class TransactionRemoteServiceImpl extends BaseRemoteServiceImpl implemen
 					.append(input.getAmount()).append('\n');
 		}
 
+		// Unlocks
+		sb.append("Inputs:\n");
+		for (TxSource.Source input : inputs) {
+			// INDEX:SOURCE:NUMBER:FINGERPRINT:AMOUNT
+			sb.append(0).append(':').append(input.getType()).append(':')
+					.append(input.getNumber()).append(':')
+					.append(input.getFingerprint()).append(':')
+					.append(input.getAmount()).append('\n');
+		}
+
 		// Output
 		sb.append("Outputs:\n");
 		for (TxOutput output : outputs) {
@@ -286,7 +298,7 @@ public class TransactionRemoteServiceImpl extends BaseRemoteServiceImpl implemen
 		StringBuilder sb = new StringBuilder();
 		sb.append("TX:")
 				// VERSION
-				.append(PROTOCOL_VERSION).append(':')
+				.append(Protocol.VERSION).append(':')
 				// NB_ISSUERS
 				.append("1:")
 				// NB_INPUTS
diff --git a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/WotRemoteService.java b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/WotRemoteService.java
index 20c1dc98560a3d651a3258b5cf07478312a0e485..37f0b443ac9c55a6dfe41c7c6cc28af69c8489d4 100644
--- a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/WotRemoteService.java
+++ b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/WotRemoteService.java
@@ -62,22 +62,22 @@ public interface WotRemoteService extends Service {
     
     WotCertification getCertifiersOf(long currencyId, String uid);
 
-    String getSelfCertification(byte[] secKey, String uid, long timestamp);
+    String getSignedIdentity(String currency, byte[] pubKey, byte[] secKey, String uid, String blockUid);
 
-    void sendSelf(long currencyId, byte[] pubKey, byte[] secKey, String uid, long timestamp);
+    void sendIdentity(long currencyId, byte[] pubKey, byte[] secKey, String uid, String blockUid);
+
+    void sendIdentity(Peer peer, String currency, byte[] pubKey, byte[] secKey, String uid, String blockUid);
 
     String getCertification(byte[] pubKey, byte[] secKey, String userUid,
-                                   long userTimestamp,
-                                   String userSignature,
-                                   int blockNumber,
-                                   String blockHash);
+                                   String userTimestamp,
+                                   String userSignature);
 
     String sendCertification(Wallet wallet, Identity identity);
 
     String sendCertification(long currencyId,
                                     byte[] pubKey, byte[] secKey,
-                                  String uid, long timestamp,
+                                  String uid, String timestamp,
                                   String userUid, String userPubKeyHash,
-                                  long userTimestamp, String userSignature);
+                             String userTimestamp, String userSignature);
 
 }
diff --git a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/WotRemoteServiceImpl.java b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/WotRemoteServiceImpl.java
index 764b89eabe774b9ad6c4ffd59c8c442a7249960d..3ef399ca621e6c846f0f3461858b59e6df456544 100644
--- a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/WotRemoteServiceImpl.java
+++ b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/bma/WotRemoteServiceImpl.java
@@ -23,15 +23,13 @@ package io.ucoin.ucoinj.core.client.service.bma;
  */
 
 import io.ucoin.ucoinj.core.client.model.ModelUtils;
-import io.ucoin.ucoinj.core.client.model.bma.WotCertification;
-import io.ucoin.ucoinj.core.client.model.bma.BlockchainBlock;
-import io.ucoin.ucoinj.core.client.model.bma.BlockchainParameters;
-import io.ucoin.ucoinj.core.client.model.bma.WotLookup;
+import io.ucoin.ucoinj.core.client.model.bma.*;
 import io.ucoin.ucoinj.core.client.model.local.Certification;
 import io.ucoin.ucoinj.core.client.model.local.Identity;
 import io.ucoin.ucoinj.core.client.model.local.Peer;
 import io.ucoin.ucoinj.core.client.model.local.Wallet;
 import io.ucoin.ucoinj.core.client.service.ServiceLocator;
+import io.ucoin.ucoinj.core.client.service.local.CurrencyService;
 import io.ucoin.ucoinj.core.exception.TechnicalException;
 import io.ucoin.ucoinj.core.service.CryptoService;
 import io.ucoin.ucoinj.core.util.CollectionUtils;
@@ -71,6 +69,7 @@ public class WotRemoteServiceImpl extends BaseRemoteServiceImpl implements WotRe
 
     private CryptoService cryptoService;
     private BlockchainRemoteService bcService;
+    private CurrencyService currencyService;
 
     public WotRemoteServiceImpl() {
         super();
@@ -81,6 +80,7 @@ public class WotRemoteServiceImpl extends BaseRemoteServiceImpl implements WotRe
         super.afterPropertiesSet();
         cryptoService = ServiceLocator.instance().getCryptoService();
         bcService = ServiceLocator.instance().getBlockchainRemoteService();
+        currencyService = ServiceLocator.instance().getCurrencyService();
     }
 
     public List<Identity> findIdentities(Set<Long> currenciesIds, String uidOrPubKey) {
@@ -282,20 +282,38 @@ public class WotRemoteServiceImpl extends BaseRemoteServiceImpl implements WotRe
     }
 
 
-    public void sendSelf(long currencyId, byte[] pubKey, byte[] secKey, String uid, long timestamp) {
+    public void sendIdentity(long currencyId, byte[] pubKey, byte[] secKey, String userId, String blockUid) {
         // http post /wot/add
         HttpPost httpPost = new HttpPost(getPath(currencyId, URL_ADD));
 
-        // Compute the pub key hash
-        String pubKeyHash = CryptoUtils.encodeBase58(pubKey);
+        String currency = currencyService.getCurrencyNameById(currencyId);
+
+        // compute the self-certification
+        String identity = getSignedIdentity(currency, pubKey, secKey, userId, blockUid);
+
+        List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
+        urlParameters.add(new BasicNameValuePair("identity", identity));
+
+        try {
+            httpPost.setEntity(new UrlEncodedFormEntity(urlParameters));
+        }
+        catch(UnsupportedEncodingException e) {
+            throw new TechnicalException(e);
+        }
+
+        // Execute the request
+        executeRequest(httpPost, String.class);
+    }
+
+    public void sendIdentity(Peer peer, String currency, byte[] pubKey, byte[] secKey, String uid, String blockUid) {
+        // http post /wot/add
+        HttpPost httpPost = new HttpPost(getPath(peer, URL_ADD));
 
         // compute the self-certification
-        String selfCertification = getSelfCertification(secKey, uid, timestamp);
+        String identity = getSignedIdentity(currency, pubKey, secKey, uid, blockUid);
 
         List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
-        urlParameters.add(new BasicNameValuePair("pubkey", pubKeyHash));
-        urlParameters.add(new BasicNameValuePair("self", selfCertification));
-        urlParameters.add(new BasicNameValuePair("other", ""));
+        urlParameters.add(new BasicNameValuePair("identity", identity));
 
         try {
             httpPost.setEntity(new UrlEncodedFormEntity(urlParameters));
@@ -324,9 +342,9 @@ public class WotRemoteServiceImpl extends BaseRemoteServiceImpl implements WotRe
 
     public String sendCertification(long currencyId,
                                     byte[] pubKey, byte[] secKey,
-                                  String uid, long timestamp,
+                                  String uid, String timestamp,
                                   String userUid, String userPubKeyHash,
-                                  long userTimestamp, String userSignature) {
+                                  String userBlockUid, String userSignature) {
         // http post /wot/add
         HttpPost httpPost = new HttpPost(getPath(currencyId, URL_ADD));
 
@@ -341,18 +359,19 @@ public class WotRemoteServiceImpl extends BaseRemoteServiceImpl implements WotRe
         // Compute the pub key hash
         String pubKeyHash = CryptoUtils.encodeBase58(pubKey);
 
-        // compute the self-certification
-        String selfCertification = getSelfCertification(userUid, userTimestamp, userSignature);
+        // compute signed identity
+        String identity = getIdentity(currentBlock.getCurrency(),
+                pubKeyHash, userUid, userBlockUid, userSignature);
 
         // Compute the certification
-        String certification = getCertification(pubKey, secKey,
-                userUid, userTimestamp, userSignature,
-                blockNumber, blockHash);
+        String certification = null; /* FIXME getCertification(pubKey, secKey,
+                userUid, userBlockUid, userSignature,
+                blockNumber, blockHash);*/
         String inlineCertification = toInlineCertification(pubKeyHash, userPubKeyHash, certification);
 
         List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
-        urlParameters.add(new BasicNameValuePair("pubkey", userPubKeyHash));
-        urlParameters.add(new BasicNameValuePair("self", selfCertification));
+        urlParameters.add(new BasicNameValuePair("identity", identity));
+        urlParameters.add(new BasicNameValuePair("self", identity));
         urlParameters.add(new BasicNameValuePair("other", inlineCertification));
 
         try {
@@ -403,26 +422,23 @@ public class WotRemoteServiceImpl extends BaseRemoteServiceImpl implements WotRe
 
         target.setUid(source.getUid());
         target.setSelf(source.getSelf());
-        Long timestamp = source.getMeta() != null ? source.getMeta().timestamp : null;
-        target.setTimestamp(timestamp);
+        String timestamp = source.getMeta() != null ? source.getMeta().timestamp : null;
+        //FIXME target.setTimestamp(timestamp);
     }
 
-    public String getSelfCertification(byte[] secKey, String uid, long timestamp) {
-        // Create the self part to sign
-        StringBuilder buffer = new StringBuilder()
-                .append("UID:")
-                .append(uid)
-                .append("\nMETA:TS:")
-                .append(timestamp)
-                .append('\n');
+    public String getSignedIdentity(String currency, byte[] pubKey, byte[] secKey, String uid, String blockUid) {
+
+        // Compute the pub key hash
+        String pubKeyHash = CryptoUtils.encodeBase58(pubKey);
+
+        // Create identity to sign
+        String unsignedIdentity = getUnsignedIdentity(currency, pubKeyHash, uid, blockUid);
 
         // Compute the signature
-        String signature = cryptoService.sign(buffer.toString(), secKey);
+        String signature = cryptoService.sign(unsignedIdentity, secKey);
 
         // Append the signature
-        return buffer.append(signature)
-                .append('\n')
-                .toString();
+        return unsignedIdentity + signature + '\n';
     }
 
     /* -- Internal methods -- */
@@ -449,7 +465,7 @@ public class WotRemoteServiceImpl extends BaseRemoteServiceImpl implements WotRe
                 cert.setCertifiedBy(false);
                 result.add(cert);
 
-                long certificationAge = medianTime - certifier.getTimestamp();
+                /*FIXME long certificationAge = medianTime - certifier.getTimestamp();
                 if(certificationAge <= sigValidity) {
                     if (certifier.getIsMember() != null && certifier.getIsMember().booleanValue()
                             && certifier.getWritten()!=null && certifier.getWritten().getNumber()>=0) {
@@ -459,7 +475,7 @@ public class WotRemoteServiceImpl extends BaseRemoteServiceImpl implements WotRe
                 }
                 else {
                     cert.setValid(false);
-                }
+                }*/
             }
         }
 
@@ -488,12 +504,15 @@ public class WotRemoteServiceImpl extends BaseRemoteServiceImpl implements WotRe
                     cert.setCertifiedBy(true);
                     result.add(cert);
 
+                    // FIXME
+                    /*
                     long certificationAge = medianTime - certifiedBy.getTimestamp();
                     if (certificationAge <= sigValidity) {
                         cert.setValid(true);
                     } else {
                         cert.setValid(false);
                     }
+                    */
                 }
             }
 
@@ -596,13 +615,11 @@ public class WotRemoteServiceImpl extends BaseRemoteServiceImpl implements WotRe
     }
 
     public String getCertification(byte[] pubKey, byte[] secKey, String userUid,
-                                   long userTimestamp,
-                                   String userSignature,
-                                   int blockNumber,
-                                   String blockHash) {
+                                   String userTimestamp,
+                                   String userSignature) {
         // Create the self part to sign
         String unsignedCertification = getCertificationUnsigned(
-                userUid, userTimestamp, userSignature, blockNumber, blockHash);
+                userUid, userTimestamp, userSignature);
 
         // Compute the signature
         String signature = cryptoService.sign(unsignedCertification, secKey);
@@ -616,10 +633,8 @@ public class WotRemoteServiceImpl extends BaseRemoteServiceImpl implements WotRe
     }
 
     protected String getCertificationUnsigned(String userUid,
-                                      long userTimestamp,
-                                      String userSignature,
-                                      int blockNumber,
-                                      String blockHash) {
+                                      String userTimestamp,
+                                      String userSignature) {
         // Create the self part to sign
         return new StringBuilder()
                 .append("UID:")
@@ -628,29 +643,38 @@ public class WotRemoteServiceImpl extends BaseRemoteServiceImpl implements WotRe
                 .append(userTimestamp)
                 .append('\n')
                 .append(userSignature)
-                .append("\nMETA:TS:")
+                /*.append("\nMETA:TS:")
                 .append(blockNumber)
                 .append('-')
-                .append(blockHash)
+                .append(blockHash)*/
                 .append('\n').toString();
     }
 
-    protected String getSelfCertification(String uid,
-                                              long timestamp,
-                                              String signature) {
-        // Create the self part to sign
+    protected String getUnsignedIdentity(String currency,
+                                         String pubkey,
+                                         String userId,
+                                         String blockUid) {
+        // see https://github.com/ucoin-io/ucoin/blob/master/doc/Protocol.md#identity
         return new StringBuilder()
-                .append("UID:")
-                .append(uid)
-                .append("\nMETA:TS:")
-                .append(timestamp)
-                .append('\n')
-                .append(signature)
-                // FIXME : in ucoin, no '\n' here - is it a bug ?
-                //.append('\n')
+                .append("Version: ").append(Protocol.VERSION)
+                .append("\nType: ").append(Protocol.TYPE_IDENTITY)
+                .append("\nCurrency: ").append(currency)
+                .append("\nIssuer: ").append(pubkey)
+                .append("\nUniqueID: ").append(userId)
+                .append("\nTimestamp: ").append(blockUid)
+                .append("\n")
                 .toString();
     }
 
+    protected String getIdentity(String currency,
+                                         String pubkey,
+                                         String userId,
+                                         String blockUid,
+                                         String signature) {
+        return getUnsignedIdentity(currency, pubkey, userId, blockUid)
+                + "\n" + signature;
+    }
+
     protected WotLookup.Uid getUid(WotLookup lookupResults, String filterUid) {
         if (lookupResults.getResults() == null || lookupResults.getResults().length == 0) {
             return null;
@@ -762,9 +786,9 @@ public class WotRemoteServiceImpl extends BaseRemoteServiceImpl implements WotRe
         if (source.meta != null) {
 
             // timestamp
-            Long timestamp = source.meta != null ? source.meta.timestamp : null;
+            String timestamp = source.meta != null ? source.meta.timestamp : null;
             if (timestamp != null) {
-                target.setTimestamp(timestamp.longValue());
+                //FIXME target.setTimestamp(timestamp.longValue());
             }
         }
 
@@ -858,4 +882,5 @@ public class WotRemoteServiceImpl extends BaseRemoteServiceImpl implements WotRe
             previousCert.setTimestamp(cert.getTimestamp());
         }
     }
+
 }
diff --git a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/exception/HttpBadRequestException.java b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/exception/HttpBadRequestException.java
index b96c7255a14acb05c3282160b3bf93d4624bb563..32cf18ad670badb1516e40ba87059f4212c78235 100644
--- a/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/exception/HttpBadRequestException.java
+++ b/ucoinj-core-client/src/main/java/io/ucoin/ucoinj/core/client/service/exception/HttpBadRequestException.java
@@ -22,6 +22,7 @@ package io.ucoin.ucoinj.core.client.service.exception;
  * #L%
  */
 
+import io.ucoin.ucoinj.core.client.model.bma.Error;
 import io.ucoin.ucoinj.core.exception.TechnicalException;
 
 /**
@@ -43,7 +44,13 @@ public class HttpBadRequestException extends TechnicalException{
         super(message);
     }
 
+    public HttpBadRequestException(Error error) {
+        super(error.getMessage());
+        setCode(error.getUcode());
+    }
+
     public HttpBadRequestException(Throwable cause) {
         super(cause);
     }
+
 }
diff --git a/ucoinj-core-client/src/test/java/io/ucoin/ucoinj/core/client/service/bma/BlockchainRemoteServiceTest.java b/ucoinj-core-client/src/test/java/io/ucoin/ucoinj/core/client/service/bma/BlockchainRemoteServiceTest.java
index 9684b0844f290ff3ff2e05f31232ef8382aa61c2..966730bc4947213638e379b8ecf2a6e27f6ec542 100644
--- a/ucoinj-core-client/src/test/java/io/ucoin/ucoinj/core/client/service/bma/BlockchainRemoteServiceTest.java
+++ b/ucoinj-core-client/src/test/java/io/ucoin/ucoinj/core/client/service/bma/BlockchainRemoteServiceTest.java
@@ -27,13 +27,15 @@ import com.google.gson.Gson;
 import com.google.gson.JsonSyntaxException;
 import io.ucoin.ucoinj.core.client.TestResource;
 import io.ucoin.ucoinj.core.client.config.Configuration;
-import io.ucoin.ucoinj.core.client.model.BasicIdentity;
 import io.ucoin.ucoinj.core.client.model.bma.BlockchainBlock;
 import io.ucoin.ucoinj.core.client.model.bma.BlockchainParameters;
-import io.ucoin.ucoinj.core.client.model.Member;
+import io.ucoin.ucoinj.core.client.model.bma.ErrorCode;
 import io.ucoin.ucoinj.core.client.model.bma.gson.GsonUtils;
 import io.ucoin.ucoinj.core.client.model.local.Peer;
+import io.ucoin.ucoinj.core.client.model.local.Wallet;
 import io.ucoin.ucoinj.core.client.service.ServiceLocator;
+import io.ucoin.ucoinj.core.client.service.exception.HttpBadRequestException;
+import io.ucoin.ucoinj.core.util.crypto.CryptoUtils;
 import io.ucoin.ucoinj.core.util.websocket.WebsocketClientEndpoint;
 import org.junit.*;
 import org.slf4j.Logger;
@@ -63,6 +65,8 @@ public class BlockchainRemoteServiceTest {
 
         Assert.assertNotNull(result);
         Assert.assertNotNull(result.getCurrency());
+
+        Assert.assertEquals(resource.getFixtures().getCurrency(), result.getCurrency());
     }
     
     @Test
@@ -74,11 +78,11 @@ public class BlockchainRemoteServiceTest {
         Assert.assertNotNull(result.getCurrency());
         
         for (BlockchainBlock.Identity id: result.getIdentities()) {
-            Assert.assertNotNull(id.getUid());
+            Assert.assertNotNull(id.getUserId());
         }
         
         for (BlockchainBlock.Joiner id: result.getJoiners()) {
-            Assert.assertNotNull(id.getUid());
+            Assert.assertNotNull(id.getUserId());
         }
     }
 
@@ -128,6 +132,30 @@ public class BlockchainRemoteServiceTest {
         }
     }
 
+
+    @Test
+    public void requestMembership() throws Exception {
+        Peer peer = createTestPeer();
+        Wallet wallet = createTestWallet();
+        String uid = resource.getFixtures().getUid();
+        String currency = resource.getFixtures().getCurrency();
+        String selfIdentityBlockUid = resource.getFixtures().getSelfIdentityBlockUid();
+
+        // Get the block UID
+        BlockchainRemoteService blockchainRemoteService = ServiceLocator.instance().getBlockchainRemoteService();
+        BlockchainBlock currentBlock = blockchainRemoteService.getCurrentBlock(peer);
+        Assume.assumeNotNull(currentBlock);
+        String blockUid = currentBlock.getNumber() + "-" + currentBlock.getHash();
+
+        try {
+            service.requestMembership(peer, currency, wallet.getPubKey(), wallet.getSecKey(), uid, blockUid, selfIdentityBlockUid);
+        }
+        catch(HttpBadRequestException e) {
+            Assert.assertEquals(ErrorCode.MEMBERSHRIP_ALREADY_SEND, e.getCode());
+
+        }
+    }
+
     /* -- Internal methods -- */
 
     protected Peer createTestPeer() {
@@ -137,4 +165,14 @@ public class BlockchainRemoteServiceTest {
 
         return peer;
     }
+
+    protected Wallet createTestWallet() {
+        Wallet wallet = new Wallet(
+                resource.getFixtures().getCurrency(),
+                resource.getFixtures().getUid(),
+                CryptoUtils.decodeBase58(resource.getFixtures().getUserPublicKey()),
+                CryptoUtils.decodeBase58(resource.getFixtures().getUserSecretKey()));
+
+        return wallet;
+    }
 }
diff --git a/ucoinj-core-client/src/test/java/io/ucoin/ucoinj/core/client/service/bma/TransactionRemoteServiceTest.java b/ucoinj-core-client/src/test/java/io/ucoin/ucoinj/core/client/service/bma/TransactionRemoteServiceTest.java
index 7c93d5196fd95f529a03f23979fb5c41310799d0..5b3dfdd8395b95ec579ba783c6cdb8d8dff397c8 100644
--- a/ucoinj-core-client/src/test/java/io/ucoin/ucoinj/core/client/service/bma/TransactionRemoteServiceTest.java
+++ b/ucoinj-core-client/src/test/java/io/ucoin/ucoinj/core/client/service/bma/TransactionRemoteServiceTest.java
@@ -52,10 +52,9 @@ public class TransactionRemoteServiceTest {
 	}
 
 	@Test
-	public void transfert() throws Exception {
+	public void transfer() throws Exception {
 
-		
-		service.transfert(
+		service.transfer(
 				createTestWallet(),
 				resource.getFixtures().getOtherUserPublicKey(),
 				1,
diff --git a/ucoinj-core-client/src/test/java/io/ucoin/ucoinj/core/client/service/bma/WotRemoteServiceTest.java b/ucoinj-core-client/src/test/java/io/ucoin/ucoinj/core/client/service/bma/WotRemoteServiceTest.java
index 4910902ddc245ba18bed8897f60781ae69c2d8d0..487e47b72c3b71ed82817d5527299108b258ee35 100644
--- a/ucoinj-core-client/src/test/java/io/ucoin/ucoinj/core/client/service/bma/WotRemoteServiceTest.java
+++ b/ucoinj-core-client/src/test/java/io/ucoin/ucoinj/core/client/service/bma/WotRemoteServiceTest.java
@@ -25,20 +25,16 @@ package io.ucoin.ucoinj.core.client.service.bma;
 
 import io.ucoin.ucoinj.core.client.TestResource;
 import io.ucoin.ucoinj.core.client.config.Configuration;
-import io.ucoin.ucoinj.core.client.model.BasicIdentity;
-import io.ucoin.ucoinj.core.client.model.bma.WotCertification;
-import io.ucoin.ucoinj.core.client.model.bma.WotLookup;
+import io.ucoin.ucoinj.core.client.model.bma.*;
 import io.ucoin.ucoinj.core.client.model.local.Identity;
 import io.ucoin.ucoinj.core.client.model.local.Peer;
 import io.ucoin.ucoinj.core.client.model.local.Wallet;
 import io.ucoin.ucoinj.core.client.service.ServiceLocator;
+import io.ucoin.ucoinj.core.client.service.exception.HttpBadRequestException;
 import io.ucoin.ucoinj.core.util.CollectionUtils;
 import io.ucoin.ucoinj.core.util.crypto.CryptoUtils;
 import io.ucoin.ucoinj.core.util.crypto.SecretBox;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
+import org.junit.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -134,51 +130,24 @@ public class WotRemoteServiceTest {
 	}
 
 	@Test
-	public void sendSelf() throws Exception {
-
-		SecretBox secretBox = createSecretBox();
-
-		String uid = resource.getFixtures().getUid();
-		long timestamp = resource.getFixtures().getSelfTimestamp();
-		Wallet wallet = createTestWallet();
-
-		String selfCertification = service.getSelfCertification(
-				wallet.getSecKey(),
-				wallet.getUid(),
-				timestamp);
-
-		String expectedCertification = String.format(
-				"UID:%s\nMETA:TS:%s\n%s\n", uid, timestamp, resource
-						.getFixtures().getSelfSignature());
-
-		Assert.assertEquals(expectedCertification, selfCertification);
-	}
-
-	@Test
-	public void getCertification() throws Exception {
-
-		Wallet wallet = createTestWallet();
-
-		String userUid = "kimamila";
-		long userTimestamp = 1418377981;
-		String userSelf = "pVO6YMhZMl5pPxa33hpFCNljIZ0fO6HMPp9d+uW+DVT4DJXP+tQ5XzLfvOaT3uH+3Slx3BiuH/fADleSp873Cg==";
-		int blockNumber = 3328;
-		String blockHash = "0837171AD6CE72B7DAD0409A230D43A9CCFFE0DC";
-
-		String selfCertification = service.getCertification(wallet.getPubKey(),
-				wallet.getSecKey(), userUid,
-				userTimestamp, userSelf, blockNumber, blockHash);
-
-		String expectedCertification = String
-				.format("UID:%s\nMETA:TS:%s\n%s\nMETA:TS:%s-%s\n%s\n",
-						userUid,
-						userTimestamp,
-						userSelf,
-						blockNumber,
-						blockHash,
-						"wOAbhxPzlnwmKgMXirPjxNno5tsHN95KMSUrVrZSLPcXn69cFg6ZbiWpSKVSFcHVVuZ4rhRvi46RFvVT/yFuDA==");
-
-		Assert.assertEquals(expectedCertification, selfCertification);
+	public void sendIdentity() throws Exception {
+        Peer peer = createTestPeer();
+        Wallet wallet = createTestWallet();
+        String uid = resource.getFixtures().getUid();
+        String currency = resource.getFixtures().getCurrency();
+
+        // Get the block UID
+        BlockchainRemoteService blockchainRemoteService = ServiceLocator.instance().getBlockchainRemoteService();
+        BlockchainBlock currentBlock = blockchainRemoteService.getCurrentBlock(peer);
+        Assume.assumeNotNull(currentBlock);
+        String blockUid = currentBlock.getNumber() + "-" + currentBlock.getHash();
+
+        try {
+            service.sendIdentity(peer, currency, wallet.getPubKey(), wallet.getSecKey(), uid, blockUid);
+        }
+        catch(HttpBadRequestException e) {
+            Assert.assertEquals(ErrorCode.UID_ALREADY_USED, e.getCode());
+        }
 	}
 
 	/* -- internal methods */
@@ -193,12 +162,11 @@ public class WotRemoteServiceTest {
 		return wallet;
 	}
 
-	protected SecretBox createSecretBox() {
-		String salt = resource.getFixtures().getUserSalt();
-		String password = resource.getFixtures().getUserPassword();
-		SecretBox secretBox = new SecretBox(salt, password);
+	protected Peer createTestPeer() {
+		Peer peer = new Peer(
+				Configuration.instance().getNodeHost(),
+				Configuration.instance().getNodePort());
 
-		return secretBox;
+		return peer;
 	}
-
 }
diff --git a/ucoinj-core-client/src/test/resources/ucoinj-core-client-test.properties b/ucoinj-core-client/src/test/resources/ucoinj-core-client-test.properties
index 0774f09e68a257a381edb39debc29254a00018dd..935715198000eb25cd750d3e407c66c67c7a4e97 100644
--- a/ucoinj-core-client/src/test/resources/ucoinj-core-client-test.properties
+++ b/ucoinj-core-client/src/test/resources/ucoinj-core-client-test.properties
@@ -1,7 +1,12 @@
 #ucoinj.node.host=metab.ucoin.io
 #ucoinj.node.host=metab.ucoin.fr
-ucoinj.node.host=192.168.0.28
-ucoinj.node.port=9201
+
+#ucoinj.node.host=192.168.0.28
+#ucoinj.node.port=9201
+
+ucoinj.node.host=twiced.fr
+ucoinj.node.port=9330
+
 
 ucoinj.node.elasticsearch.host=localhost
 ucoinj.node.elasticsearch.port=9200
diff --git a/ucoinj-core-shared/src/main/java/io/ucoin/ucoinj/core/exception/TechnicalException.java b/ucoinj-core-shared/src/main/java/io/ucoin/ucoinj/core/exception/TechnicalException.java
index ef8d644ea8caf7472d2b2f8a0165810176182e95..ab430c542aabc4013c6521533316f8f9b33deb02 100644
--- a/ucoinj-core-shared/src/main/java/io/ucoin/ucoinj/core/exception/TechnicalException.java
+++ b/ucoinj-core-shared/src/main/java/io/ucoin/ucoinj/core/exception/TechnicalException.java
@@ -33,6 +33,16 @@ public class TechnicalException extends RuntimeException{
 
     private static final long serialVersionUID = -6715624222174163366L;
 
+    private int code;
+
+    public int getCode() {
+        return code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
     public TechnicalException() {
         super();
     }
diff --git a/ucoinj-core-shared/src/main/java/io/ucoin/ucoinj/core/test/TestFixtures.java b/ucoinj-core-shared/src/main/java/io/ucoin/ucoinj/core/test/TestFixtures.java
index 7649583e4fb2be6b8ef6f1833326560de7a095d8..8ec6f536ef0aa4ffb6a44e9003e53360c7621216 100644
--- a/ucoinj-core-shared/src/main/java/io/ucoin/ucoinj/core/test/TestFixtures.java
+++ b/ucoinj-core-shared/src/main/java/io/ucoin/ucoinj/core/test/TestFixtures.java
@@ -27,11 +27,11 @@ package io.ucoin.ucoinj.core.test;
 public class TestFixtures {
 
 	public String getCurrency() {
-        return "meta_brouzouf";
+        return "super_currency";
     }
 	
     public String getUid() {
-        return "cgeek";
+        return "abc";
     }
 
     public String getUserSalt() {
@@ -70,15 +70,15 @@ public class TestFixtures {
     }
     
     /**
-     * A signature, that corespond to getSelfTimestamp(), getUid()
+     * A signature, that correspond to self identity
      * @return
      */
-    public String getSelfSignature() {
-    	return "TMgQysT7JwY8XwemskwWb8LBDJybLUsnxqaaUvSteIYpOxRiB92gkFQQcGpBwq4hAwhEiqBAiFkiXIozppDDDg==";
+    public String getSelfIdentitySignature() {
+    	return "sBawDbMdsUYFf1z4i/3sXC4kuVnLLy2aTpcY3BdfpzhX/DFOPxcCyq95D+lTed1Cuv7Ey+0KRSWMUcKnIZQ+BA==";
     }
     
-    public long getSelfTimestamp() {
-    	return 1420881879;
+    public String getSelfIdentityBlockUid() {
+    	return "10169-00072A7870BDA66FA3BA8F102933C24EB591A15D789000AD8150F0FE476733D7";
     }
     
     /**
diff --git a/ucoinj-elasticsearch-plugin/src/main/java/io/ucoin/ucoinj/elasticsearch/action/RestModule.java b/ucoinj-elasticsearch-plugin/src/main/java/io/ucoin/ucoinj/elasticsearch/action/RestModule.java
index 52a958d971812c2b7273be7566509017638ff262..1433bf1be26cb2d5c0ef6adb8281378b512fc02b 100644
--- a/ucoinj-elasticsearch-plugin/src/main/java/io/ucoin/ucoinj/elasticsearch/action/RestModule.java
+++ b/ucoinj-elasticsearch-plugin/src/main/java/io/ucoin/ucoinj/elasticsearch/action/RestModule.java
@@ -23,7 +23,8 @@ package io.ucoin.ucoinj.elasticsearch.action;
  */
 
 import io.ucoin.ucoinj.elasticsearch.action.currency.RestCurrencyIndexAction;
-import io.ucoin.ucoinj.elasticsearch.action.market.RestMarketRecordIndexAction;
+import io.ucoin.ucoinj.elasticsearch.action.market.RestMarketDemandIndexAction;
+import io.ucoin.ucoinj.elasticsearch.action.market.RestMarketOfferIndexAction;
 import io.ucoin.ucoinj.elasticsearch.action.registry.RestRegistryRecordIndexAction;
 import io.ucoin.ucoinj.elasticsearch.action.security.RestSecurityAuthAction;
 import io.ucoin.ucoinj.elasticsearch.action.security.RestSecurityGetChallengeAction;
@@ -35,7 +36,8 @@ public class RestModule extends AbstractModule implements Module {
     @Override protected void configure() {
         bind(RestCurrencyIndexAction.class).asEagerSingleton();
 
-        bind(RestMarketRecordIndexAction.class).asEagerSingleton();
+        bind(RestMarketOfferIndexAction.class).asEagerSingleton();
+        bind(RestMarketDemandIndexAction.class).asEagerSingleton();
 
         bind(RestRegistryRecordIndexAction.class).asEagerSingleton();
 
diff --git a/ucoinj-elasticsearch-plugin/src/main/java/io/ucoin/ucoinj/elasticsearch/action/market/RestMarketRecordIndexAction.java b/ucoinj-elasticsearch-plugin/src/main/java/io/ucoin/ucoinj/elasticsearch/action/market/RestMarketDemandIndexAction.java
similarity index 87%
rename from ucoinj-elasticsearch-plugin/src/main/java/io/ucoin/ucoinj/elasticsearch/action/market/RestMarketRecordIndexAction.java
rename to ucoinj-elasticsearch-plugin/src/main/java/io/ucoin/ucoinj/elasticsearch/action/market/RestMarketDemandIndexAction.java
index 5fe953ac23be97069a1306578d5a269367b8e50c..e721244e30bb3f988d8f1152ed8f7cd6b220179a 100644
--- a/ucoinj-elasticsearch-plugin/src/main/java/io/ucoin/ucoinj/elasticsearch/action/market/RestMarketRecordIndexAction.java
+++ b/ucoinj-elasticsearch-plugin/src/main/java/io/ucoin/ucoinj/elasticsearch/action/market/RestMarketDemandIndexAction.java
@@ -35,21 +35,21 @@ import static org.elasticsearch.rest.RestRequest.Method.POST;
 import static org.elasticsearch.rest.RestStatus.BAD_REQUEST;
 import static org.elasticsearch.rest.RestStatus.OK;
 
-public class RestMarketRecordIndexAction extends BaseRestHandler {
+public class RestMarketDemandIndexAction extends BaseRestHandler {
 
-    private static final ESLogger log = ESLoggerFactory.getLogger(RestMarketRecordIndexAction.class.getName());
+    private static final ESLogger log = ESLoggerFactory.getLogger(RestMarketDemandIndexAction.class.getName());
 
     @Inject
-    public RestMarketRecordIndexAction(Settings settings, RestController controller, Client client) {
+    public RestMarketDemandIndexAction(Settings settings, RestController controller, Client client) {
         super(settings, controller, client);
-        controller.registerHandler(POST, "/market/record", this);
+        controller.registerHandler(POST, "/market/demand", this);
     }
 
     @Override
     protected void handleRequest(final RestRequest request, RestChannel restChannel, Client client) throws Exception {
 
         try {
-            String recordId = ServiceLocator.instance().getMarketRecordIndexerService().indexRecordFromJson(request.content().toUtf8());
+            String recordId = ServiceLocator.instance().getMarketRecordIndexerService().indexDemandFromJson(request.content().toUtf8());
 
             restChannel.sendResponse(new BytesRestResponse(OK, recordId));
         }
diff --git a/ucoinj-elasticsearch-plugin/src/main/java/io/ucoin/ucoinj/elasticsearch/action/market/RestMarketOfferIndexAction.java b/ucoinj-elasticsearch-plugin/src/main/java/io/ucoin/ucoinj/elasticsearch/action/market/RestMarketOfferIndexAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..bbfefcc94d9c8f7345a8d05f0af00f569fe141d7
--- /dev/null
+++ b/ucoinj-elasticsearch-plugin/src/main/java/io/ucoin/ucoinj/elasticsearch/action/market/RestMarketOfferIndexAction.java
@@ -0,0 +1,65 @@
+package io.ucoin.ucoinj.elasticsearch.action.market;
+
+/*
+ * #%L
+ * ucoinj-elasticsearch-plugin
+ * %%
+ * Copyright (C) 2014 - 2016 EIS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the 
+ * License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public 
+ * License along with this program.  If not, see
+ * <http://www.gnu.org/licenses/gpl-3.0.html>.
+ * #L%
+ */
+
+import io.ucoin.ucoinj.core.exception.BusinessException;
+import io.ucoin.ucoinj.elasticsearch.service.ServiceLocator;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.inject.Inject;
+import org.elasticsearch.common.logging.ESLogger;
+import org.elasticsearch.common.logging.ESLoggerFactory;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.rest.*;
+
+import static org.elasticsearch.rest.RestRequest.Method.POST;
+import static org.elasticsearch.rest.RestStatus.BAD_REQUEST;
+import static org.elasticsearch.rest.RestStatus.OK;
+
+public class RestMarketOfferIndexAction extends BaseRestHandler {
+
+    private static final ESLogger log = ESLoggerFactory.getLogger(RestMarketOfferIndexAction.class.getName());
+
+    @Inject
+    public RestMarketOfferIndexAction(Settings settings, RestController controller, Client client) {
+        super(settings, controller, client);
+        controller.registerHandler(POST, "/market/offer", this);
+    }
+
+    @Override
+    protected void handleRequest(final RestRequest request, RestChannel restChannel, Client client) throws Exception {
+
+        try {
+            String recordId = ServiceLocator.instance().getMarketRecordIndexerService().indexOfferFromJson(request.content().toUtf8());
+
+            restChannel.sendResponse(new BytesRestResponse(OK, recordId));
+        }
+        catch(BusinessException e) {
+            log.error(e.getMessage(), e);
+            restChannel.sendResponse(new BytesRestResponse(BAD_REQUEST, String.format("{error: {ucode: 'XXX', message:'%s'}}", e.getMessage())));
+        }
+        catch(Exception e) {
+            log.error(e.getMessage(), e);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/ucoinj-elasticsearch-plugin/src/test/es-home/config/shield/logging.yml b/ucoinj-elasticsearch-plugin/src/test/es-home/config/shield/logging.yml
new file mode 100644
index 0000000000000000000000000000000000000000..4adf913a371cb30f2db3cdd5d73a6c0334fe0392
--- /dev/null
+++ b/ucoinj-elasticsearch-plugin/src/test/es-home/config/shield/logging.yml
@@ -0,0 +1,26 @@
+# default configuration for the audit trail logs
+#
+# Error Levels:
+#
+# ERROR   authentication_failed, access_denied, tampered_request, connection_denied
+# WARN    authentication_failed, access_denied, tampered_request, connection_denied, anonymous_access
+# INFO    authentication_failed, access_denied, tampered_request, connection_denied, anonymous_access, access_granted
+# DEBUG   doesn't output additional entry types beyond INFO, but extends the information emmitted for each entry
+# TRACE   authentication_failed, access_denied, tampered_request, connection_denied, anonymous_access, access_granted, connection_granted, authentication_failed [<realm>]. In addition, internal system requests (self-management requests triggered by elasticsearch itself) will also be logged for "access_granted" entry type.
+#
+
+logger:
+  shield.audit.logfile: INFO, access_log
+
+additivity:
+  shield.audit.logfile: false
+
+appender:
+
+  access_log:
+    type: dailyRollingFile
+    file: ${path.logs}/${cluster.name}-access.log
+    datePattern: "'.'yyyy-MM-dd"
+    layout:
+      type: pattern
+      conversionPattern: "[%d{ISO8601}] %m%n"
diff --git a/ucoinj-elasticsearch-plugin/src/test/es-home/config/shield/role_mapping.yml b/ucoinj-elasticsearch-plugin/src/test/es-home/config/shield/role_mapping.yml
new file mode 100644
index 0000000000000000000000000000000000000000..68c82f7e7c05b02e9aa539262ffa2df332cd078e
--- /dev/null
+++ b/ucoinj-elasticsearch-plugin/src/test/es-home/config/shield/role_mapping.yml
@@ -0,0 +1,14 @@
+# Role mapping configuration file which has elasticsearch roles as keys
+# that map to one or more user or group distinguished names
+
+#roleA:   this is an elasticsearch role
+#  - groupA-DN  this is a group distinguished name
+#  - groupB-DN
+#  - user1-DN   this is the full user distinguished name
+
+#power_user:
+#  - "cn=admins,dc=example,dc=com"
+#user:
+#  - "cn=users,dc=example,dc=com"
+#  - "cn=admins,dc=example,dc=com"
+#  - "cn=John Doe,cn=other users,dc=example,dc=com"
diff --git a/ucoinj-elasticsearch-plugin/src/test/es-home/config/shield/roles.yml b/ucoinj-elasticsearch-plugin/src/test/es-home/config/shield/roles.yml
new file mode 100644
index 0000000000000000000000000000000000000000..633156f7611ee1257c930a1d86a10828cd8e2fb7
--- /dev/null
+++ b/ucoinj-elasticsearch-plugin/src/test/es-home/config/shield/roles.yml
@@ -0,0 +1,71 @@
+# All cluster rights
+# All operations on all indices
+admin:
+  cluster: all
+  indices:
+    '*':
+      privileges: all
+
+# monitoring cluster privileges
+# All operations on all indices
+power_user:
+  cluster: monitor
+  indices:
+    '*':
+      privileges: all
+
+# Read-only operations on indices
+user:
+  indices:
+    '*':
+      privileges: read
+
+# Defines the required permissions for transport clients
+transport_client:
+  cluster:
+      - cluster:monitor/nodes/liveness
+      #uncomment the following for sniffing
+      #- cluster:monitor/state
+
+# The required permissions for kibana 4 users.
+kibana4:
+  cluster: 
+      - cluster:monitor/nodes/info
+      - cluster:monitor/health 
+  indices:
+    '*':
+      privileges: indices:admin/mappings/fields/get, indices:admin/validate/query, indices:data/read/search, indices:data/read/msearch, indices:data/read/field_stats, indices:admin/get
+    '.kibana':
+      privileges: indices:admin/exists, indices:admin/mapping/put, indices:admin/mappings/fields/get, indices:admin/refresh, indices:admin/validate/query, indices:data/read/get, indices:data/read/mget, indices:data/read/search, indices:data/write/delete, indices:data/write/index, indices:data/write/update
+
+# The required permissions for the kibana 4 server
+kibana4_server:
+  cluster:
+      - cluster:monitor/nodes/info
+      - cluster:monitor/health
+  indices:
+    '.kibana':
+      privileges: indices:admin/create, indices:admin/exists, indices:admin/mapping/put, indices:admin/mappings/fields/get, indices:admin/refresh, indices:admin/validate/query, indices:data/read/get, indices:data/read/mget, indices:data/read/search, indices:data/write/delete, indices:data/write/index, indices:data/write/update
+
+# The required role for logstash users
+logstash:
+  cluster: indices:admin/template/get, indices:admin/template/put
+  indices:
+    'logstash-*':
+      privileges: indices:data/write/bulk, indices:data/write/delete, indices:data/write/update, indices:data/read/search, indices:data/read/scroll, create_index
+
+# Marvel user role. Assign to marvel users.
+marvel_user:
+  indices:
+    '.marvel-es-*':
+      privileges: read
+    '.kibana':
+      privileges: indices:admin/exists, indices:admin/mappings/fields/get, indices:admin/validate/query, indices:data/read/get, indices:data/read/mget, indices:data/read/search
+
+# Marvel remote agent role. Assign to the agent user on the remote marvel cluster
+# to which the marvel agent will export all its data
+remote_marvel_agent:
+  cluster: indices:admin/template/put, indices:admin/template/get
+  indices:
+    '.marvel-es-*':
+      privileges: all
\ No newline at end of file
diff --git a/ucoinj-elasticsearch-plugin/src/test/es-home/config/shield/users b/ucoinj-elasticsearch-plugin/src/test/es-home/config/shield/users
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/ucoinj-elasticsearch-plugin/src/test/es-home/config/shield/users_roles b/ucoinj-elasticsearch-plugin/src/test/es-home/config/shield/users_roles
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/ucoinj-elasticsearch-plugin/src/test/es-home/logs/elasticsearch-access.log b/ucoinj-elasticsearch-plugin/src/test/es-home/logs/elasticsearch-access.log
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/ucoinj-elasticsearch-plugin/src/test/es-home/logs/elasticsearch.log b/ucoinj-elasticsearch-plugin/src/test/es-home/logs/elasticsearch.log
new file mode 100644
index 0000000000000000000000000000000000000000..41bdfb5d498a23795aec04efba624b738024f4cc
--- /dev/null
+++ b/ucoinj-elasticsearch-plugin/src/test/es-home/logs/elasticsearch.log
@@ -0,0 +1,68 @@
+[2016-02-02 19:00:21,260][INFO ][node                     ] [Lucas Brand] version[2.2.0], pid[4389], build[8ff36d1/2016-01-27T13:32:39Z]
+[2016-02-02 19:00:21,261][INFO ][node                     ] [Lucas Brand] initializing ...
+[2016-02-02 19:00:21,353][INFO ][plugins                  ] [Lucas Brand] modules [], plugins [], sites []
+[2016-02-02 19:00:21,389][INFO ][env                      ] [Lucas Brand] using [1] data paths, mounts [[/home (/dev/sdb5)]], net usable_space [202.6gb], net total_space [436.4gb], spins? [possibly], types [ext4]
+[2016-02-02 19:00:21,389][INFO ][env                      ] [Lucas Brand] heap size [3.4gb], compressed ordinary object pointers [true]
+[2016-02-02 19:00:23,318][INFO ][node                     ] [Lucas Brand] initialized
+[2016-02-02 19:00:23,318][INFO ][node                     ] [Lucas Brand] starting ...
+[2016-02-02 19:00:23,381][INFO ][transport                ] [Lucas Brand] publish_address {127.0.0.1:9300}, bound_addresses {127.0.0.1:9300}, {[::1]:9300}
+[2016-02-02 19:00:23,390][INFO ][discovery                ] [Lucas Brand] elasticsearch/0vD7T8u-Rmajbu8MH0yb_w
+[2016-02-02 19:00:26,433][INFO ][cluster.service          ] [Lucas Brand] new_master {Lucas Brand}{0vD7T8u-Rmajbu8MH0yb_w}{127.0.0.1}{127.0.0.1:9300}, reason: zen-disco-join(elected_as_master, [0] joins received)
+[2016-02-02 19:00:26,443][INFO ][http                     ] [Lucas Brand] publish_address {127.0.0.1:9292}, bound_addresses {127.0.0.1:9292}, {[::1]:9292}
+[2016-02-02 19:00:26,443][INFO ][node                     ] [Lucas Brand] started
+[2016-02-02 19:00:26,535][INFO ][gateway                  ] [Lucas Brand] recovered [0] indices into cluster_state
+[2016-02-02 19:01:28,760][INFO ][node                     ] [Lucas Brand] stopping ...
+[2016-02-02 19:01:28,770][INFO ][node                     ] [Lucas Brand] stopped
+[2016-02-02 19:01:28,770][INFO ][node                     ] [Lucas Brand] closing ...
+[2016-02-02 19:01:28,773][INFO ][node                     ] [Lucas Brand] closed
+[2016-02-02 19:01:32,954][INFO ][node                     ] [Hephaestus] version[2.2.0], pid[4590], build[8ff36d1/2016-01-27T13:32:39Z]
+[2016-02-02 19:01:32,955][INFO ][node                     ] [Hephaestus] initializing ...
+[2016-02-02 19:01:33,045][INFO ][plugins                  ] [Hephaestus] modules [], plugins [], sites []
+[2016-02-02 19:01:33,075][INFO ][env                      ] [Hephaestus] using [1] data paths, mounts [[/home (/dev/sdb5)]], net usable_space [202.6gb], net total_space [436.4gb], spins? [possibly], types [ext4]
+[2016-02-02 19:01:33,075][INFO ][env                      ] [Hephaestus] heap size [3.4gb], compressed ordinary object pointers [true]
+[2016-02-02 19:01:34,914][INFO ][node                     ] [Hephaestus] initialized
+[2016-02-02 19:01:34,914][INFO ][node                     ] [Hephaestus] starting ...
+[2016-02-02 19:01:34,973][INFO ][transport                ] [Hephaestus] publish_address {127.0.0.1:9300}, bound_addresses {127.0.0.1:9300}, {[::1]:9300}
+[2016-02-02 19:01:34,981][INFO ][discovery                ] [Hephaestus] elasticsearch/KPUfVSTIRRicjnPSp6TjLQ
+[2016-02-02 19:01:38,024][INFO ][cluster.service          ] [Hephaestus] new_master {Hephaestus}{KPUfVSTIRRicjnPSp6TjLQ}{127.0.0.1}{127.0.0.1:9300}, reason: zen-disco-join(elected_as_master, [0] joins received)
+[2016-02-02 19:01:38,037][INFO ][http                     ] [Hephaestus] publish_address {127.0.0.1:9292}, bound_addresses {127.0.0.1:9292}, {[::1]:9292}
+[2016-02-02 19:01:38,038][INFO ][node                     ] [Hephaestus] started
+[2016-02-02 19:01:38,105][INFO ][gateway                  ] [Hephaestus] recovered [0] indices into cluster_state
+[2016-02-02 19:02:06,623][INFO ][node                     ] [Hephaestus] stopping ...
+[2016-02-02 19:02:06,633][INFO ][node                     ] [Hephaestus] stopped
+[2016-02-02 19:02:06,633][INFO ][node                     ] [Hephaestus] closing ...
+[2016-02-02 19:02:06,637][INFO ][node                     ] [Hephaestus] closed
+[2016-02-02 19:02:24,839][INFO ][node                     ] [Sergeant Fury] version[2.2.0], pid[4758], build[8ff36d1/2016-01-27T13:32:39Z]
+[2016-02-02 19:02:24,840][INFO ][node                     ] [Sergeant Fury] initializing ...
+[2016-02-02 19:02:24,922][INFO ][plugins                  ] [Sergeant Fury] modules [], plugins [], sites []
+[2016-02-02 19:02:24,946][INFO ][env                      ] [Sergeant Fury] using [1] data paths, mounts [[/home (/dev/sdb5)]], net usable_space [202.6gb], net total_space [436.4gb], spins? [possibly], types [ext4]
+[2016-02-02 19:02:24,946][INFO ][env                      ] [Sergeant Fury] heap size [3.4gb], compressed ordinary object pointers [true]
+[2016-02-02 19:02:26,789][INFO ][node                     ] [Sergeant Fury] initialized
+[2016-02-02 19:02:26,789][INFO ][node                     ] [Sergeant Fury] starting ...
+[2016-02-02 19:02:26,851][INFO ][transport                ] [Sergeant Fury] publish_address {127.0.0.1:9300}, bound_addresses {127.0.0.1:9300}, {[::1]:9300}
+[2016-02-02 19:02:26,860][INFO ][discovery                ] [Sergeant Fury] elasticsearch/dG65jlrZSDCOeJg0Q074Cw
+[2016-02-02 19:02:29,905][INFO ][cluster.service          ] [Sergeant Fury] new_master {Sergeant Fury}{dG65jlrZSDCOeJg0Q074Cw}{127.0.0.1}{127.0.0.1:9300}, reason: zen-disco-join(elected_as_master, [0] joins received)
+[2016-02-02 19:02:29,914][INFO ][http                     ] [Sergeant Fury] publish_address {127.0.0.1:9292}, bound_addresses {127.0.0.1:9292}, {[::1]:9292}
+[2016-02-02 19:02:29,915][INFO ][node                     ] [Sergeant Fury] started
+[2016-02-02 19:02:29,985][INFO ][gateway                  ] [Sergeant Fury] recovered [0] indices into cluster_state
+[2016-02-02 19:02:43,546][INFO ][node                     ] [Sergeant Fury] stopping ...
+[2016-02-02 19:02:43,555][INFO ][node                     ] [Sergeant Fury] stopped
+[2016-02-02 19:02:43,555][INFO ][node                     ] [Sergeant Fury] closing ...
+[2016-02-02 19:02:43,559][INFO ][node                     ] [Sergeant Fury] closed
+[2016-02-02 19:02:49,922][INFO ][node                     ] [Lady Mandarin] version[2.2.0], pid[4918], build[8ff36d1/2016-01-27T13:32:39Z]
+[2016-02-02 19:02:49,923][INFO ][node                     ] [Lady Mandarin] initializing ...
+[2016-02-02 19:02:50,007][INFO ][plugins                  ] [Lady Mandarin] modules [], plugins [], sites []
+[2016-02-02 19:02:50,045][INFO ][env                      ] [Lady Mandarin] using [1] data paths, mounts [[/home (/dev/sdb5)]], net usable_space [202.6gb], net total_space [436.4gb], spins? [possibly], types [ext4]
+[2016-02-02 19:02:50,045][INFO ][env                      ] [Lady Mandarin] heap size [3.4gb], compressed ordinary object pointers [true]
+[2016-02-02 19:02:51,888][INFO ][node                     ] [Lady Mandarin] initialized
+[2016-02-02 19:02:51,888][INFO ][node                     ] [Lady Mandarin] starting ...
+[2016-02-02 19:02:51,950][INFO ][transport                ] [Lady Mandarin] publish_address {127.0.0.1:9300}, bound_addresses {127.0.0.1:9300}, {[::1]:9300}
+[2016-02-02 19:02:51,960][INFO ][discovery                ] [Lady Mandarin] elasticsearch/hCDo3Pj5SnKGJzrKTawrSw
+[2016-02-02 19:02:55,005][INFO ][cluster.service          ] [Lady Mandarin] new_master {Lady Mandarin}{hCDo3Pj5SnKGJzrKTawrSw}{127.0.0.1}{127.0.0.1:9300}, reason: zen-disco-join(elected_as_master, [0] joins received)
+[2016-02-02 19:02:55,015][INFO ][http                     ] [Lady Mandarin] publish_address {127.0.0.1:9292}, bound_addresses {127.0.0.1:9292}, {[::1]:9292}
+[2016-02-02 19:02:55,015][INFO ][node                     ] [Lady Mandarin] started
+[2016-02-02 19:02:55,084][INFO ][gateway                  ] [Lady Mandarin] recovered [0] indices into cluster_state
+[2016-02-02 19:25:37,053][INFO ][node                     ] [Lady Mandarin] stopping ...
+[2016-02-02 19:25:37,064][INFO ][node                     ] [Lady Mandarin] stopped
+[2016-02-02 19:25:37,065][INFO ][node                     ] [Lady Mandarin] closing ...
+[2016-02-02 19:25:37,068][INFO ][node                     ] [Lady Mandarin] closed
diff --git a/ucoinj-elasticsearch-plugin/src/test/es-home/logs/elasticsearch_deprecation.log b/ucoinj-elasticsearch-plugin/src/test/es-home/logs/elasticsearch_deprecation.log
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/ucoinj-elasticsearch-plugin/src/test/es-home/logs/elasticsearch_index_indexing_slowlog.log b/ucoinj-elasticsearch-plugin/src/test/es-home/logs/elasticsearch_index_indexing_slowlog.log
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/ucoinj-elasticsearch-plugin/src/test/es-home/logs/elasticsearch_index_search_slowlog.log b/ucoinj-elasticsearch-plugin/src/test/es-home/logs/elasticsearch_index_search_slowlog.log
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/ucoinj-elasticsearch/src/main/java/io/ucoin/ucoinj/elasticsearch/service/market/MarketRecordIndexerService.java b/ucoinj-elasticsearch/src/main/java/io/ucoin/ucoinj/elasticsearch/service/market/MarketRecordIndexerService.java
index 6f4020b2590e5f866def77724b9ca76ea5cd00b3..d81187d8b6bbd707c798c9e1c8f5bbc0a5d68677 100644
--- a/ucoinj-elasticsearch/src/main/java/io/ucoin/ucoinj/elasticsearch/service/market/MarketRecordIndexerService.java
+++ b/ucoinj-elasticsearch/src/main/java/io/ucoin/ucoinj/elasticsearch/service/market/MarketRecordIndexerService.java
@@ -61,18 +61,16 @@ public class MarketRecordIndexerService extends BaseIndexerService {
     private static final String JSON_STRING_PROPERTY_REGEX = "[,]?[\"\\s\\n\\r]*%s[\"]?[\\s\\n\\r]*:[\\s\\n\\r]*\"[^\"]+\"";
 
     public static final String INDEX_NAME = "market";
-    public static final String INDEX_TYPE = "record";
 
-    private Gson gson;
-
-    private Configuration config;
+    public static final String INDEX_TYPE_OFFER = "offer";
+    public static final String INDEX_TYPE_DEMAND = "demand";
 
     private WotRemoteService wotRemoteService;
 
     private CryptoService cryptoService;
 
     public MarketRecordIndexerService() {
-        gson = GsonUtils.newBuilder().create();
+
     }
 
     @Override
@@ -80,15 +78,12 @@ public class MarketRecordIndexerService extends BaseIndexerService {
         super.afterPropertiesSet();
         wotRemoteService = ServiceLocator.instance().getWotRemoteService();
         cryptoService = ServiceLocator.instance().getCryptoService();
-        config = Configuration.instance();
     }
 
     @Override
     public void close() throws IOException {
         super.close();
         wotRemoteService = null;
-        config = null;
-        gson = null;
     }
 
     /**
@@ -123,71 +118,51 @@ public class MarketRecordIndexerService extends BaseIndexerService {
      * @throws JsonProcessingException
      */
     public void createIndex() throws JsonProcessingException {
-        log.info(String.format("Creating index [%s/%s]", INDEX_NAME, INDEX_TYPE));
-
         CreateIndexRequestBuilder createIndexRequestBuilder = getClient().admin().indices().prepareCreate(INDEX_NAME);
         Settings indexSettings = Settings.settingsBuilder()
-                .put("number_of_shards", 1)
-                .put("number_of_replicas", 1)
+                .put("number_of_shards", 3)
+                .put("number_of_replicas", 2)
                 .put("analyzer", createDefaultAnalyzer())
                 .build();
+
+        // Create offer index
+        log.info(String.format("Creating index [%s/%s]", INDEX_NAME, INDEX_TYPE_OFFER));
         createIndexRequestBuilder.setSettings(indexSettings);
-        createIndexRequestBuilder.addMapping(INDEX_TYPE, createIndexMapping());
+        createIndexRequestBuilder.addMapping(INDEX_TYPE_OFFER, createIndexMapping(INDEX_TYPE_OFFER));
+        createIndexRequestBuilder.execute().actionGet();
+
+        // Create demand index
+        log.info(String.format("Creating index [%s/%s]", INDEX_NAME, INDEX_TYPE_DEMAND));
+        createIndexRequestBuilder.setSettings(indexSettings);
+        createIndexRequestBuilder.addMapping(INDEX_TYPE_DEMAND, createIndexMapping(INDEX_TYPE_DEMAND));
         createIndexRequestBuilder.execute().actionGet();
     }
 
     /**
-     *
+     * Index a new offer
      * @param recordJson
      * @return the record id
      */
-    public String indexRecordFromJson(String recordJson) {
-
-        try {
-            ObjectMapper mapper = new ObjectMapper();
-            JsonNode actualObj = mapper.readTree(recordJson);
-            Set<String> fieldNames = Sets.newHashSet(actualObj.fieldNames());
-            if (!fieldNames.contains(Record.PROPERTY_ISSUER)
-                    || !fieldNames.contains(Record.PROPERTY_SIGNATURE)) {
-                throw new InvalidFormatException("Invalid record JSON format. Required fields [issuer,signature]");
-            }
-            String issuer = actualObj.get(Record.PROPERTY_ISSUER).asText();
-            String signature = actualObj.get(Record.PROPERTY_SIGNATURE).asText();
-
-            String recordNoSign = recordJson.replaceAll(String.format(JSON_STRING_PROPERTY_REGEX, Record.PROPERTY_SIGNATURE), "")
-                    .replaceAll(String.format(JSON_STRING_PROPERTY_REGEX, Record.PROPERTY_HASH), "");
-
-            if (!cryptoService.verify(recordNoSign, signature, issuer)) {
-                throw new InvalidSignatureException("Invalid signature for JSON string: " + recordNoSign);
-            }
-
-            if (log.isDebugEnabled()) {
-                log.debug(String.format("Indexing a record from issuer [%s]", issuer.substring(0, 8)));
-            }
-
-        }
-        catch(IOException | JsonSyntaxException e) {
-            throw new InvalidFormatException("Invalid record JSON: " + e.getMessage(), e);
-        }
-
-        // Preparing indexBlocksFromNode
-        IndexRequestBuilder indexRequest = getClient().prepareIndex(INDEX_NAME, INDEX_TYPE)
-                .setSource(recordJson);
+    public String indexOfferFromJson(String recordJson) {
 
-        // Execute indexBlocksFromNode
-        IndexResponse response = indexRequest
-                .setRefresh(false)
-                .execute().actionGet();
+        return indexRecordFromJson(recordJson, INDEX_TYPE_OFFER);
+    }
 
-        return response.getId();
+    /**
+     * Index a new demand
+     * @param recordJson
+     * @return the record id
+     */
+    public String indexDemandFromJson(String recordJson) {
+        return indexRecordFromJson(recordJson, INDEX_TYPE_DEMAND);
     }
 
     /* -- Internal methods -- */
 
 
-    public XContentBuilder createIndexMapping() {
+    public XContentBuilder createIndexMapping(String indexType) {
         try {
-            XContentBuilder mapping = XContentFactory.jsonBuilder().startObject().startObject(INDEX_TYPE)
+            XContentBuilder mapping = XContentFactory.jsonBuilder().startObject().startObject(indexType)
                     .startObject("properties")
 
                     // title
@@ -242,8 +217,53 @@ public class MarketRecordIndexerService extends BaseIndexerService {
             return mapping;
         }
         catch(IOException ioe) {
-            throw new TechnicalException(String.format("Error while getting mapping for index [%s/%s]: %s", INDEX_NAME, INDEX_TYPE, ioe.getMessage()), ioe);
+            throw new TechnicalException(String.format("Error while getting mapping for index [%s/%s]: %s", INDEX_NAME, indexType, ioe.getMessage()), ioe);
+        }
+    }
+
+    public String indexRecordFromJson(String recordJson, String indexType) {
+
+        try {
+            ObjectMapper mapper = new ObjectMapper();
+            JsonNode actualObj = mapper.readTree(recordJson);
+            Set<String> fieldNames = Sets.newHashSet(actualObj.fieldNames());
+            if (!fieldNames.contains(Record.PROPERTY_ISSUER)
+                    || !fieldNames.contains(Record.PROPERTY_SIGNATURE)) {
+                throw new InvalidFormatException("Invalid record JSON format. Required fields [issuer,signature]");
+            }
+            String issuer = actualObj.get(Record.PROPERTY_ISSUER).asText();
+
+            String signature = actualObj.get(Record.PROPERTY_SIGNATURE).asText();
+
+            String recordNoSign = recordJson.replaceAll(String.format(JSON_STRING_PROPERTY_REGEX, Record.PROPERTY_SIGNATURE), "")
+                    .replaceAll(String.format(JSON_STRING_PROPERTY_REGEX, Record.PROPERTY_HASH), "");
+
+            if (!cryptoService.verify(recordNoSign, signature, issuer)) {
+                throw new InvalidSignatureException("Invalid signature for JSON string: " + recordNoSign);
+            }
+
+            // TODO : check if issuer is a valid member
+            //wotRemoteService.getRequirments();
+
+            if (log.isDebugEnabled()) {
+                log.debug(String.format("Indexing a record from issuer [%s]", issuer.substring(0, 8)));
+            }
+
+        }
+        catch(IOException | JsonSyntaxException e) {
+            throw new InvalidFormatException("Invalid record JSON: " + e.getMessage(), e);
         }
+
+        // Preparing indexBlocksFromNode
+        IndexRequestBuilder indexRequest = getClient().prepareIndex(INDEX_NAME, indexType)
+                .setSource(recordJson);
+
+        // Execute indexBlocksFromNode
+        IndexResponse response = indexRequest
+                .setRefresh(false)
+                .execute().actionGet();
+
+        return response.getId();
     }
 
 }
diff --git a/ucoinj-elasticsearch/src/test/resources/log4j.properties b/ucoinj-elasticsearch/src/test/resources/log4j.properties
index ab3b55380dd939a15cb92f6173dd8f1ff84b5835..983dbe9f1a1d91d9794428b5209e0ead5e002478 100644
--- a/ucoinj-elasticsearch/src/test/resources/log4j.properties
+++ b/ucoinj-elasticsearch/src/test/resources/log4j.properties
@@ -9,6 +9,7 @@ log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %5p (%c:%L) - [%t] %m
 
 # uCoinj levels
 log4j.logger.io.ucoin=INFO
+log4j.logger.io.ucoin.ucoinj.elasticsearch=DEBUG
 #log4j.logger.io.ucoin.ucoinj=DEBUG
 #log4j.logger.io.ucoin.ucoinj.core=WARN
 #log4j.logger.io.ucoin.ucoinj.elasticsearch=DEBUG