sync core compiles
diff --git a/src/db-helper.cc b/src/db-helper.cc
index c5455e8..0e08612 100644
--- a/src/db-helper.cc
+++ b/src/db-helper.cc
@@ -37,7 +37,7 @@
         device_name     BLOB NOT NULL,                          \n\
         description     TEXT,                                   \n\
         seq_no          INTEGER NOT NULL,                       \n\
-        last_known_tdi  TEXT,                                   \n\
+        last_known_locator  BLOB,                               \n\
         last_update     TIMESTAMP                               \n\
     );                                                          \n\
                                                                 \n\
diff --git a/src/hash-helper.cc b/src/hash-helper.cc
index dbb70a3..d92e6b0 100644
--- a/src/hash-helper.cc
+++ b/src/hash-helper.cc
@@ -103,6 +103,9 @@
   return os;
 }
 
+unsigned char Hash::_origin = 0;
+HashPtr Hash::Origin(new Hash(&Hash::_origin, sizeof(unsigned char)));
+
 HashPtr
 Hash::FromString (const std::string &hashInTextEncoding)
 {
diff --git a/src/hash-helper.h b/src/hash-helper.h
index d4f750d..638a93a 100644
--- a/src/hash-helper.h
+++ b/src/hash-helper.h
@@ -37,6 +37,8 @@
 class Hash
 {
 public:
+  static unsigned char _origin;
+  static HashPtr Origin;
   Hash (const void *buf, unsigned int length)
     : m_length (length)
   {
diff --git a/src/sync-core.cc b/src/sync-core.cc
index 21201aa..32a1243 100644
--- a/src/sync-core.cc
+++ b/src/sync-core.cc
@@ -21,8 +21,12 @@
 
 #include "sync-core.h"
 
-SyncCore::SyncCore
-         : m_log(path, userName)
+const string SyncCore::RECOVER = "RECOVER";
+const double SyncCore::WAIT = 0.2;
+const double SyncCore::RANDOM_PERCENT = 0.5;
+
+SyncCore::SyncCore(const string &path, const Name &userName, const Name &localPrefix, const Name &syncPrefix, const StateMsgCallback &callback, CcnxWrapperPtr handle, SchedulerPtr scheduler)
+         : m_log(path, userName.toString())
          , m_localPrefix(localPrefix)
          , m_syncPrefix(syncPrefix)
          , m_stateMsgCallback(callback)
@@ -30,16 +34,40 @@
          , m_scheduler(scheduler)
 {
   m_rootHash = m_log.RememberStateInStateLog();
-  m_interestClosure = new Closure(0, boost::bind(&SyncCore::handleSyncData, this, _1, _2), boost::bind(&SyncCore::handleSyncInterestTimeout, this, _1));
+  m_syncClosure = new Closure(0, boost::bind(&SyncCore::handleSyncData, this, _1, _2), boost::bind(&SyncCore::handleSyncInterestTimeout, this, _1));
+  m_recoverClosure = new Closure(0, boost::bind(&SyncCore::handleRecoverData, this, _1, _2), boost::bind(&SyncCore::handleRecoverInterestTimeout, this, _1));
+  m_handle->setInterestFilter(m_syncPrefix, boost::bind(&SyncCore::handleInterest, this, _1));
+  m_log.initYP(m_yp);
   m_scheduler->start();
   sendSyncInterest();
 }
 
 SyncCore::~SyncCore()
 {
-  m_scheduler->stop();
-  delete m_interestClosure;
-  m_interestClosure = 0;
+  m_scheduler->shutdown();
+  if (m_syncClosure != 0)
+  {
+    delete m_syncClosure;
+    m_syncClosure = 0;
+  }
+
+  if (m_recoverClosure != 0)
+  {
+    delete m_recoverClosure;
+    m_recoverClosure = 0;
+  }
+}
+
+Name
+SyncCore::yp(const Name &deviceName)
+{
+  Name locator;
+  ReadLock(m_ypMutex);
+  if (m_yp.find(deviceName) != m_yp.end())
+  {
+    locator = m_yp[deviceName];
+  }
+  return locator;
 }
 
 void
@@ -51,13 +79,15 @@
 }
 
 void
-SyncCore::updateLocalState(seqno_t seqno)
+SyncCore::updateLocalState(sqlite3_int64 seqno)
 {
-  m_log.UpdateDeviceSeqNo(seqno);
+  m_log.UpdateDeviceSeqNo(m_userName, seqno);
+  // choose to update locator everytime
+  m_log.UpdateLocator(m_userName, m_localPrefix);
   HashPtr oldHash = m_rootHash;
   m_rootHash = m_log.RememberStateInStateLog();
 
-  SyncStateMsgPtr msg = m_log.FindStateDifferences(oldHash, m_rootHash);
+  SyncStateMsgPtr msg = m_log.FindStateDifferences(*oldHash, *m_rootHash);
 
   // reply sync Interest with oldHash as last component
   Name syncName = constructSyncName(oldHash);
@@ -68,14 +98,76 @@
   // no hurry in sending out new Sync Interest; if others send the new Sync Interest first, no problem, we know the new root hash already;
   // this is trying to avoid the situation that the order of SyncData and new Sync Interest gets reversed at receivers
   ostringstream ss;
-  ss << m_rootHash;
+  ss << *m_rootHash;
   TaskPtr task(new OneTimeTask(boost::bind(&SyncCore::sendSyncInterest, this), ss.str(), m_scheduler, 0.05));
   m_scheduler->addTask(task);
 }
 
 void
+SyncCore::handleInterest(const Name &name)
+{
+  int size = name.size();
+  int prefixSize = m_syncPrefix.size();
+  if (size == prefixSize + 1)
+  {
+    // this is normal sync interest
+    handleSyncInterest(name);
+  }
+  else if (size == prefixSize + 2 && name.getCompAsString(m_syncPrefix.size()) == RECOVER)
+  {
+    // this is recovery interest
+    handleRecoverInterest(name);
+  }
+}
+
+void
+SyncCore::handleRecoverInterest(const Name &name)
+{
+  Bytes hashBytes = name.getComp(name.size() - 1);
+  // this is the hash unkonwn to the sender of the interest
+  Hash hash(head(hashBytes), hashBytes.size());
+  if (m_log.LookupSyncLog(hash) > 0)
+  {
+    // we know the hash, should reply everything
+    SyncStateMsgPtr msg = m_log.FindStateDifferences(*(Hash::Origin), *m_rootHash);
+    Bytes syncData;
+    msgToBytes(msg, syncData);
+    m_handle->publishData(name, syncData, FRESHNESS);
+  }
+  else
+  {
+    // we don't recognize this hash, can not help
+  }
+}
+
+void
 SyncCore::handleSyncInterest(const Name &name)
 {
+  Bytes hashBytes = name.getComp(name.size() - 1);
+  HashPtr hash(new Hash(head(hashBytes), hashBytes.size()));
+  if (*hash == *m_rootHash)
+  {
+    // we have the same hash; nothing needs to be done
+    return;
+  }
+  else if (m_log.LookupSyncLog(*hash) > 0)
+  {
+    // we know something more
+    SyncStateMsgPtr msg = m_log.FindStateDifferences(*hash, *m_rootHash);
+
+    Bytes syncData;
+    msgToBytes(msg, syncData);
+    m_handle->publishData(name, syncData, FRESHNESS);
+  }
+  else
+  {
+    // we don't recognize the hash, send recover Interest if still don't know the hash after a randomized wait period
+    ostringstream ss;
+    ss << *hash;
+    IntervalGeneratorPtr generator(new RandomIntervalGenerator(WAIT, RANDOM_PERCENT, RandomIntervalGenerator::UP));
+    TaskPtr task(new PeriodicTask(boost::bind(&SyncCore::recover, this, hash), ss.str(), m_scheduler, generator, 1));
+    m_scheduler->addTask(task);
+  }
 }
 
 Closure::TimeoutCallbackReturnValue
@@ -83,18 +175,44 @@
 {
   // sendInterestInterest with the current root hash;
   sendSyncInterest();
-  return Closure::OK;
+  return Closure::RESULT_OK;
+}
+
+Closure::TimeoutCallbackReturnValue
+SyncCore::handleRecoverInterestTimeout(const Name &name)
+{
+  // We do not re-express recovery interest for now
+  // if difference is not resolved, the sync interest will trigger
+  // recovery anyway; so it's not so important to have recovery interest
+  // re-expressed
+  return Closure::RESULT_OK;
+}
+
+void
+SyncCore::handleRecoverData(const Name &name, const Bytes &content)
+{
+  handleStateData(content);
 }
 
 void
 SyncCore::handleSyncData(const Name &name, const Bytes &content)
 {
+  // suppress recover in interest - data out of order case
+  handleStateData(content);
+
+  // resume outstanding sync interest
+  sendSyncInterest();
+}
+
+void
+SyncCore::handleStateData(const Bytes &content)
+{
   SyncStateMsgPtr msg(new SyncStateMsg);
   bool success = msg->ParseFromArray(head(content), content.size());
   if(!success)
   {
     // ignore misformed SyncData
-    cerr << "Misformed SyncData with name: " << name << endl;
+    cerr << "Misformed SyncData"<< endl;
     return;
   }
 
@@ -103,32 +221,83 @@
   while (index < size)
   {
     SyncState state = msg->state(index);
+    string devStr = state.name();
+    Name deviceName((const unsigned char *)devStr.c_str(), devStr.size());
+    if (state.type() == SyncState::UPDATE)
+    {
+      sqlite3_int64 seqno = state.seq();
+      m_log.UpdateDeviceSeqNo(deviceName, seqno);
+      if (state.has_locator())
+      {
+        string locStr = state.locator();
+        Name locatorName((const unsigned char *)locStr.c_str(), locStr.size());
+        m_log.UpdateLocator(deviceName, locatorName);
+        WriteLock(m_ypMutex);
+        m_yp[deviceName] = locatorName;
+      }
+    }
+    else
+    {
+      deregister(deviceName);
+    }
     index++;
   }
 
+  // find the actuall difference and invoke callback on the actual difference
+  HashPtr oldHash = m_rootHash;
+  m_rootHash = m_log.RememberStateInStateLog();
+  SyncStateMsgPtr diff = m_log.FindStateDifferences(*oldHash, *m_rootHash);
+  m_stateMsgCallback(diff);
 }
 
 void
 SyncCore::sendSyncInterest()
 {
   Name syncInterest = constructSyncName(m_rootHash);
-  sendInterest(syncInterest, m_interestClosure);
+  m_handle->sendInterest(syncInterest, m_syncClosure);
+}
+
+void
+SyncCore::recover(const HashPtr &hash)
+{
+  if (!(*hash == *m_rootHash) && m_log.LookupSyncLog(*hash) <= 0)
+  {
+    // unfortunately we still don't recognize this hash
+    Bytes bytes;
+    readRaw(bytes, (const unsigned char *)hash->GetHash(), hash->GetHashBytes());
+    Name recoverInterest = m_syncPrefix;
+    recoverInterest.appendComp(RECOVER);
+    // append the unknown hash
+    recoverInterest.appendComp(bytes);
+    m_handle->sendInterest(recoverInterest, m_recoverClosure);
+  }
+  else
+  {
+    // we already learned the hash; cheers!
+  }
+}
+
+void
+SyncCore::deregister(const Name &name)
+{
+  // Do nothing for now
+  // TODO: handle deregistering
 }
 
 Name
 SyncCore::constructSyncName(const HashPtr &hash)
 {
   Bytes bytes;
-  readRaw(bytes, (const unsigned char*)hash->GetHash(), hash->GetHashBytes);
+  readRaw(bytes, (const unsigned char*)hash->GetHash(), hash->GetHashBytes());
   Name syncName = m_syncPrefix;
-  syncName.append(bytes);
+  syncName.appendComp(bytes);
   return syncName;
 }
 
 void
 SyncCore::msgToBytes(const SyncStateMsgPtr &msg, Bytes &bytes)
 {
-  int size = msg.ByteSize();
+  int size = msg->ByteSize();
   bytes.resize(size);
-  msg.SerializeToArray(head(bytes), size);
+  msg->SerializeToArray(head(bytes), size);
 }
diff --git a/src/sync-core.h b/src/sync-core.h
index b06b8b8..afe5e05 100644
--- a/src/sync-core.h
+++ b/src/sync-core.h
@@ -35,13 +35,15 @@
 {
 public:
   typedef boost::function<void (const SyncStateMsgPtr & stateMsg) > StateMsgCallback;
-  typedef sqlite3_int64 seqno_t;
-  typedef Map<Name, Name> YellowPage;
+  typedef map<Name, Name> YellowPage;
   typedef boost::shared_mutex Mutex;
   typedef boost::shared_lock<Mutex> ReadLock;
   typedef boost::unique_lock<Mutex> WriteLock;
 
-  static const int FRESHNESS = 2;
+  static const int FRESHNESS = 2; // seconds
+  static const string RECOVER;
+  static const double WAIT; // seconds;
+  static const double RANDOM_PERCENT; // seconds;
 
 public:
   SyncCore(const string &path                   // path where SyncLog is stored
@@ -59,27 +61,45 @@
   updateLocalPrefix(const Name &localPrefix);
 
   void
-  updateLocalState(seqno_t);
+  updateLocalState(sqlite3_int64);
 
   Name
   yp(const Name &name);
 
   void
-  handleSyncInterest(const Name &name);
-
-  Closure::TimeoutCallbackReturnValue
-  handleSyncInterestTimeout(const Name &name);
+  handleInterest(const Name &name);
 
   void
   handleSyncData(const Name &name, const Bytes &content);
 
   void
-  deregister();
+  handleRecoverData(const Name &name, const Bytes &content);
+
+  Closure::TimeoutCallbackReturnValue
+  handleSyncInterestTimeout(const Name &name);
+
+  Closure::TimeoutCallbackReturnValue
+  handleRecoverInterestTimeout(const Name &name);
+
+  void
+  deregister(const Name &name);
+
+  void
+  recover(const HashPtr &hash);
 
 protected:
   void
   sendSyncInterest();
 
+  void
+  handleSyncInterest(const Name &name);
+
+  void
+  handleRecoverInterest(const Name &name);
+
+  void
+  handleStateData(const Bytes &content);
+
   Name
   constructSyncName(const HashPtr &hash);
 
@@ -97,7 +117,8 @@
   YellowPage m_yp;
   Mutex m_ypMutex;
   CcnxWrapperPtr m_handle;
-  Closure *m_interestClosure;
+  Closure *m_syncClosure;
+  Closure *m_recoverClosure;
 
 };
 
diff --git a/src/sync-log.cc b/src/sync-log.cc
index 4b0984a..f3ba3d0 100644
--- a/src/sync-log.cc
+++ b/src/sync-log.cc
@@ -20,17 +20,19 @@
  */
 
 #include "sync-log.h"
+#include <utility>
 
 #include <boost/make_shared.hpp>
 
 using namespace boost;
 using namespace std;
+using namespace Ccnx;
 
 SyncLog::SyncLog (const boost::filesystem::path &path, const std::string &localName)
   : DbHelper (path)
   , m_localName (localName)
 {
-  UpdateDeviceSeqno (localName, 0);
+  UpdateDeviceSeqNo (localName, 0);
   
   sqlite3_stmt *stmt;
   int res = sqlite3_prepare_v2 (m_db, "SELECT device_id, seq_no FROM SyncNodes WHERE device_name=?", -1, &stmt, 0);
@@ -50,6 +52,25 @@
   sqlite3_finalize (stmt);
 }
 
+void
+SyncLog::initYP(map<Name, Name> &yp)
+{
+  sqlite3_stmt *stmt;
+  sqlite3_prepare_v2(m_db, "SELECT device_name, last_known_locator FROM SyncNodes;", -1, &stmt, 0);
+
+  while (sqlite3_step(stmt) == SQLITE_ROW)
+  {
+    Name deviceName((const unsigned char *)sqlite3_column_blob(stmt, 0), sqlite3_column_bytes(stmt, 0));
+    Name locator;
+    if (sqlite3_column_type(stmt, 1) == SQLITE_BLOB)
+    {
+      locator = Name((const unsigned char *)sqlite3_column_blob(stmt, 1), sqlite3_column_bytes(stmt, 1));
+    }
+    yp.insert(make_pair(deviceName, locator));
+  }
+
+  sqlite3_finalize(stmt);
+}
 
 sqlite3_int64
 SyncLog::GetNextLocalSeqNo ()
@@ -177,7 +198,7 @@
 }
 
 void
-SyncLog::UpdateDeviceSeqno (const Ccnx::Name &name, sqlite3_int64 seqNo)
+SyncLog::UpdateDeviceSeqNo (const Ccnx::Name &name, sqlite3_int64 seqNo)
 {
   sqlite3_stmt *stmt;
   // update is performed using trigger
@@ -192,7 +213,7 @@
   if (res != SQLITE_OK)
     {
       BOOST_THROW_EXCEPTION (Error::Db ()
-                             << errmsg_info_str ("Some error with UpdateDeviceSeqno (name)"));
+                             << errmsg_info_str ("Some error with UpdateDeviceSeqNo (name)"));
     }
   sqlite3_finalize (stmt);
 }
@@ -217,6 +238,49 @@
   sqlite3_finalize (stmt);
 }
 
+Name
+SyncLog::LookupLocator(const Name &deviceName)
+{
+  sqlite3_stmt *stmt;
+  sqlite3_prepare_v2 (m_db, "SELECT last_known_locator FROM SyncNodes WHERE device_name=?;", -1, &stmt, 0);
+  Ccnx::CcnxCharbufPtr nameBuf = deviceName;
+  sqlite3_bind_blob (stmt, 1, nameBuf->buf(), nameBuf->length(), SQLITE_STATIC);
+  int res = sqlite3_step (stmt);
+  Name locator;
+  switch (res)
+  {
+  case SQLITE_ROW:
+    {
+      locator = Name((const unsigned char *)sqlite3_column_blob(stmt, 0), sqlite3_column_bytes(stmt, 0));
+    }
+  case SQLITE_DONE: break;
+  default:
+    BOOST_THROW_EXCEPTION(Error::Db() << errmsg_info_str("Error in LookupLocator()"));
+  }
+
+  sqlite3_finalize(stmt);
+
+  return locator;
+}
+
+void
+SyncLog::UpdateLocator(const Name &deviceName, const Name &locator)
+{
+  sqlite3_stmt *stmt;
+  sqlite3_prepare_v2 (m_db, "UPDATE SyncNodes SET last_known_locator=? WHERE device_name=?;", -1, &stmt, 0);
+  Ccnx::CcnxCharbufPtr nameBuf = deviceName;
+  Ccnx::CcnxCharbufPtr locatorBuf = locator;
+  sqlite3_bind_blob (stmt, 1, nameBuf->buf(), nameBuf->length(), SQLITE_STATIC);
+  sqlite3_bind_blob (stmt, 2, locatorBuf->buf(), locatorBuf->length(), SQLITE_STATIC);
+  int res = sqlite3_step (stmt);
+
+  if (res != SQLITE_OK && res != SQLITE_DONE)
+  {
+    BOOST_THROW_EXCEPTION(Error::Db() << errmsg_info_str("Error in UpdateLoactor()"));
+  }
+
+  sqlite3_finalize(stmt);
+}
 
 SyncStateMsgPtr
 SyncLog::FindStateDifferences (const std::string &oldHash, const std::string &newHash)
@@ -230,7 +294,7 @@
   sqlite3_stmt *stmt;
 
   int res = sqlite3_prepare_v2 (m_db, "\
-SELECT sn.device_name, s_old.seq_no, s_new.seq_no                       \
+SELECT sn.device_name, sn.last_known_locator, s_old.seq_no, s_new.seq_no\
     FROM (SELECT *                                                      \
             FROM SyncStateNodes                                         \
             WHERE state_id=(SELECT state_id                             \
@@ -250,7 +314,7 @@
                                                                         \
 UNION ALL                                                               \
                                                                         \
-SELECT sn.device_name, s_old.seq_no, s_new.seq_no                       \
+SELECT sn.device_name, sn.last_known_locator, s_old.seq_no, s_new.seq_no\
     FROM (SELECT *                                                      \
             FROM SyncStateNodes                                         \
             WHERE state_id=(SELECT state_id                             \
@@ -285,7 +349,13 @@
 
       state->set_name (reinterpret_cast<const char*> (sqlite3_column_blob (stmt, 0), sqlite3_column_bytes (stmt, 0)));
 
-      sqlite3_int64 newSeqNo = sqlite3_column_int64 (stmt, 2);
+      // locator is optional, so must check if it is null
+      if (sqlite3_column_type(stmt, 1) == SQLITE_BLOB)
+      {
+        state->set_locator (reinterpret_cast<const char*> (sqlite3_column_blob (stmt, 1), sqlite3_column_bytes (stmt, 1)));
+      }
+
+      sqlite3_int64 newSeqNo = sqlite3_column_int64 (stmt, 3);
       if (newSeqNo > 0)
         {
           state->set_type (SyncState::UPDATE);
diff --git a/src/sync-log.h b/src/sync-log.h
index c75fcf7..d066991 100644
--- a/src/sync-log.h
+++ b/src/sync-log.h
@@ -25,6 +25,7 @@
 #include "db-helper.h"
 #include <sync-state.pb.h>
 #include <ccnx-name.h>
+#include <map>
 
 typedef boost::shared_ptr<SyncStateMsg> SyncStateMsgPtr;
 
@@ -33,21 +34,22 @@
 public:
   SyncLog (const boost::filesystem::path &path, const std::string &localName);
 
+  // fill in the map with device-name <-> locator pairs
+  void
+  initYP(map<Ccnx::Name, Ccnx::Name> &yp);
+
   sqlite3_int64
   GetNextLocalSeqNo (); // side effect: local seq_no will be increased
 
-  void
-  UpdateDeviceSeqNo (sqlite3_int64 deviceId, sqlite3_int64 seqNo);
-  
   // done
   void
-  UpdateDeviceSeqno (const Ccnx::Name &name, sqlite3_int64 seqNo);
+  UpdateDeviceSeqNo (const Ccnx::Name &name, sqlite3_int64 seqNo);
 
-  // std::string
-  // LookupForwardingAlias (const std::string &deviceName);
+  Ccnx::Name
+  LookupLocator (const Ccnx::Name &deviceName);
 
-  // void
-  // UpdateForwardingAlias ();
+  void
+  UpdateLocator (const Ccnx::Name &deviceName, const Ccnx::Name &locator);
 
   // done
   /**
@@ -72,6 +74,11 @@
   FindStateDifferences (const Hash &oldHash, const Hash &newHash);  
 
 protected:
+  void
+  UpdateDeviceSeqNo (sqlite3_int64 deviceId, sqlite3_int64 seqNo);
+  
+
+protected:
   // std::string m_localName;
   Ccnx::Name m_localName;
   
diff --git a/src/sync-state.proto b/src/sync-state.proto
index 2aafb0c..26095e1 100644
--- a/src/sync-state.proto
+++ b/src/sync-state.proto
@@ -10,6 +10,7 @@
   required ActionType type = 2;
 
   optional uint64 seq = 3;
+  optional bytes locator = 4;
 }
 
 message SyncStateMsg
diff --git a/test/database-test.cc b/test/database-test.cc
index dcbcc2b..c9058e9 100644
--- a/test/database-test.cc
+++ b/test/database-test.cc
@@ -45,20 +45,20 @@
   // should be empty
   BOOST_CHECK_EQUAL (lexical_cast<string> (*hash), "7a6f2c1eefd539560d2dc3e5542868a79810d0867db15d9b87e41ec105899405");
 
-  db.UpdateDeviceSeqno (Name ("Alex"), 1);
+  db.UpdateDeviceSeqNo (Name ("Alex"), 1);
   hash = db.RememberStateInStateLog ();
 
   BOOST_CHECK_EQUAL (lexical_cast<string> (*hash), "bf19308cb2c2ddab7bcce66e9074cd0eed74893be0813ca67a95e97c55d65896");
 
-  db.UpdateDeviceSeqno (Name ("Alex"), 2);
+  db.UpdateDeviceSeqNo (Name ("Alex"), 2);
   hash = db.RememberStateInStateLog ();
   BOOST_CHECK_EQUAL (lexical_cast<string> (*hash), "86b51f1f98662583b295b61385ae4450ff8fac955981f1ca4381144ab1d7a4e0");
 
-  db.UpdateDeviceSeqno (Name ("Alex"), 2);
+  db.UpdateDeviceSeqNo (Name ("Alex"), 2);
   hash = db.RememberStateInStateLog ();
   BOOST_CHECK_EQUAL (lexical_cast<string> (*hash), "86b51f1f98662583b295b61385ae4450ff8fac955981f1ca4381144ab1d7a4e0");
 
-  db.UpdateDeviceSeqno (Name ("Alex"), 1);
+  db.UpdateDeviceSeqNo (Name ("Alex"), 1);
   hash = db.RememberStateInStateLog ();
   BOOST_CHECK_EQUAL (lexical_cast<string> (*hash), "86b51f1f98662583b295b61385ae4450ff8fac955981f1ca4381144ab1d7a4e0");
 
@@ -70,7 +70,7 @@
   // db.FindStateDifferences ("86b51f1f98662583b295b61385ae4450ff8fac955981f1ca4381144ab1d7a4e0",
   //                          "869c38c6dffe8911ced320aecc6d9244904d13d3e8cd21081311f2129b4557ce");
 
-  // db.UpdateDeviceSeqno (Name ("Bob"), 1);
+  // db.UpdateDeviceSeqNo (Name ("Bob"), 1);
   // hash = db.RememberStateInStateLog ();
   // BOOST_CHECK_EQUAL (lexical_cast<string> (*hash), "d001d4680fd9adcb48e34a795e3cc3d5d36f209fbab34fd57f70f362c2085310");
 
diff --git a/wscript b/wscript
index 6872b0b..69e49b9 100644
--- a/wscript
+++ b/wscript
@@ -99,6 +99,7 @@
                   'src/action-log.cc',
                   'src/action-item.proto',
                   'src/sync-state.proto',
+                  'src/sync-core.cc',
             ],
         use = "BOOST SQLITE3 SSL common",
         includes = ['include', 'src'],