diff --git a/nsync/sync-logic.cc b/nsync/sync-logic.cc
new file mode 100644
index 0000000..3038532
--- /dev/null
+++ b/nsync/sync-logic.cc
@@ -0,0 +1,708 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Chaoyi Bian <bcy@pku.edu.cn>
+ *	   Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ *         Yingdi Yu <yingdi@cs.ucla.edu>
+ */
+
+#include "sync-logic.h"
+#include "sync-diff-leaf.h"
+#include "sync-full-leaf.h"
+#include "sync-logging.h"
+#include "sync-state.h"
+
+#include <boost/foreach.hpp>
+#include <boost/lexical_cast.hpp>
+#include <vector>
+
+using namespace std;
+using namespace ndn;
+
+INIT_LOGGER ("SyncLogic");
+
+
+#ifdef _DEBUG
+#define _LOG_DEBUG_ID(v) _LOG_DEBUG(m_instanceId << " " << v)
+#else
+#define _LOG_DEBUG_ID(v) _LOG_DEBUG(v)
+#endif
+
+#define GET_RANDOM(var) var ()
+
+#define TIME_SECONDS_WITH_JITTER(sec) \
+  (time::seconds(sec) + time::milliseconds(GET_RANDOM (m_reexpressionJitter)))
+
+#define TIME_MILLISECONDS_WITH_JITTER(ms) \
+  (time::seconds(ms) + time::milliseconds(GET_RANDOM (m_reexpressionJitter)))
+
+namespace Sync {
+
+using ndn::shared_ptr;
+
+int SyncLogic::m_instanceCounter = 0;
+
+const int SyncLogic::m_syncResponseFreshness = 1000; // MUST BE dividable by 1000!!!
+const int SyncLogic::m_syncInterestReexpress = 4; // seconds
+
+SyncLogic::SyncLogic (const Name& syncPrefix,
+                      shared_ptr<Validator> validator,
+                      shared_ptr<Face> face,
+                      LogicUpdateCallback onUpdate,
+                      LogicRemoveCallback onRemove)
+  : m_state (new FullState)
+  , m_syncInterestTable (*face->ioService(), time::seconds(m_syncInterestReexpress))
+  , m_syncPrefix (syncPrefix)
+  , 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)))
+  , m_rangeUniformRandom (m_randomGenerator, boost::uniform_int<> (200,1000))
+  , m_reexpressionJitter (m_randomGenerator, boost::uniform_int<> (100,500))
+  , m_recoveryRetransmissionInterval (m_defaultRecoveryRetransmitInterval)
+{
+  m_syncRegisteredPrefixId = m_face->setInterestFilter (m_syncPrefix,
+                                                        bind(&SyncLogic::onSyncInterest, this, _1, _2),
+                                                        bind(&SyncLogic::onSyncRegisterFailed, this, _1, _2));
+
+
+  m_reexpressingInterestId = m_scheduler.scheduleEvent (time::seconds (0), // no need to add jitter
+                                                        bind (&SyncLogic::sendSyncInterest, this));
+
+  m_instanceId = string("Instance " + boost::lexical_cast<string>(m_instanceCounter++) + " ");
+}
+
+SyncLogic::SyncLogic (const Name& syncPrefix,
+                      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_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)))
+  , m_rangeUniformRandom (m_randomGenerator, boost::uniform_int<> (200,1000))
+  , m_reexpressionJitter (m_randomGenerator, boost::uniform_int<> (100,500))
+  , m_recoveryRetransmissionInterval (m_defaultRecoveryRetransmitInterval)
+{
+  m_syncRegisteredPrefixId = m_face->setInterestFilter (m_syncPrefix,
+                                                        bind(&SyncLogic::onSyncInterest, this, _1, _2),
+                                                        bind(&SyncLogic::onSyncRegisterFailed, this, _1, _2));
+
+  m_reexpressingInterestId = m_scheduler.scheduleEvent (time::seconds (0), // no need to add jitter
+                                                        bind (&SyncLogic::sendSyncInterest, this));
+}
+
+SyncLogic::~SyncLogic ()
+{
+  m_face->unsetInterestFilter(m_syncRegisteredPrefixId);
+  m_scheduler.cancelEvent (m_reexpressingInterestId);
+  m_scheduler.cancelEvent (m_delayedInterestProcessingId);
+}
+
+/**
+ * Two types of intersts
+ *
+ * Normal name:    .../<hash>
+ * Recovery name:  .../recovery/<hash>
+ */
+boost::tuple<DigestConstPtr, std::string>
+SyncLogic::convertNameToDigestAndType (const Name &name)
+{
+  BOOST_ASSERT (m_syncPrefix.isPrefixOf(name));
+
+  int nameLengthDiff = name.size() - m_syncPrefix.size();
+  BOOST_ASSERT (nameLengthDiff > 0);
+  BOOST_ASSERT (nameLengthDiff < 3);
+
+  string hash = name.get(-1).toEscapedString();
+  string interestType;
+
+  if(nameLengthDiff == 1)
+    interestType = "normal";
+  else
+    interestType = name.get(-2).toEscapedString();
+
+  _LOG_DEBUG_ID (hash << ", " << interestType);
+
+  DigestPtr digest = boost::make_shared<Digest> ();
+  istringstream is (hash);
+  is >> *digest;
+
+  return make_tuple (digest, interestType);
+}
+
+void
+SyncLogic::onSyncInterest (const Name& prefix, const ndn::Interest& interest)
+{
+  Name name = interest.getName();
+
+  _LOG_DEBUG_ID("respondSyncInterest: " << name);
+
+  try
+    {
+      _LOG_DEBUG_ID ("<< I " << name);
+
+      DigestConstPtr digest;
+      string type;
+      tie (digest, type) = convertNameToDigestAndType (name);
+
+      if (type == "normal") // kind of ineffective...
+        {
+          processSyncInterest (name, digest);
+        }
+      else if (type == "recovery")
+        {
+          processSyncRecoveryInterest (name, digest);
+        }
+    }
+  catch (Error::DigestCalculationError &e)
+    {
+      _LOG_DEBUG_ID ("Something fishy happened...");
+      // log error. ignoring it for now, later we should log it
+      return ;
+    }
+}
+
+void
+SyncLogic::onSyncRegisterFailed(const Name& prefix, const string& msg)
+{
+  _LOG_DEBUG_ID("Sync prefix registration failed! " << msg);
+}
+
+void
+SyncLogic::onSyncData(const ndn::Interest& interest, Data& data)
+{
+  OnDataValidated onValidated = bind(&SyncLogic::onSyncDataValidated, this, _1);
+  OnDataValidationFailed onValidationFailed = bind(&SyncLogic::onSyncDataValidationFailed, this, _1);
+  m_validator->validate(data, onValidated, onValidationFailed);
+}
+
+void
+SyncLogic::onSyncTimeout(const ndn::Interest& interest)
+{
+  // It is OK. Others will handle the time out situation.
+}
+
+void
+SyncLogic::onSyncDataValidationFailed(const shared_ptr<const Data>& data)
+{
+  _LOG_DEBUG_ID("Sync data cannot be verified!");
+}
+
+void
+SyncLogic::onSyncDataValidated(const shared_ptr<const Data>& data)
+{
+  Name name = data->getName();
+  const char* wireData = (const char*)data->getContent().value();
+  size_t len = data->getContent().value_size();
+
+  try
+    {
+      _LOG_DEBUG_ID ("<< D " << name);
+
+      DigestConstPtr digest;
+      string type;
+      tie (digest, type) = convertNameToDigestAndType (name);
+
+      if (type == "normal")
+        {
+          processSyncData (name, digest, wireData, len);
+        }
+      else
+        {
+          // timer is always restarted when we schedule recovery
+          m_scheduler.cancelEvent (m_reexpressingRecoveryInterestId);
+          processSyncData (name, digest, wireData, len);
+        }
+    }
+  catch (Error::DigestCalculationError &e)
+    {
+      _LOG_DEBUG_ID ("Something fishy happened...");
+      // log error. ignoring it for now, later we should log it
+      return;
+    }
+}
+
+void
+SyncLogic::processSyncInterest (const Name &name, DigestConstPtr digest, bool timedProcessing/*=false*/)
+{
+  _LOG_DEBUG_ID("processSyncInterest");
+  DigestConstPtr rootDigest;
+  {
+    rootDigest = m_state->getDigest();
+  }
+
+  // Special case when state is not empty and we have received request with zero-root digest
+  if (digest->isZero () && !rootDigest->isZero ())
+    {
+
+      SyncStateMsg ssm;
+      {
+        ssm << (*m_state);
+      }
+      sendSyncData (name, digest, ssm);
+      return;
+    }
+
+  if (*rootDigest == *digest)
+    {
+      _LOG_DEBUG_ID ("processSyncInterest (): Same state. Adding to PIT");
+      m_syncInterestTable.insert (digest, name.toUri(), false);
+      return;
+    }
+
+  DiffStateContainer::iterator stateInDiffLog = m_log.find (digest);
+
+  if (stateInDiffLog != m_log.end ())
+  {
+    DiffStateConstPtr stateDiff = (*stateInDiffLog)->diff ();
+
+    sendSyncData (name, digest, stateDiff);
+    return;
+  }
+
+  if (!timedProcessing)
+    {
+      bool exists = m_syncInterestTable.insert (digest, name.toUri(), true);
+      if (exists) // somebody else replied, so restart random-game timer
+        {
+          _LOG_DEBUG_ID ("Unknown digest, but somebody may have already replied, so restart our timer");
+          m_scheduler.cancelEvent (m_delayedInterestProcessingId);
+        }
+
+      uint32_t waitDelay = GET_RANDOM (m_rangeUniformRandom);
+      _LOG_DEBUG_ID ("Digest is not in the log. Schedule processing after small delay: " << time::milliseconds (waitDelay));
+
+      m_delayedInterestProcessingId = m_scheduler.scheduleEvent (time::milliseconds (waitDelay),
+                                                                 bind (&SyncLogic::processSyncInterest, this, name, digest, true));
+    }
+  else
+    {
+      _LOG_DEBUG_ID ("                                                      (timed processing)");
+
+      m_recoveryRetransmissionInterval = m_defaultRecoveryRetransmitInterval;
+      sendSyncRecoveryInterests (digest);
+    }
+}
+
+void
+SyncLogic::processSyncData (const Name &name, DigestConstPtr digest, const char *wireData, size_t len)
+{
+  DiffStatePtr diffLog = boost::make_shared<DiffState> ();
+  bool ownInterestSatisfied = false;
+
+  try
+    {
+
+      m_syncInterestTable.remove (name.toUri()); // Remove satisfied interest from PIT
+
+      ownInterestSatisfied = (name == m_outstandingInterestName);
+
+      DiffState diff;
+      SyncStateMsg msg;
+      if (!msg.ParseFromArray(wireData, len) || !msg.IsInitialized())
+      {
+        //Throw
+        BOOST_THROW_EXCEPTION (Error::SyncStateMsgDecodingFailure () );
+      }
+      msg >> diff;
+
+      vector<MissingDataInfo> v;
+      BOOST_FOREACH (LeafConstPtr leaf, diff.getLeaves().get<ordered>())
+        {
+          DiffLeafConstPtr diffLeaf = boost::dynamic_pointer_cast<const DiffLeaf> (leaf);
+          BOOST_ASSERT (diffLeaf != 0);
+
+          NameInfoConstPtr info = diffLeaf->getInfo();
+          if (diffLeaf->getOperation() == UPDATE)
+            {
+              SeqNo seq = diffLeaf->getSeq();
+
+              bool inserted = false;
+              bool updated = false;
+              SeqNo oldSeq;
+              {
+                boost::tie (inserted, updated, oldSeq) = m_state->update (info, seq);
+              }
+
+              if (inserted || updated)
+                {
+                  diffLog->update (info, seq);
+                  if (!oldSeq.isValid())
+                  {
+                    oldSeq = SeqNo(seq.getSession(), 0);
+                  }
+                  else
+                  {
+                    ++oldSeq;
+                  }
+                  // there is no need for application to process update on forwarder node
+                  if (info->toString() != forwarderPrefix)
+                  {
+                    MissingDataInfo mdi = {info->toString(), oldSeq, seq};
+                    {
+                      ostringstream interestName;
+                      interestName << mdi.prefix << "/" << mdi.high.getSession() << "/" << mdi.high.getSeq();
+                      _LOG_DEBUG_ID("+++++++++++++++ " + interestName.str());
+                    }
+                    if (m_perBranch)
+                    {
+                       ostringstream interestName;
+                       interestName << mdi.prefix << "/" << mdi.high.getSession() << "/" << mdi.high.getSeq();
+                       m_onUpdateBranch(interestName.str());
+                    }
+                    else
+                    {
+                      v.push_back(mdi);
+                    }
+                  }
+                }
+            }
+          else if (diffLeaf->getOperation() == REMOVE)
+            {
+              if (m_state->remove (info))
+                {
+                  diffLog->remove (info);
+                  if (!m_perBranch)
+                  {
+                    m_onRemove (info->toString ());
+                  }
+                }
+            }
+          else
+            {
+            }
+        }
+
+      if (!v.empty())
+      {
+        if (!m_perBranch)
+        {
+           m_onUpdate(v);
+        }
+      }
+
+      insertToDiffLog (diffLog);
+    }
+  catch (Error::SyncStateMsgDecodingFailure &e)
+    {
+      _LOG_DEBUG_ID ("Something really fishy happened during state decoding " <<
+                  diagnostic_information (e));
+      diffLog.reset ();
+      // don't do anything
+    }
+
+  if ((diffLog != 0 && diffLog->getLeaves ().size () > 0) ||
+      ownInterestSatisfied)
+    {
+      _LOG_DEBUG_ID(" +++++++++++++++ state changed!!!");
+      // Do it only if everything went fine and state changed
+
+      // this is kind of wrong
+      // satisfyPendingSyncInterests (diffLog); // if there are interests in PIT, there is a point to satisfy them using new state
+
+      // if state has changed, then it is safe to express a new interest
+      time::system_clock::Duration after = time::milliseconds(GET_RANDOM (m_reexpressionJitter));
+      // cout << "------------ reexpress interest after: " << after << endl;
+      EventId eventId = m_scheduler.scheduleEvent (after,
+                                                   bind (&SyncLogic::sendSyncInterest, this));
+
+      m_scheduler.cancelEvent (m_reexpressingInterestId);
+      m_reexpressingInterestId = eventId;
+    }
+}
+
+void
+SyncLogic::processSyncRecoveryInterest (const Name &name, DigestConstPtr digest)
+{
+  _LOG_DEBUG_ID("processSyncRecoveryInterest");
+  DiffStateContainer::iterator stateInDiffLog = m_log.find (digest);
+
+  if (stateInDiffLog == m_log.end ())
+    {
+      _LOG_DEBUG_ID ("Could not find " << *digest << " in digest log");
+      return;
+    }
+
+  SyncStateMsg ssm;
+  {
+    ssm << (*m_state);
+  }
+  sendSyncData (name, digest, ssm);
+}
+
+void
+SyncLogic::satisfyPendingSyncInterests (DiffStateConstPtr diffLog)
+{
+  DiffStatePtr fullStateLog = boost::make_shared<DiffState> ();
+  {
+    BOOST_FOREACH (LeafConstPtr leaf, m_state->getLeaves ()/*.get<timed> ()*/)
+      {
+        fullStateLog->update (leaf->getInfo (), leaf->getSeq ());
+        /// @todo Impose limit on how many state info should be send out
+      }
+  }
+
+  try
+    {
+      uint32_t counter = 0;
+      while (m_syncInterestTable.size () > 0)
+        {
+          Sync::Interest interest = m_syncInterestTable.pop ();
+
+          if (!interest.m_unknown)
+            {
+              _LOG_DEBUG_ID (">> D " << interest.m_name);
+              sendSyncData (interest.m_name, interest.m_digest, diffLog);
+            }
+          else
+            {
+              _LOG_DEBUG_ID (">> D (unknown)" << interest.m_name);
+              sendSyncData (interest.m_name, interest.m_digest, fullStateLog);
+            }
+          counter ++;
+        }
+      _LOG_DEBUG_ID ("Satisfied " << counter << " pending interests");
+    }
+  catch (Error::InterestTableIsEmpty &e)
+    {
+      // ok. not really an error
+    }
+}
+
+void
+SyncLogic::insertToDiffLog (DiffStatePtr diffLog)
+{
+  diffLog->setDigest (m_state->getDigest());
+  if (m_log.size () > 0)
+    {
+      m_log.get<sequenced> ().front ()->setNext (diffLog);
+    }
+  m_log.erase (m_state->getDigest()); // remove diff state with the same digest.  next pointers are still valid
+  /// @todo Optimization
+  m_log.get<sequenced> ().push_front (diffLog);
+}
+
+void
+SyncLogic::addLocalNames (const Name &prefix, uint64_t session, uint64_t seq)
+{
+  DiffStatePtr diff;
+  {
+    //cout << "Add local names" <<endl;
+    NameInfoConstPtr info = StdNameInfo::FindOrCreate(prefix.toUri());
+
+    _LOG_DEBUG_ID ("addLocalNames (): old state " << *m_state->getDigest ());
+
+    SeqNo seqN (session, seq);
+    m_state->update(info, seqN);
+
+    _LOG_DEBUG_ID ("addLocalNames (): new state " << *m_state->getDigest ());
+
+    diff = boost::make_shared<DiffState>();
+    diff->update(info, seqN);
+    insertToDiffLog (diff);
+  }
+
+  // _LOG_DEBUG_ID ("PIT size: " << m_syncInterestTable.size ());
+  satisfyPendingSyncInterests (diff);
+}
+
+void
+SyncLogic::remove(const Name &prefix)
+{
+  DiffStatePtr diff;
+  {
+    NameInfoConstPtr info = StdNameInfo::FindOrCreate(prefix.toUri());
+    m_state->remove(info);
+
+    // increment the sequence number for the forwarder node
+    NameInfoConstPtr forwarderInfo = StdNameInfo::FindOrCreate(forwarderPrefix);
+
+    LeafContainer::iterator item = m_state->getLeaves ().find (forwarderInfo);
+    SeqNo seqNo (0);
+    if (item != m_state->getLeaves ().end ())
+      {
+        seqNo = (*item)->getSeq ();
+        ++seqNo;
+      }
+    m_state->update (forwarderInfo, seqNo);
+
+    diff = boost::make_shared<DiffState>();
+    diff->remove(info);
+    diff->update(forwarderInfo, seqNo);
+
+    insertToDiffLog (diff);
+  }
+
+  satisfyPendingSyncInterests (diff);
+}
+
+void
+SyncLogic::sendSyncInterest ()
+{
+  _LOG_DEBUG_ID("sendSyncInterest");
+
+  {
+    m_outstandingInterestName = m_syncPrefix;
+    ostringstream os;
+    os << *m_state->getDigest();
+    m_outstandingInterestName.append(os.str());
+    _LOG_DEBUG_ID (">> I " << m_outstandingInterestName);
+  }
+
+  _LOG_DEBUG_ID("sendSyncInterest: " << m_outstandingInterestName);
+
+  EventId eventId = m_scheduler.scheduleEvent (time::seconds(m_syncInterestReexpress) + time::milliseconds(GET_RANDOM (m_reexpressionJitter)),
+                                               bind (&SyncLogic::sendSyncInterest, this));
+  m_scheduler.cancelEvent (m_reexpressingInterestId);
+  m_reexpressingInterestId = eventId;
+
+  ndn::Interest interest(m_outstandingInterestName);
+  interest.setMustBeFresh(true);
+
+  m_face->expressInterest(interest,
+                          bind(&SyncLogic::onSyncData, this, _1, _2),
+                          bind(&SyncLogic::onSyncTimeout, this, _1));
+}
+
+void
+SyncLogic::sendSyncRecoveryInterests (DigestConstPtr digest)
+{
+  ostringstream os;
+  os << *digest;
+
+  Name interestName = m_syncPrefix;
+  interestName.append("recovery").append(os.str());
+
+  time::system_clock::Duration nextRetransmission = time::milliseconds (m_recoveryRetransmissionInterval + GET_RANDOM (m_reexpressionJitter));
+
+  m_recoveryRetransmissionInterval <<= 1;
+
+  m_scheduler.cancelEvent (m_reexpressingRecoveryInterestId);
+  if (m_recoveryRetransmissionInterval < 100*1000) // <100 seconds
+    m_reexpressingRecoveryInterestId = m_scheduler.scheduleEvent (nextRetransmission,
+                                                                  bind (&SyncLogic::sendSyncRecoveryInterests, this, digest));
+
+  ndn::Interest interest(interestName);
+  interest.setMustBeFresh(true);
+
+  m_face->expressInterest(interest,
+                          bind(&SyncLogic::onSyncData, this, _1, _2),
+                          bind(&SyncLogic::onSyncTimeout, this, _1));
+}
+
+
+void
+SyncLogic::sendSyncData (const Name &name, DigestConstPtr digest, StateConstPtr state)
+{
+  SyncStateMsg msg;
+  msg << (*state);
+  sendSyncData(name, digest, msg);
+}
+
+// pass in state msg instead of state, so that there is no need to lock the state until
+// this function returns
+void
+SyncLogic::sendSyncData (const Name &name, DigestConstPtr digest, SyncStateMsg &ssm)
+{
+  _LOG_DEBUG_ID (">> D " << name);
+  int size = ssm.ByteSize();
+  char *wireData = new char[size];
+  ssm.SerializeToArray(wireData, size);
+
+  Data syncData(name);
+  syncData.setContent(reinterpret_cast<const uint8_t*>(wireData), size);
+  syncData.setFreshnessPeriod(time::seconds(m_syncResponseFreshness));
+
+  m_keyChain->sign(syncData);
+
+  m_face->put(syncData);
+
+  delete []wireData;
+
+  // checking if our own interest got satisfied
+  bool satisfiedOwnInterest = false;
+  {
+    satisfiedOwnInterest = (m_outstandingInterestName == name);
+  }
+
+  if (satisfiedOwnInterest)
+    {
+      _LOG_DEBUG_ID ("Satisfied our own Interest. Re-expressing (hopefully with a new digest)");
+
+      time::system_clock::Duration after = time::milliseconds(GET_RANDOM (m_reexpressionJitter));
+      // cout << "------------ reexpress interest after: " << after << endl;
+      EventId eventId = m_scheduler.scheduleEvent (after,
+                                                   bind (&SyncLogic::sendSyncInterest, this));
+      m_scheduler.cancelEvent (m_reexpressingInterestId);
+      m_reexpressingInterestId = eventId;
+    }
+}
+
+string
+SyncLogic::getRootDigest()
+{
+  ostringstream os;
+  os << *m_state->getDigest();
+  return os.str();
+}
+
+size_t
+SyncLogic::getNumberOfBranches () const
+{
+  return m_state->getLeaves ().size ();
+}
+
+void
+SyncLogic::printState () const
+{
+  BOOST_FOREACH (const boost::shared_ptr<Sync::Leaf> leaf, m_state->getLeaves ())
+    {
+      std::cout << *leaf << std::endl;
+    }
+}
+
+std::map<std::string, bool>
+SyncLogic::getBranchPrefixes() const
+{
+  std::map<std::string, bool> m;
+
+  BOOST_FOREACH (const boost::shared_ptr<Sync::Leaf> leaf, m_state->getLeaves ())
+    {
+      std::string prefix = leaf->getInfo()->toString();
+      // do not return forwarder prefix
+      if (prefix != forwarderPrefix)
+      {
+        m.insert(pair<std::string, bool>(prefix, false));
+      }
+    }
+
+  return m;
+}
+
+}
