security: Integrate certificate exchanging into sync

Change-Id: I6ea284b0683d75013f6b72845d894eaed29e468c
diff --git a/log4cxx.properties b/log4cxx.properties
index 9a76448..0659753 100644
--- a/log4cxx.properties
+++ b/log4cxx.properties
@@ -12,6 +12,7 @@
 log4j.appender.A1.layout.ConversionPattern=%d{ss,SSS}  %-12c  %m%n
 
 log4j.logger.SyncLogic = TRACE
+log4j.logger.SyncSocket = TRACE
 log4j.logger.SyncValidator = DEBUG
 #log4j.logger.SyncInterestTable = TRACE
 #log4j.logger.AppDataFetch = TRACE
diff --git a/src/sync-intro-certificate.h b/src/sync-intro-certificate.h
index 48dae45..3c28366 100644
--- a/src/sync-intro-certificate.h
+++ b/src/sync-intro-certificate.h
@@ -18,6 +18,12 @@
 
 class IntroCertificate : public ndn::Data
 {
+  /**
+   * Naming convention of IntroCertificate:
+   * /<sync_prefix>/CHRONOS-INTRO-CERT/introducee_certname/introducer_certname/version
+   * Content: introducee's identity certificate;
+   * KeyLocator: introducer's identity certificate;
+   */
 public:
   struct Error : public ndn::Data::Error { Error(const std::string &what) : ndn::Data::Error(what) {} };
 
@@ -33,7 +39,7 @@
    */
   IntroCertificate(const ndn::Name& syncPrefix,
                    const ndn::IdentityCertificate& introduceeCert,
-                   const ndn::Name& introducerName); //without version number
+                   const ndn::Name& introducerCertName); //without version number
 
   /**
    * @brief Construct IntroCertificate using a plain data.
@@ -55,59 +61,60 @@
   }
 
   const ndn::Name&
-  getIntroducerName() const
+  getIntroducerCertName() const
   {
-    return m_introducerName;
+    return m_introducerCertName;
   }
 
   const ndn::Name&
-  getIntroduceeName() const
+  getIntroduceeCertName() const
   {
-    return m_introduceeName;
+    return m_introduceeCertName;
   }
 
 private:
   ndn::Name m_syncPrefix;
   ndn::IdentityCertificate m_introduceeCert;
-  ndn::Name m_introducerName;
-  ndn::Name m_introduceeName;
+  ndn::Name m_introducerCertName;
+  ndn::Name m_introduceeCertName;
 };
 
 inline
 IntroCertificate::IntroCertificate(const ndn::Name& syncPrefix,
                                    const ndn::IdentityCertificate& introduceeCert,
-                                   const ndn::Name& introducerName)
+                                   const ndn::Name& introducerCertName)
   : m_syncPrefix(syncPrefix)
   , m_introduceeCert(introduceeCert)
-  , m_introducerName(introducerName)
-  , m_introduceeName(introduceeCert.getName().getPrefix(-1))
+  , m_introducerCertName(introducerCertName)
+  , m_introduceeCertName(introduceeCert.getName().getPrefix(-1))
 {
-  // Naming convention /<sync_prefix>/intro-cert/introducee_certname/introducer_certname/version/
+  // Naming convention /<sync_prefix>/CHRONOS-INTRO-CERT/introducee_certname/introducer_certname/version
   ndn::Name dataName = m_syncPrefix;
-  dataName.append("intro-cert").append(introduceeCert.getName().getPrefix(-1).wireEncode()).append(introducerName.wireEncode()).appendVersion();
+  dataName.append("CHRONOS-INTRO-CERT")
+    .append(m_introduceeCertName.wireEncode())
+    .append(m_introducerCertName.wireEncode())
+    .appendVersion();
   
   setName(dataName);
-  setContent(introduceeCert.wireEncode());
+  setContent(m_introduceeCert.wireEncode());
 }
 
 inline
 IntroCertificate::IntroCertificate(const ndn::Data& data)
   : Data(data)
 {
+  // Naming convention /<sync_prefix>/CHRONOS-INTRO-CERT/introducee_certname/introducer_certname/version
   ndn::Name dataName = data.getName();
-  ndn::Name introduceeCertName;
-  ndn::Name introducerName;
 
-  if(dataName.size() < 4 || dataName.get(-4).toEscapedString() != "intro-cert")
+  if(dataName.size() < 4 || dataName.get(-4).toEscapedString() != "CHRONOS-INTRO-CERT")
     throw Error("Not a Sync::IntroCertificate");
 
-  m_syncPrefix = dataName.getPrefix(-4);
-
   try
     {
       m_introduceeCert.wireDecode(data.getContent().blockFromValue());
-      m_introducerName.wireDecode(dataName.get(-2).blockFromValue());
-      introduceeCertName.wireDecode(dataName.get(-3).blockFromValue());
+      m_introducerCertName.wireDecode(dataName.get(-2).blockFromValue());
+      m_introduceeCertName.wireDecode(dataName.get(-3).blockFromValue());
+      m_syncPrefix = dataName.getPrefix(-4);
     }
   catch(ndn::IdentityCertificate::Error& e)
     {
@@ -122,15 +129,14 @@
       throw Error("Cannot decode block name");
     }
 
-  if(introduceeCertName != m_introduceeCert.getName().getPrefix(-1))
+  if(m_introduceeCertName != m_introduceeCert.getName().getPrefix(-1))
     throw Error("Invalid Sync::IntroCertificate (inconsistent introducee name)");
 
-  m_introduceeName = introduceeCertName;
-
+  ndn::Name keyLocatorName;
   try
     {
       ndn::SignatureSha256WithRsa sig(data.getSignature());
-      introducerName = sig.getKeyLocator().getName();
+      keyLocatorName = sig.getKeyLocator().getName();
     }
   catch(ndn::KeyLocator::Error& e)
     {
@@ -141,10 +147,7 @@
       throw Error("Invalid Sync::IntroCertificate (inconsistent introducer name#2)");
     }
 
-  if(m_introducerName != introducerName)
-    throw Error("Invalid Sync::IntroCertificate (inconsistent introducer name#3)");
-
-  if(m_introducerName != introducerName)
+  if(m_introducerCertName != keyLocatorName)
     throw Error("Invalid Sync::IntroCertificate (inconsistent introducer name#3)");
 }
 
diff --git a/src/sync-logic.cc b/src/sync-logic.cc
index 5bbd83c..5d20143 100644
--- a/src/sync-logic.cc
+++ b/src/sync-logic.cc
@@ -58,7 +58,7 @@
 int SyncLogic::m_instanceCounter = 0;
 
 SyncLogic::SyncLogic (const Name& syncPrefix,
-                      const Name& identity,
+                      const IdentityCertificate& myCertificate,
                       shared_ptr<Validator> validator, 
                       shared_ptr<Face> face,
                       LogicUpdateCallback onUpdate,
@@ -66,12 +66,11 @@
   : m_state (new FullState)
   , m_syncInterestTable (*face->ioService(), time::seconds(m_syncInterestReexpress))
   , m_syncPrefix (syncPrefix)
-  , m_identity (identity)
+  , m_myCertificate(myCertificate)
   , m_onUpdate (onUpdate)
   , m_onRemove (onRemove)
   , m_perBranch (false)
   , m_validator(validator)
-  , m_keyChain(new KeyChain())
   , m_face(face)
   , m_scheduler(*face->ioService())
   , m_randomGenerator (static_cast<unsigned int> (std::time (0)))
@@ -91,18 +90,17 @@
 }
 
 SyncLogic::SyncLogic (const Name& syncPrefix,
-                      const Name& identity,
+                      const IdentityCertificate& myCertificate,
                       shared_ptr<Validator> validator,
                       shared_ptr<Face> face,
                       LogicPerBranchCallback onUpdateBranch)
   : m_state (new FullState)
   , m_syncInterestTable (*face->ioService(), time::seconds (m_syncInterestReexpress))
   , m_syncPrefix (syncPrefix)
-  , m_identity (identity)
+  , m_myCertificate(myCertificate)
   , m_onUpdateBranch (onUpdateBranch)
   , m_perBranch(true)
   , m_validator(validator)
-  , m_keyChain(new KeyChain())
   , m_face(face)
   , m_scheduler(*face->ioService())
   , m_randomGenerator (static_cast<unsigned int> (std::time (0)))
@@ -168,7 +166,7 @@
     {
       _LOG_DEBUG_ID ("<< I " << name);
 
-      if(name.get(m_syncPrefix.size()).toEscapedString() == "intro-cert")
+      if(name.get(m_syncPrefix.size()).toEscapedString() == "CHRONOS-INTRO-CERT")
         // it is a certificate, validator will take care of it.
         return;
 
@@ -644,7 +642,7 @@
   syncData.setContent(reinterpret_cast<const uint8_t*>(wireData), size);
   syncData.setFreshnessPeriod(m_syncResponseFreshness);
   
-  m_keyChain->signByIdentity(syncData, m_identity);
+  m_keyChain.sign(syncData, m_myCertificate.getName());
   
   m_face->put(syncData);
   
diff --git a/src/sync-logic.h b/src/sync-logic.h
index 423c8d7..ec8fc29 100644
--- a/src/sync-logic.h
+++ b/src/sync-logic.h
@@ -68,23 +68,15 @@
   typedef boost::function< void (const std::string &/*prefix*/ ) > LogicRemoveCallback;
   typedef boost::function< void (const std::string &)> LogicPerBranchCallback;
 
-  /**
-   * @brief Constructor
-   * @param syncPrefix the name prefix to use for the Sync Interest
-   * @param onUpdate function that will be called when new state is detected
-   * @param onRemove function that will be called when state is removed
-   * @param ccnxHandle ccnx handle
-   * the app data when new remote names are learned
-   */
   SyncLogic (const ndn::Name& syncPrefix,
-             const ndn::Name& identity,
+             const ndn::IdentityCertificate& myCertificate,
              ndn::shared_ptr<ndn::Validator> validator,
              ndn::shared_ptr<ndn::Face> face,
              LogicUpdateCallback onUpdate,
              LogicRemoveCallback onRemove);
 
   SyncLogic (const ndn::Name& syncPrefix,
-             const ndn::Name& identity,
+             const ndn::IdentityCertificate& myCertificate,
              ndn::shared_ptr<ndn::Validator> validator,
              ndn::shared_ptr<ndn::Face> face,
              LogicPerBranchCallback onUpdateBranch);
@@ -184,14 +176,14 @@
   SyncInterestTable m_syncInterestTable;
 
   ndn::Name m_syncPrefix;
-  ndn::Name m_identity;
+  ndn::IdentityCertificate m_myCertificate;
   LogicUpdateCallback m_onUpdate;
   LogicRemoveCallback m_onRemove;
   LogicPerBranchCallback m_onUpdateBranch;
   bool m_perBranch;
-  ndn::ptr_lib::shared_ptr<ndn::Validator> m_validator;
-  ndn::ptr_lib::shared_ptr<ndn::KeyChain> m_keyChain;
-  ndn::ptr_lib::shared_ptr<ndn::Face> m_face;
+  ndn::shared_ptr<ndn::Validator> m_validator;
+  ndn::KeyChain m_keyChain;
+  ndn::shared_ptr<ndn::Face> m_face;
   const ndn::RegisteredPrefixId* m_syncRegisteredPrefixId;
 
   ndn::Scheduler m_scheduler;
diff --git a/src/sync-socket.cc b/src/sync-socket.cc
index b37d657..9d3dc77 100644
--- a/src/sync-socket.cc
+++ b/src/sync-socket.cc
@@ -31,20 +31,27 @@
 using ndn::shared_ptr;
 
 SyncSocket::SyncSocket (const Name& syncPrefix,
-                        const Name& identity,
-                        shared_ptr<Validator> validator,
+                        const ndn::Name& dataPrefix,
+                        uint64_t dataSession,
+                        const IdentityCertificate& myCertificate,
+                        shared_ptr<SecRuleRelative> dataRule,
                         shared_ptr<Face> face,
                         NewDataCallback dataCallback, 
                         RemoveCallback rmCallback )
-  : m_newDataCallback(dataCallback)
-  , m_identity(identity)
-  , m_validator(validator)
-  , m_keyChain(new KeyChain())
+  : m_dataPrefix(dataPrefix)
+  , m_dataSession(dataSession)
+  , m_newDataCallback(dataCallback)
+  , m_myCertificate(myCertificate)
   , m_face(face)
   , m_ioService(face->ioService())
+  , m_syncValidator(new SyncValidator(syncPrefix, 
+                                      m_myCertificate, 
+                                      m_face, 
+                                      bind(&SyncSocket::publishData, this, _1, _2, _3, true),
+                                      dataRule))
   , m_syncLogic (syncPrefix,
-                 identity,
-                 validator,
+                 myCertificate,
+                 m_syncValidator,
                  face,
                  bind(&SyncSocket::passCallback, this, _1),
                  rmCallback)
@@ -54,27 +61,28 @@
 {
 }
 
-bool 
-SyncSocket::publishData(const Name &prefix, uint64_t session, const char *buf, size_t len, int freshness)
+void
+SyncSocket::publishData(const uint8_t* buf, size_t len, int freshness, bool isCert)
 {
   shared_ptr<Data> data = make_shared<Data>();
   data->setContent(reinterpret_cast<const uint8_t*>(buf), len);
   data->setFreshnessPeriod(1000*freshness);
 
-  m_ioService->post(bind(&SyncSocket::publishDataInternal, this, data, prefix, session));
-
-  return true;  
+  m_ioService->post(bind(&SyncSocket::publishDataInternal, this, 
+                         data, m_dataPrefix, m_dataSession, isCert));
 }
 
 void
-SyncSocket::publishDataInternal(shared_ptr<Data> data, const Name &prefix, uint64_t session)
+SyncSocket::publishDataInternal(shared_ptr<Data> data, const Name &prefix, uint64_t session, bool isCert)
 {
   uint64_t sequence = getNextSeq(prefix, session);
   Name dataName = prefix;
   dataName.append(boost::lexical_cast<string>(session)).append(boost::lexical_cast<string>(sequence));
+  if(isCert)
+    dataName.append("INTRO-CERT");
   data->setName(dataName);
 
-  m_keyChain->signByIdentity(*data, m_identity);
+  m_keyChain.sign(*data, m_myCertificate.getName());
   m_face->put(*data);
 
   SeqNo s(session, sequence + 1);
@@ -84,15 +92,17 @@
 }
 
 void 
-SyncSocket::fetchData(const Name &prefix, const SeqNo &seq, const OnDataValidated& onValidated, int retry)
+SyncSocket::fetchData(const Name &prefix, const SeqNo &seq, const OnDataValidated& dataCallback, int retry)
 {
   Name interestName = prefix;
   interestName.append(boost::lexical_cast<string>(seq.getSession())).append(boost::lexical_cast<string>(seq.getSeq()));
 
-  const OnDataValidationFailed& onValidationFailed = bind(&SyncSocket::onDataValidationFailed, this, _1);
-  
   ndn::Interest interest(interestName);
   interest.setMustBeFresh(true);
+
+  const OnDataValidated& onValidated = bind(&SyncSocket::onDataValidated, this, _1, interestName.size(), dataCallback);
+  const OnDataValidationFailed& onValidationFailed = bind(&SyncSocket::onDataValidationFailed, this, _1, _2);
+
   m_face->expressInterest(interest, 
                           bind(&SyncSocket::onData, this, _1, _2, onValidated, onValidationFailed), 
                           bind(&SyncSocket::onDataTimeout, this, _1, retry, onValidated, onValidationFailed));
@@ -104,7 +114,7 @@
                    const OnDataValidated& onValidated,
                    const OnDataValidationFailed& onValidationFailed)
 {
-  m_validator->validate(data, onValidated, onValidationFailed);
+  m_syncValidator->validate(data, onValidated, onValidationFailed);
 }
 
 void
@@ -135,24 +145,30 @@
 }
 
 void
-SyncSocket::onDataValidationFailed(const shared_ptr<const Data>& data)
+SyncSocket::onDataValidated(const shared_ptr<const Data>& data,
+                            size_t interestNameSize,
+                            const OnDataValidated& onValidated)
 {
-  _LOG_DEBUG("data cannot be verified!");
+  _LOG_DEBUG("--------------------" << data->getName());
+  if(data->getName().size() > interestNameSize 
+     && data->getName().get(interestNameSize).toEscapedString() == "INTRO-CERT")
+    {
+      Data rawData;
+      rawData.wireDecode(data->getContent().blockFromValue());
+      IntroCertificate introCert(rawData);
+      m_syncValidator->addParticipant(introCert);
+    }
+  else
+    {
+      onValidated(data);
+    }
 }
 
-
-uint64_t
-SyncSocket::getNextSeq (const Name &prefix, uint64_t session)
+void
+SyncSocket::onDataValidationFailed(const shared_ptr<const Data>& data,
+                                   const std::string& failureInfo)
 {
-  SequenceLog::iterator i = m_sequenceLog.find (prefix);
-
-  if (i != m_sequenceLog.end ())
-    {
-      SeqNo s = i->second;
-      if (s.getSession() == session)
-        return s.getSeq();
-    }
-  return 0;
+  _LOG_DEBUG("data cannot be verified!: " << failureInfo);
 }
 
 }//Sync
diff --git a/src/sync-socket.h b/src/sync-socket.h
index f796fed..72df7ab 100644
--- a/src/sync-socket.h
+++ b/src/sync-socket.h
@@ -27,6 +27,7 @@
 
 #include "sync-logic.h"
 #include "sync-seq-no.h"
+#include "sync-validator.h"
 
 #include <utility>
 #include <map>
@@ -45,59 +46,78 @@
   typedef ndn::function< void (const std::vector<MissingDataInfo> &, SyncSocket * ) > NewDataCallback;
   typedef ndn::function< void (const std::string &/*prefix*/ ) > RemoveCallback;
 
-  /**
-   * @brief the constructor for SyncAppSocket; the parameter syncPrefix
-   * should be passed to the constructor of m_syncAppWrapper; the other
-   * parameter should be passed to the constructor of m_fetcher; furthermore,
-   * the fetch function of m_fetcher should be a second paramter passed to
-   * the constructor of m_syncAppWrapper, so that m_syncAppWrapper can tell
-   * m_fetcher to fetch the actual app data after it learns the names
-   *
-   * @param syncPrefix the name prefix for Sync Interest
-   * @param dataCallback the callback to process data
-   */
   SyncSocket (const ndn::Name& syncPrefix, 
-              const ndn::Name& identity,
-              ndn::shared_ptr<ndn::Validator> validator,
+              const ndn::Name& dataPrefix,
+              uint64_t dataSession,
+              const ndn::IdentityCertificate& myCertificate,
+              ndn::shared_ptr<ndn::SecRuleRelative> dataRule,
               ndn::shared_ptr<ndn::Face> face,
               NewDataCallback dataCallback, 
               RemoveCallback rmCallback);
 
   ~SyncSocket ();
 
-  bool 
-  publishData(const ndn::Name &prefix, uint64_t session, const char *buf, size_t len, int freshness);
+  void
+  publishData(const uint8_t* buf, size_t len, int freshness, bool isCert = false);
 
   void 
   remove (const ndn::Name &prefix) 
-  { m_syncLogic.remove(prefix); }
+  { 
+    m_syncLogic.remove(prefix); 
+  }
 
   void 
   fetchData(const ndn::Name &prefix, const SeqNo &seq, const ndn::OnDataValidated& onValidated, int retry = 0);
 
   std::string 
   getRootDigest() 
-  { return m_syncLogic.getRootDigest(); }
+  { 
+    return m_syncLogic.getRootDigest(); 
+  }
 
   uint64_t
-  getNextSeq (const ndn::Name &prefix, uint64_t session);
+  getNextSeq (const ndn::Name &prefix, uint64_t session)
+  {
+    SequenceLog::iterator i = m_sequenceLog.find (prefix);
+    
+    if (i != m_sequenceLog.end ())
+      {
+        SeqNo s = i->second;
+        if (s.getSession() == session)
+          return s.getSeq();
+      }
+    return 0;
+  }
 
   SyncLogic &
   getLogic () 
-  { return m_syncLogic; }
+  { 
+    return m_syncLogic; 
+  }
 
-  // make this a static function so we don't have to create socket instance without
-  // knowing the local prefix. it's a wrong place for this function anyway
-  static std::string
-  GetLocalPrefix (); 
+  void
+  addParticipant(const ndn::IdentityCertificate& introducee)
+  {
+    ndn::shared_ptr<const IntroCertificate> introCert = m_syncValidator->addParticipant(introducee);
+  }
+
+  // // make this a static function so we don't have to create socket instance without
+  // // knowing the local prefix. it's a wrong place for this function anyway
+  // static std::string
+  // GetLocalPrefix (); 
   
 private:
   void
-  publishDataInternal(ndn::shared_ptr<ndn::Data> data, const ndn::Name &prefix, uint64_t session);
+  publishDataInternal(ndn::shared_ptr<ndn::Data> data, 
+                      const ndn::Name &prefix, 
+                      uint64_t session, 
+                      bool isCert);
 
   void 
   passCallback(const std::vector<MissingDataInfo> &v) 
-  { m_newDataCallback(v, this); }
+  { 
+    m_newDataCallback(v, this); 
+  }
 
   void
   onData(const ndn::Interest& interest, ndn::Data& data,
@@ -111,17 +131,26 @@
                 const ndn::OnDataValidationFailed& onValidationFailed);
 
   void
-  onDataValidationFailed(const ndn::shared_ptr<const ndn::Data>& data);
+  onDataValidated(const ndn::shared_ptr<const ndn::Data>& data,
+                  size_t interestNameSize,
+                  const ndn::OnDataValidated& onValidated);
+
+  void
+  onDataValidationFailed(const ndn::shared_ptr<const ndn::Data>& data,
+                         const std::string& failureInfo);
 
 private:
   typedef std::map<ndn::Name, SeqNo> SequenceLog;
+
+  ndn::Name m_dataPrefix;
+  uint64_t m_dataSession;
   NewDataCallback m_newDataCallback;
   SequenceLog m_sequenceLog;
-  ndn::Name m_identity;
-  ndn::shared_ptr<ndn::Validator> m_validator;
-  ndn::shared_ptr<ndn::KeyChain> m_keyChain;
+  ndn::IdentityCertificate m_myCertificate;
+  ndn::KeyChain m_keyChain;
   ndn::shared_ptr<ndn::Face> m_face;
   ndn::shared_ptr<boost::asio::io_service> m_ioService;
+  ndn::shared_ptr<SyncValidator> m_syncValidator;
   SyncLogic      m_syncLogic;
 };
 
diff --git a/src/sync-validator.cc b/src/sync-validator.cc
index 03c292b..2d86dbe 100644
--- a/src/sync-validator.cc
+++ b/src/sync-validator.cc
@@ -26,6 +26,7 @@
 SyncValidator::SyncValidator(const Name& prefix,
                              const IdentityCertificate& anchor,
                              shared_ptr<Face> face,
+                             const PublishCertCallback& publishCertCallback,
                              shared_ptr<SecRuleRelative> rule,
                              shared_ptr<CertificateCache> certificateCache, 
                              const int stepLimit)
@@ -34,6 +35,7 @@
   , m_anchor(anchor)
   , m_stepLimit(stepLimit)
   , m_certificateCache(certificateCache)
+  , m_publishCertCallback(publishCertCallback)
   , m_dataRule(rule)
 {
   if(!static_cast<bool>(face))
@@ -43,10 +45,10 @@
     m_certificateCache = make_shared<CertificateCacheTtl>(m_face->ioService());
 
   Name certPrefix = prefix;
-  certPrefix.append("intro-cert");
-  m_prefixId = m_face->setInterestFilter (certPrefix, 
-                                          bind(&SyncValidator::onCertInterest, this, _1, _2), 
-                                          bind(&SyncValidator::onCertRegisterFailed, this, _1, _2));
+  certPrefix.append("CHRONOS-INTRO-CERT");
+  m_prefixId = m_face->setInterestFilter(certPrefix, 
+                                         bind(&SyncValidator::onCertInterest, this, _1, _2), 
+                                         bind(&SyncValidator::onCertRegisterFailed, this, _1, _2));
 
   setAnchor(m_anchor);
 }
@@ -81,12 +83,12 @@
               // Check the nodes introduced by the trusted node.
               Edges::const_iterator edgeIt = m_introCerts.find(*eeIt);
               if(edgeIt != m_introCerts.end() 
-                 && m_trustedNodes.find(edgeIt->second.getIntroduceeName()) == m_trustedNodes.end()
+                 && m_trustedNodes.find(edgeIt->second.getIntroduceeCertName()) == m_trustedNodes.end()
                  && verifySignature(edgeIt->second, publicKey))
                 {
                   // If the introduced node can be validated, add it into trusted node set and the node queue.
-                  m_trustedNodes[edgeIt->second.getIntroduceeName()] = edgeIt->second.getIntroduceeCert().getPublicKeyInfo();
-                  nodeQueue.push(edgeIt->second.getIntroduceeName());
+                  m_trustedNodes[edgeIt->second.getIntroduceeCertName()] = edgeIt->second.getIntroduceeCert().getPublicKeyInfo();
+                  nodeQueue.push(edgeIt->second.getIntroduceeCertName());
                 }
             }
         }
@@ -105,7 +107,7 @@
     return onValidationFailed(data.shared_from_this(), 
                               "Maximum steps of validation reached: " + data.getName().toUri());
 
-  if(m_prefix.isPrefixOf(data.getName()))
+  if(m_prefix.isPrefixOf(data.getName()) || (static_cast<bool>(m_dataRule) && m_dataRule->satisfy(data)))
     {
       try
         {
@@ -123,8 +125,10 @@
             }
           else
             {
+              _LOG_DEBUG("I am: " << m_anchor.getName().get(0).toEscapedString() << " for " << data.getName()); 
+
               Name interestName = m_prefix;
-              interestName.append("intro-cert").append(keyLocatorName.wireEncode());
+              interestName.append("CHRONOS-INTRO-CERT").append(keyLocatorName.wireEncode());
               Interest interest(interestName);
               interest.setInterestLifetime(500);
 
@@ -155,41 +159,9 @@
                                     "Key Locator is not a name: " + data.getName().toUri());
         }
     }
-
-  if(static_cast<bool>(m_dataRule) && m_dataRule->satisfy(data))
-    {
-      try
-        {
-          SignatureSha256WithRsa sig(data.getSignature());
-          Name keyLocatorName = sig.getKeyLocator().getName();
-          
-          TrustNodes::const_iterator it = m_trustedNodes.find(keyLocatorName);
-          if(m_trustedNodes.end() != it)
-            {
-              if(verifySignature(data, sig, it->second))
-                return onValidated(data.shared_from_this());
-              else
-                return onValidationFailed(data.shared_from_this(), 
-                                          "Cannot verify signature: " + data.getName().toUri());
-            }
-          else
-            return onValidationFailed(data.shared_from_this(), 
-                                      "Signer cannot be trusted: " + keyLocatorName.toUri());
-        }
-      catch(SignatureSha256WithRsa::Error& e)
-        {
-          return onValidationFailed(data.shared_from_this(), 
-                                    "Not SignatureSha256WithRsa signature: " + string(e.what()));
-        }
-      catch(KeyLocator::Error& e)
-        {
-          return onValidationFailed(data.shared_from_this(),
-                                    "Key Locator is not a name: " + data.getName().toUri());
-        }
-    }
   else
     return onValidationFailed(data.shared_from_this(),
-                              "No data rule or rule is not satisfied: " + data.getName().toUri());
+                              "No rule or rule is not satisfied: " + data.getName().toUri());
 }
 
 void
diff --git a/src/sync-validator.h b/src/sync-validator.h
index b3cff00..7a6fc8f 100644
--- a/src/sync-validator.h
+++ b/src/sync-validator.h
@@ -23,6 +23,8 @@
 class SyncValidator : public ndn::Validator
 {
 public:
+  typedef ndn::function< void (const uint8_t*, size_t, int) > PublishCertCallback;
+
   struct Error : public ndn::Validator::Error { Error(const std::string &what) : ndn::Validator::Error(what) {} };
 
   static const ndn::shared_ptr<ndn::CertificateCache> DefaultCertificateCache;
@@ -31,6 +33,7 @@
   SyncValidator(const ndn::Name& prefix,
                 const ndn::IdentityCertificate& anchor,
                 ndn::shared_ptr<ndn::Face> face,
+                const PublishCertCallback& publishCertCallback,
                 ndn::shared_ptr<ndn::SecRuleRelative> rule = DefaultDataRule,
                 ndn::shared_ptr<ndn::CertificateCache> certificateCache = DefaultCertificateCache, 
                 const int stepLimit = 10);
@@ -74,6 +77,9 @@
   inline void
   addParticipant(const IntroCertificate& introCert);
 
+  inline void
+  getIntroCertNames(std::vector<ndn::Name>& list);
+
 #ifdef _TEST
   bool
   canTrust(const ndn::Name& certName)
@@ -144,6 +150,7 @@
   ndn::shared_ptr<ndn::CertificateCache> m_certificateCache;
   ndn::KeyChain m_keychain;
   const ndn::RegisteredPrefixId* m_prefixId;
+  PublishCertCallback m_publishCertCallback;
   ndn::shared_ptr<ndn::SecRuleRelative> m_dataRule;
 
   class IntroNode
@@ -162,12 +169,12 @@
     {
       if(isIntroducer)
         {
-          m_nodeName = introCert.getIntroducerName();
+          m_nodeName = introCert.getIntroducerCertName();
           m_introduceeCerts.push_back(introCert.getName());
         }
       else
         {
-          m_nodeName = introCert.getIntroduceeName();
+          m_nodeName = introCert.getIntroduceeCertName();
           m_introducerCerts.push_back(introCert.getName());
         }
     } 
@@ -253,7 +260,7 @@
   m_introCerts[certName] = introCert;
 
   // Check if the introducer has been added.
-  Nodes::iterator nodeIt = m_introNodes.find(introCert.getIntroducerName());
+  Nodes::iterator nodeIt = m_introNodes.find(introCert.getIntroducerCertName());
   if(nodeIt == m_introNodes.end())
     {
       IntroNode node(introCert, true);
@@ -263,7 +270,7 @@
     nodeIt->second.addIntroCertAsIntroducer(certName);
 
   // Check if the introducee has been added.
-  nodeIt = m_introNodes.find(introCert.getIntroduceeName());
+  nodeIt = m_introNodes.find(introCert.getIntroduceeCertName());
   if(nodeIt == m_introNodes.end())
     {
       IntroNode node(introCert, false);
@@ -273,24 +280,38 @@
     nodeIt->second.addIntroCertAsIntroducee(certName);
 
   // Check if the introducer is one of the trusted nodes.
-  TrustNodes::const_iterator trustNodeIt = m_trustedNodes.find(introCert.getIntroducerName());
+  TrustNodes::const_iterator trustNodeIt = m_trustedNodes.find(introCert.getIntroducerCertName());
   if(trustNodeIt != m_trustedNodes.end() && verifySignature(introCert, trustNodeIt->second))
     // If the introducee, add it into trusted node set.
-    m_trustedNodes[introCert.getIntroduceeName()] = introCert.getIntroduceeCert().getPublicKeyInfo();
+    m_trustedNodes[introCert.getIntroduceeCertName()] = introCert.getIntroduceeCert().getPublicKeyInfo();
 }
 
 inline ndn::shared_ptr<const IntroCertificate>
 SyncValidator::addParticipant(const ndn::IdentityCertificate& introducee)
 {
-  ndn::shared_ptr<IntroCertificate> introCert = ndn::make_shared<IntroCertificate>(m_prefix, introducee, m_anchor.getName().getPrefix(-1));
+  ndn::shared_ptr<IntroCertificate> introCert
+    = ndn::shared_ptr<IntroCertificate>(new IntroCertificate(m_prefix, introducee, m_anchor.getName().getPrefix(-1)));
 
   m_keychain.sign(*introCert, m_anchor.getName());
   
   addParticipant(*introCert);
 
+  // Publish certificate as normal data.
+  ndn::Block block = introCert->wireEncode();
+  m_publishCertCallback(block.wire(), block.size(), 1000);
+
   return introCert;
 }
 
+inline void
+SyncValidator::getIntroCertNames(std::vector<ndn::Name>& list)
+{
+  Edges::const_iterator it = m_introCerts.begin();
+  Edges::const_iterator end = m_introCerts.end();
+  for(; it != end; it++)
+    list.push_back(it->first);
+}
+
 } // namespace Sync
 
 #endif //SYNC_VALIDATOR_H
diff --git a/tests/test-socket.cc b/tests/test-socket.cc
index e4791c2..a10a2f1 100644
--- a/tests/test-socket.cc
+++ b/tests/test-socket.cc
@@ -142,93 +142,94 @@
     : m_face1(new ndn::Face(ioService))
     , m_face2(new ndn::Face(ioService))
     , m_face3(new ndn::Face(ioService))
-    , m_p1("/irl.cs.ucla.edu")
-    , m_p2("/yakshi.org")
-    , m_p3("/google.com")
-    , m_syncPrefix("/let/us/sync")
+    , m_name1("/irl.cs.ucla.edu/" + boost::lexical_cast<std::string>(ndn::time::now()))
+    , m_name2("/yakshi.org/" + boost::lexical_cast<std::string>(ndn::time::now()))
+    , m_name3("/google.com/" + boost::lexical_cast<std::string>(ndn::time::now()))
   {
-    ndn::KeyChain keyChain;
-    m_name1 = m_p1;
-    m_name1.append(boost::lexical_cast<std::string>(ndn::time::now()));
-    ndn::Name certName1 = keyChain.createIdentity(m_name1);
-    m_id1 = keyChain.getCertificate(certName1);
+    m_id1 = m_keyChain.getCertificate(m_keyChain.createIdentity(m_name1));
+    m_id2 = m_keyChain.getCertificate(m_keyChain.createIdentity(m_name2));
+    m_id3 = m_keyChain.getCertificate(m_keyChain.createIdentity(m_name3));
 
-    m_name2 = m_p2;
-    m_name2.append(boost::lexical_cast<std::string>(ndn::time::now()));
-    ndn::Name certName2 = keyChain.createIdentity(m_name2);
-    m_id2 = keyChain.getCertificate(certName2);
-
-    m_name3 = m_p3;
-    m_name3.append(boost::lexical_cast<std::string>(ndn::time::now()));
-    ndn::Name certName3 = keyChain.createIdentity(m_name3);
-    m_id3 = keyChain.getCertificate(certName3);
-
-    ndn::shared_ptr<ndn::SecRuleRelative> rule = ndn::make_shared<ndn::SecRuleRelative>("^(<>*)<><>$",
-                                                                                        "^(<>*)<><KEY><ksk-.*><ID-CERT>$",
-                                                                                        "==", "\\1", "\\1", true);
-
-    m_v1 = ndn::make_shared<SyncValidator>(m_syncPrefix, *m_id1, m_face1, rule);
-    m_v1->addParticipant(*m_id2);
-    m_v2 = ndn::make_shared<SyncValidator>(m_syncPrefix, *m_id2, m_face2, rule);
-    m_v2->addParticipant(*m_id1);
-    m_v2->addParticipant(*m_id3);
-    m_v3 = ndn::make_shared<SyncValidator>(m_syncPrefix, *m_id3, m_face3, rule);
-    m_v3->addParticipant(*m_id2);
+    m_rule = ndn::make_shared<ndn::SecRuleRelative>("^(<>*)<><>$",
+                                                    "^(<>*)<><KEY><ksk-.*><ID-CERT>$",
+                                                    "==", "\\1", "\\1", true);
   }
 
   void
   createSyncSocket1()
   {
     _LOG_DEBUG ("s1");
-    m_s1 = ndn::make_shared<SyncSocket>(m_syncPrefix, m_name1, m_v1, m_face1, 
-                                   bind(&TestSocketApp::fetchAll, &m_a1, _1, _2), 
-                                   bind(&TestSocketApp::pass, &m_a1, _1));
+
+    m_s1 = ndn::make_shared<SyncSocket>("/let/us/sync",
+                                        "/irl.cs.ucla.edu",
+                                        0,
+                                        *m_id1,
+                                        m_rule,
+                                        m_face1,
+                                        bind(&TestSocketApp::fetchAll, &m_a1, _1, _2), 
+                                        bind(&TestSocketApp::pass, &m_a1, _1));
+    m_s1->addParticipant(*m_id2);
   }
 
   void
   createSyncSocket2()
   {
     _LOG_DEBUG ("s2");
-    m_s2 = ndn::make_shared<SyncSocket>(m_syncPrefix, m_name2, m_v2, m_face2, 
-                                   bind(&TestSocketApp::fetchAll, &m_a2, _1, _2), 
-                                   bind(&TestSocketApp::pass, &m_a2, _1));
+
+    m_s2 = ndn::make_shared<SyncSocket>("/let/us/sync",
+                                        "/yakshi.org",
+                                        0,
+                                        *m_id2,
+                                        m_rule,
+                                        m_face2,
+                                        bind(&TestSocketApp::fetchAll, &m_a2, _1, _2), 
+                                        bind(&TestSocketApp::pass, &m_a2, _1));
+    m_s2->addParticipant(*m_id1);
+    m_s2->addParticipant(*m_id3);
   }
   
   void
   createSyncSocket3()
   {
     _LOG_DEBUG ("s3");
-    m_s3 = ndn::make_shared<SyncSocket>(m_syncPrefix, m_name3, m_v3, m_face3, 
-                                   bind(&TestSocketApp::fetchAll, &m_a3, _1, _2), 
-                                   bind(&TestSocketApp::pass, &m_a3, _1));
+
+    m_s3 = ndn::make_shared<SyncSocket>("/let/us/sync",
+                                        "/google.com",
+                                        0,
+                                        *m_id3,
+                                        m_rule, 
+                                        m_face3, 
+                                        bind(&TestSocketApp::fetchAll, &m_a3, _1, _2), 
+                                        bind(&TestSocketApp::pass, &m_a3, _1));
+    m_s3->addParticipant(*m_id2);
   }
 
   void
-  publishSocket1(uint32_t session, string data)
+  publishSocket1(string data)
   {
     _LOG_DEBUG ("s1 publish");
-    m_s1->publishData (m_p1, session, data.c_str(), data.size(), 1000); 
+    m_s1->publishData (reinterpret_cast<const uint8_t*>(data.c_str()), data.size(), 1000); 
   }
 
   void
-  publishSocket2(uint32_t session, string data)
+  publishSocket2(string data)
   {
     _LOG_DEBUG ("s2 publish");
-    m_s2->publishData (m_p2, session, data.c_str(), data.size(), 1000); 
+    m_s2->publishData (reinterpret_cast<const uint8_t*>(data.c_str()), data.size(), 1000); 
   }
 
   void
-  publishSocket3(uint32_t session, string data)
+  publishSocket3(string data)
   {
     _LOG_DEBUG ("s3 publish");
-    m_s3->publishData (m_p3, session, data.c_str(), data.size(), 1000); 
+    m_s3->publishData (reinterpret_cast<const uint8_t*>(data.c_str()), data.size(), 1000); 
   }
 
   void
   setSocket1(string suffix, string data)
   {
     _LOG_DEBUG ("a1 set");
-    ndn::Name name = m_p1;
+    ndn::Name name("/irl.cs.ucla.edu");
     name.append(suffix);
     m_a1.set (name, data.c_str(), data.size()); 
   }
@@ -237,7 +238,7 @@
   setSocket2(string suffix, string data)
   {
     _LOG_DEBUG ("a2 set");
-    ndn::Name name = m_p2;
+    ndn::Name name("/yakshi.org");
     name.append(suffix);
     m_a2.set (name, data.c_str(), data.size()); 
   }
@@ -246,7 +247,7 @@
   setSocket3(string suffix, string data)
   {
     _LOG_DEBUG ("a3 set");
-    ndn::Name name = m_p3;
+    ndn::Name name("/google.com");
     name.append(suffix);
     m_a3.set (name, data.c_str(), data.size()); 
   }
@@ -264,26 +265,21 @@
     m_s1.reset();
     m_s2.reset();
     m_s3.reset();
-    m_v1.reset();
-    m_v2.reset();
-    m_v3.reset();
 
-    ndn::KeyChain keyChain;
-    keyChain.deleteIdentity(m_name1);
-    keyChain.deleteIdentity(m_name2);
-    keyChain.deleteIdentity(m_name3);
+    m_keyChain.deleteIdentity(m_name1);
+    m_keyChain.deleteIdentity(m_name2);
+    m_keyChain.deleteIdentity(m_name3);
 
   }
 
+  ndn::KeyChain m_keyChain;
+  ndn::shared_ptr<ndn::SecRuleRelative> m_rule;
 
-  TestSocketApp m_a1, m_a2, m_a3;
-  ndn::shared_ptr<ndn::IdentityCertificate> m_id1, m_id2, m_id3;
-  ndn::shared_ptr<Sync::SyncValidator> m_v1, m_v2, m_v3;
   ndn::shared_ptr<ndn::Face> m_face1, m_face2, m_face3;
   ndn::Name m_name1, m_name2, m_name3;
-  ndn::Name m_p1, m_p2, m_p3;
+  TestSocketApp m_a1, m_a2, m_a3;
+  ndn::shared_ptr<ndn::IdentityCertificate> m_id1, m_id2, m_id3;
   ndn::shared_ptr<SyncSocket> m_s1, m_s2, m_s3;
-  ndn::Name m_syncPrefix;
 };
 
 class TestSet2{
@@ -291,76 +287,77 @@
   TestSet2(ndn::shared_ptr<boost::asio::io_service> ioService)
     : m_face1(new ndn::Face(ioService))
     , m_face2(new ndn::Face(ioService))
-    , m_p1("/xiaonei.com")
-    , m_p2("/mitbbs.com")
-    , m_syncPrefix("/this/is/the/prefix")
+    , m_name1("/xiaonei.com/" + boost::lexical_cast<std::string>(ndn::time::now()))
+    , m_name2("/mitbbs.com/" + boost::lexical_cast<std::string>(ndn::time::now()))
   {
-    ndn::KeyChain keyChain;
-    m_name1 = m_p1;
-    m_name1.append(boost::lexical_cast<string>(ndn::time::now()));
-    ndn::Name certName1 = keyChain.createIdentity(m_name1);
-    m_id1 = keyChain.getCertificate(certName1);
+    m_id1 = m_keyChain.getCertificate(m_keyChain.createIdentity(m_name1));
+    m_id2 = m_keyChain.getCertificate(m_keyChain.createIdentity(m_name2));
 
-    m_name2 = m_p2;
-    m_name2.append(boost::lexical_cast<string>(ndn::time::now()));
-    ndn::Name certName2 = keyChain.createIdentity(m_name2);
-    m_id2 = keyChain.getCertificate(certName2);
-
-    ndn::shared_ptr<ndn::SecRuleRelative> rule = ndn::make_shared<ndn::SecRuleRelative>("^(<>*)<><>$",
-                                                                                        "^(<>*)<><KEY><ksk-.*><ID-CERT>$",
-                                                                                        "==", "\\1", "\\1", true);
-
-    m_v1 = ndn::make_shared<SyncValidator>(m_syncPrefix, *m_id1, m_face1, rule);
-    m_v1->addParticipant(*m_id2);
-    m_v2 = ndn::make_shared<SyncValidator>(m_syncPrefix, *m_id2, m_face2, rule);
-    m_v2->addParticipant(*m_id1);
-
+    m_rule = ndn::make_shared<ndn::SecRuleRelative>("^(<>*)<><>$",
+                                                    "^(<>*)<><KEY><ksk-.*><ID-CERT>$",
+                                                    "==", "\\1", "\\1", true);
   }
 
   void
   createSyncSocket1()
   {
     _LOG_DEBUG ("s1");
-    m_s1 = ndn::make_shared<SyncSocket>(m_syncPrefix, m_name1, m_v1, m_face1, 
-                                   bind(&TestSocketApp::fetchNumbers, &m_a1, _1, _2), 
-                                   bind(&TestSocketApp::pass, &m_a1, _1));
+    
+    m_s1 = ndn::make_shared<SyncSocket>("/this/is/the/prefix",
+                                        "/xiaonei.com",
+                                        0,
+                                        *m_id1,
+                                        m_rule,
+                                        m_face1,
+                                        bind(&TestSocketApp::fetchNumbers, &m_a1, _1, _2), 
+                                        bind(&TestSocketApp::pass, &m_a1, _1));
+
+    m_s1->addParticipant(*m_id2);
   }
 
   void
   createSyncSocket2()
   {
     _LOG_DEBUG ("s2");
-    m_s2 = ndn::make_shared<SyncSocket>(m_syncPrefix, m_name2, m_v2, m_face2, 
-                                   bind(&TestSocketApp::fetchNumbers, &m_a2, _1, _2), 
-                                   bind(&TestSocketApp::pass, &m_a2, _1));
+
+    m_s2 = ndn::make_shared<SyncSocket>("/this/is/the/prefix",
+                                        "/mitbbs.com",
+                                        0,
+                                        *m_id2,
+                                        m_rule,
+                                        m_face2,
+                                        bind(&TestSocketApp::fetchNumbers, &m_a2, _1, _2), 
+                                        bind(&TestSocketApp::pass, &m_a2, _1));
+
+    m_s2->addParticipant(*m_id1);
   }
   
   void
-  publishSocket1(uint32_t session, string data)
+  publishSocket1(string data)
   {
     _LOG_DEBUG ("s1 publish");
-    m_s1->publishData (m_p1, session, data.c_str(), data.size(), 1000); 
+    m_s1->publishData (reinterpret_cast<const uint8_t*>(data.c_str()), data.size(), 1000); 
   }
 
   void
-  publishSocket2(uint32_t session, string data)
+  publishSocket2(string data)
   {
     _LOG_DEBUG ("s2 publish");
-    m_s2->publishData (m_p2, session, data.c_str(), data.size(), 1000); 
+    m_s2->publishData (reinterpret_cast<const uint8_t*>(data.c_str()), data.size(), 1000); 
   }
 
   void
   setSocket1(const char* ptr, size_t size)
   {
     _LOG_DEBUG ("a1 setNum");
-    m_a1.setNum (m_p1, ptr, size); 
+    m_a1.setNum ("/xiaonei.com", ptr, size); 
   }
 
   void
   setSocket2(const char* ptr, size_t size)
   {
     _LOG_DEBUG ("a2 setNum");
-    m_a2.setNum (m_p2, ptr, size); 
+    m_a2.setNum ("/mitbbs.com", ptr, size); 
   }
 
   void
@@ -378,22 +375,19 @@
   {
     m_s1.reset();
     m_s2.reset();
-    m_v1.reset();
-    m_v2.reset();
 
-    ndn::KeyChain keyChain;
-    keyChain.deleteIdentity(m_name1);
-    keyChain.deleteIdentity(m_name2);
+    m_keyChain.deleteIdentity(m_name1);
+    m_keyChain.deleteIdentity(m_name2);
   }
 
+  ndn::KeyChain m_keyChain;
+  ndn::shared_ptr<ndn::SecRuleRelative> m_rule;
+
   TestSocketApp m_a1, m_a2;
   ndn::shared_ptr<ndn::IdentityCertificate> m_id1, m_id2;
-  ndn::shared_ptr<Sync::SyncValidator> m_v1, m_v2;
   ndn::shared_ptr<ndn::Face> m_face1, m_face2;
-  ndn::Name m_p1, m_p2;
   ndn::Name m_name1, m_name2;
   ndn::shared_ptr<SyncSocket> m_s1, m_s2;
-  ndn::Name m_syncPrefix;
 };
 
 BOOST_AUTO_TEST_CASE (AppSocketTest1)
@@ -408,34 +402,34 @@
   scheduler.scheduleEvent(ndn::time::seconds(0.05), ndn::bind(&TestSet1::createSyncSocket2, &testSet1));
   scheduler.scheduleEvent(ndn::time::seconds(0.10), ndn::bind(&TestSet1::createSyncSocket3, &testSet1));
   string data0 = "Very funny Scotty, now beam down my clothes";
-  scheduler.scheduleEvent(ndn::time::seconds(0.15), ndn::bind(&TestSet1::publishSocket1, &testSet1, 0, data0));
-  scheduler.scheduleEvent(ndn::time::seconds(1.15), ndn::bind(&TestSet1::setSocket1, &testSet1, "/0/0", data0));
+  scheduler.scheduleEvent(ndn::time::seconds(0.15), ndn::bind(&TestSet1::publishSocket1, &testSet1, data0));
+  scheduler.scheduleEvent(ndn::time::seconds(1.15), ndn::bind(&TestSet1::setSocket1, &testSet1, "/0/1", data0));
   scheduler.scheduleEvent(ndn::time::seconds(1.16), ndn::bind(&TestSet1::check, &testSet1, 1)); 
   string data1 = "Yes, give me that ketchup";
   string data2 = "Don't look conspicuous, it draws fire";
-  scheduler.scheduleEvent(ndn::time::seconds(1.17), ndn::bind(&TestSet1::publishSocket1, &testSet1, 0, data1));
-  scheduler.scheduleEvent(ndn::time::seconds(1.18), ndn::bind(&TestSet1::publishSocket1, &testSet1, 0, data2));
-  scheduler.scheduleEvent(ndn::time::seconds(2.15), ndn::bind(&TestSet1::setSocket1, &testSet1, "/0/1", data1));
-  scheduler.scheduleEvent(ndn::time::seconds(2.16), ndn::bind(&TestSet1::setSocket1, &testSet1, "/0/2", data2));
+  scheduler.scheduleEvent(ndn::time::seconds(1.17), ndn::bind(&TestSet1::publishSocket1, &testSet1, data1));
+  scheduler.scheduleEvent(ndn::time::seconds(1.18), ndn::bind(&TestSet1::publishSocket1, &testSet1, data2));
+  scheduler.scheduleEvent(ndn::time::seconds(2.15), ndn::bind(&TestSet1::setSocket1, &testSet1, "/0/2", data1));
+  scheduler.scheduleEvent(ndn::time::seconds(2.16), ndn::bind(&TestSet1::setSocket1, &testSet1, "/0/3", data2));
   scheduler.scheduleEvent(ndn::time::seconds(2.17), ndn::bind(&TestSet1::check, &testSet1, 2));
   string data3 = "You surf the Internet, I surf the real world";
   string data4 = "I got a fortune cookie once that said 'You like Chinese food'";
   string data5 = "Real men wear pink. Why? Because their wives make them";
-  scheduler.scheduleEvent(ndn::time::seconds(3.18), ndn::bind(&TestSet1::publishSocket3, &testSet1, 0, data3));
-  scheduler.scheduleEvent(ndn::time::seconds(3.20), ndn::bind(&TestSet1::publishSocket2, &testSet1, 0, data4));
-  scheduler.scheduleEvent(ndn::time::seconds(3.21), ndn::bind(&TestSet1::publishSocket2, &testSet1, 0, data5));
-  scheduler.scheduleEvent(ndn::time::seconds(4.21), ndn::bind(&TestSet1::setSocket3, &testSet1, "/0/0", data3));
-  scheduler.scheduleEvent(ndn::time::seconds(4.22), ndn::bind(&TestSet1::setSocket2, &testSet1, "/0/0", data4));
-  scheduler.scheduleEvent(ndn::time::seconds(4.23), ndn::bind(&TestSet1::setSocket2, &testSet1, "/0/1", data5));
-  scheduler.scheduleEvent(ndn::time::seconds(4.30), ndn::bind(&TestSet1::check, &testSet1, 3));
+  scheduler.scheduleEvent(ndn::time::seconds(3.18), ndn::bind(&TestSet1::publishSocket3, &testSet1, data3));
+  scheduler.scheduleEvent(ndn::time::seconds(3.20), ndn::bind(&TestSet1::publishSocket2, &testSet1, data4));
+  scheduler.scheduleEvent(ndn::time::seconds(3.21), ndn::bind(&TestSet1::publishSocket2, &testSet1, data5));
+  scheduler.scheduleEvent(ndn::time::seconds(4.71), ndn::bind(&TestSet1::setSocket3, &testSet1, "/0/1", data3));
+  scheduler.scheduleEvent(ndn::time::seconds(4.72), ndn::bind(&TestSet1::setSocket2, &testSet1, "/0/2", data4));
+  scheduler.scheduleEvent(ndn::time::seconds(4.73), ndn::bind(&TestSet1::setSocket2, &testSet1, "/0/3", data5));
+  scheduler.scheduleEvent(ndn::time::seconds(4.80), ndn::bind(&TestSet1::check, &testSet1, 3));
   // not sure weither this is simultanous data generation from multiple sources
   _LOG_DEBUG ("Simultaneous publishing");
   string data6 = "Shakespeare says: 'Prose before hos.'";
   string data7 = "Pick good people, talent never wears out";
-  scheduler.scheduleEvent(ndn::time::seconds(5.50), ndn::bind(&TestSet1::publishSocket1, &testSet1, 0, data6));
-  scheduler.scheduleEvent(ndn::time::seconds(5.50), ndn::bind(&TestSet1::publishSocket2, &testSet1, 0, data7));
-  scheduler.scheduleEvent(ndn::time::seconds(6.80), ndn::bind(&TestSet1::setSocket1, &testSet1, "/0/3", data6));
-  scheduler.scheduleEvent(ndn::time::seconds(6.80), ndn::bind(&TestSet1::setSocket2, &testSet1, "/0/2", data7));
+  scheduler.scheduleEvent(ndn::time::seconds(5.50), ndn::bind(&TestSet1::publishSocket1, &testSet1, data6));
+  scheduler.scheduleEvent(ndn::time::seconds(5.50), ndn::bind(&TestSet1::publishSocket2, &testSet1, data7));
+  scheduler.scheduleEvent(ndn::time::seconds(6.80), ndn::bind(&TestSet1::setSocket1, &testSet1, "/0/4", data6));
+  scheduler.scheduleEvent(ndn::time::seconds(6.80), ndn::bind(&TestSet1::setSocket2, &testSet1, "/0/4", data7));
   scheduler.scheduleEvent(ndn::time::seconds(6.90), ndn::bind(&TestSet1::check, &testSet1, 4));
   scheduler.scheduleEvent(ndn::time::seconds(7.00), ndn::bind(&TestSet1::done, &testSet1));
 
@@ -452,12 +446,12 @@
   scheduler.scheduleEvent(ndn::time::seconds(0.05), ndn::bind(&TestSet2::createSyncSocket2, &testSet2));
   uint32_t num[5] = {0, 1, 2, 3, 4};
   string data0((const char *) num, sizeof(num));
-  scheduler.scheduleEvent(ndn::time::seconds(0.10), ndn::bind(&TestSet2::publishSocket1, &testSet2, 0, data0));
+  scheduler.scheduleEvent(ndn::time::seconds(0.10), ndn::bind(&TestSet2::publishSocket1, &testSet2, data0));
   scheduler.scheduleEvent(ndn::time::seconds(0.15), ndn::bind(&TestSet2::setSocket1, &testSet2, (const char *) num, sizeof (num)));
   scheduler.scheduleEvent(ndn::time::seconds(1.00), ndn::bind(&TestSet2::check, &testSet2, 10));
   uint32_t newNum[5] = {9, 7, 2, 1, 1};
   string data1((const char *) newNum, sizeof(newNum));
-  scheduler.scheduleEvent(ndn::time::seconds(1.10), ndn::bind(&TestSet2::publishSocket2, &testSet2, 0, data1));
+  scheduler.scheduleEvent(ndn::time::seconds(1.10), ndn::bind(&TestSet2::publishSocket2, &testSet2, data1));
   scheduler.scheduleEvent(ndn::time::seconds(1.15), ndn::bind(&TestSet2::setSocket2, &testSet2, (const char *) newNum, sizeof (newNum)));
   scheduler.scheduleEvent(ndn::time::seconds(2.00), ndn::bind(&TestSet2::check, &testSet2, 30));
   scheduler.scheduleEvent(ndn::time::seconds(7.00), ndn::bind(&TestSet2::done, &testSet2));
diff --git a/tests/test-sync-logic.cc b/tests/test-sync-logic.cc
index 76c5fc5..ebce9c0 100644
--- a/tests/test-sync-logic.cc
+++ b/tests/test-sync-logic.cc
@@ -102,10 +102,10 @@
                   ndn::shared_ptr<Handler> h)
   { 
     ndn::Name identity("/tmp-" + boost::lexical_cast<std::string>(ndn::time::now()));
-    m_keyChain.createIdentity(identity);
+    ndn::shared_ptr<ndn::IdentityCertificate> cert = m_keyChain.getCertificate(m_keyChain.createIdentity(identity));
     m_faces[index] = ndn::make_shared<ndn::Face>(m_ioService);
     m_l[index] = new SyncLogic(ndn::Name("/bcast"), 
-                               identity,
+                               *cert,
                                m_validator, m_faces[index], 
                                bind (&Handler::wrapper, &*h, _1), 
                                bind (&Handler::onRemove, &*h, _1)); 
diff --git a/tests/test-sync-validator.cc b/tests/test-sync-validator.cc
index ca7078b..9049edc 100644
--- a/tests/test-sync-validator.cc
+++ b/tests/test-sync-validator.cc
@@ -8,28 +8,37 @@
 
 BOOST_AUTO_TEST_SUITE(TestSyncValidator)
 
-void onValidated(const ndn::shared_ptr<const ndn::Data>& data)
+void 
+onValidated(const ndn::shared_ptr<const ndn::Data>& data)
 {
   BOOST_CHECK(true);
 }
 
-void onValidationFailed(const ndn::shared_ptr<const ndn::Data>& data,
-			const std::string& failureInfo)
+void 
+onValidationFailed(const ndn::shared_ptr<const ndn::Data>& data,
+                   const std::string& failureInfo)
 {
   BOOST_CHECK(false);
 }
 
-void onValidated2(const ndn::shared_ptr<const ndn::Data>& data)
+void 
+onValidated2(const ndn::shared_ptr<const ndn::Data>& data)
 {
   BOOST_CHECK(false);
 }
 
-void onValidationFailed2(const ndn::shared_ptr<const ndn::Data>& data,
-			const std::string& failureInfo)
+void 
+onValidationFailed2(const ndn::shared_ptr<const ndn::Data>& data,
+                    const std::string& failureInfo)
 {
   BOOST_CHECK(true);
 }
 
+void 
+publishData(const uint8_t* buf, size_t len, int freshness)
+{
+}
+
 BOOST_AUTO_TEST_CASE (Graph)
 {
   using namespace Sync;
@@ -60,7 +69,10 @@
 
   shared_ptr<boost::asio::io_service> ioService = make_shared<boost::asio::io_service>();
   shared_ptr<Face> face = make_shared<Face>(ioService);
-  SyncValidator validator(prefix, *anchor, face);
+  shared_ptr<SecRuleRelative> rule;
+  SyncValidator validator(prefix, *anchor, face, 
+                          bind(&publishData, _1, _2, _3),
+                          rule);
 
   validator.addParticipant(*introducer);
   BOOST_CHECK(validator.canTrust(certName2));
@@ -135,7 +147,10 @@
 
   shared_ptr<boost::asio::io_service> ioService = make_shared<boost::asio::io_service>();
   shared_ptr<Face> face = make_shared<Face>(ioService);
-  SyncValidator validator(prefix, *anchor, face);
+  shared_ptr<SecRuleRelative> rule;
+  SyncValidator validator(prefix, *anchor, face,
+                          bind(&publishData, _1, _2, _3),
+                          rule);
 
   validator.addParticipant(*introducer);
   BOOST_CHECK(validator.canTrust(certName2));
@@ -211,7 +226,10 @@
 
   shared_ptr<boost::asio::io_service> ioService = make_shared<boost::asio::io_service>();
   shared_ptr<Face> face = make_shared<Face>(ioService);
-  SyncValidator validator(prefix, *anchor, face);
+  shared_ptr<SecRuleRelative> rule;
+  SyncValidator validator(prefix, *anchor, face,
+                          bind(&publishData, _1, _2, _3),
+                          rule);
 
   validator.addParticipant(*introducer);
   BOOST_CHECK(validator.canTrust(certName2));