Checkpoint
diff --git a/model/sync-diff-leaf.cc b/model/sync-diff-leaf.cc
index 2680859..59e0fc1 100644
--- a/model/sync-diff-leaf.cc
+++ b/model/sync-diff-leaf.cc
@@ -19,3 +19,21 @@
  *         卞超轶 Chaoyi Bian <bcy@pku.edu.cn>
  *	   Alexander Afanasyev <alexander.afanasyev@ucla.edu>
  */
+
+#include "sync-diff-leaf.h"
+
+namespace Sync {
+
+DiffLeaf::DiffLeaf (NameInfoConstPtr info, const SeqNo &seq)
+  : Leaf (info, seq)
+  , m_op (UPDATE)
+{
+}
+
+DiffLeaf::DiffLeaf (NameInfoConstPtr info)
+  : Leaf (info, SeqNo (0,0))
+  , m_op (REMOVE)
+{
+}
+
+}
diff --git a/model/sync-diff-leaf.h b/model/sync-diff-leaf.h
index 4ebc6d5..084b5fc 100644
--- a/model/sync-diff-leaf.h
+++ b/model/sync-diff-leaf.h
@@ -49,11 +49,7 @@
    * @param info Smart pointer to leaf's name
    * @param seq  Initial sequence number of the pointer
    */
-  DiffLeaf (boost::shared_ptr<const NameInfo> info, const SeqNo &seq)
-    : Leaf (info, seq)
-    , m_op (UPDATE)
-  {
-  }
+  DiffLeaf (NameInfoConstPtr info, const SeqNo &seq);
 
   /**
    * @brief Constructor to create an REMOVE diff leaf
@@ -62,22 +58,16 @@
    * This constructor creates a leaf with phony sequence number
    * with 0 session ID and 0 sequence number
    */
-  DiffLeaf (boost::shared_ptr<const NameInfo> info)
-    : Leaf (info, SeqNo (0,0))
-    , m_op (REMOVE)
-  {
-  }
+  DiffLeaf (NameInfoConstPtr info);
 
-  virtual ~DiffLeaf ()
-  {
-  }
+  virtual ~DiffLeaf () { }
 
+  /**
+   * @brief Get diff leaf type
+   */
   Operation
-  getOperation () const
-  {
-    return m_op;
-  }
-  
+  getOperation () const { return m_op; }
+
 private:
   Operation m_op;
 };
diff --git a/model/sync-digest.cc b/model/sync-digest.cc
index a499659..4004614 100644
--- a/model/sync-digest.cc
+++ b/model/sync-digest.cc
@@ -36,9 +36,7 @@
 {
   m_context = EVP_MD_CTX_create ();
 
-  int ok = EVP_DigestInit_ex (m_context, EVP_sha1 (), 0);
-  if (!ok)
-    throw DigestCalculationError () << errinfo_at_line (__LINE__);
+  reset ();
 }
 
 Digest::~Digest ()
@@ -50,7 +48,22 @@
 }
 
 void
-Digest::Finalize ()
+Digest::reset ()
+{
+  if (m_buffer != 0)
+    {
+      delete [] m_buffer;
+      m_buffer = 0;
+    }
+
+  int ok = EVP_DigestInit_ex (m_context, EVP_sha1 (), 0);
+  if (!ok)
+    throw DigestCalculationError () << errinfo_at_line (__LINE__);
+}
+
+
+void
+Digest::finalize ()
 {
   if (m_buffer != 0) return;
 
@@ -66,7 +79,7 @@
 Digest::getHash ()
 {
   if (m_buffer == 0)
-    Finalize ();
+    finalize ();
 
   NS_ASSERT (sizeof (std::size_t) <= m_hashLength);
   
@@ -79,10 +92,10 @@
 Digest::operator == (Digest &digest)
 {
   if (m_buffer == 0)
-    Finalize ();
+    finalize ();
 
   if (digest.m_buffer == 0)
-    digest.Finalize ();
+    digest.finalize ();
   
   NS_ASSERT (m_hashLength == digest.m_hashLength);
 
@@ -90,16 +103,27 @@
 }
 
 
+void
+Digest::update (const uint8_t *buffer, size_t size)
+{
+  // cannot update Digest when it has been finalized
+  if (m_buffer != 0)
+    throw DigestCalculationError () << errinfo_at_line (__LINE__);
+
+  bool ok = EVP_DigestUpdate (m_context, buffer, size);
+  if (!ok)
+    throw DigestCalculationError () << errinfo_at_line (__LINE__);
+}
+
+
 Digest &
 Digest::operator << (const Digest &src)
 {
-  if (src.m_buffer == 0)
+  if (src.m_buffer == 0) 
     throw DigestCalculationError () << errinfo_at_line (__LINE__);
 
-  bool ok = EVP_DigestUpdate (m_context, src.m_buffer, src.m_hashLength);
-  if (!ok)
-    throw DigestCalculationError () << errinfo_at_line (__LINE__);
-  
+  update (src.m_buffer, src.m_hashLength);
+
   return *this;
 }
 
diff --git a/model/sync-digest.h b/model/sync-digest.h
index fca9798..d0c76f5 100644
--- a/model/sync-digest.h
+++ b/model/sync-digest.h
@@ -44,6 +44,12 @@
   Digest ();
 
   /**
+   * @brief Reset digest to the initial state
+   */
+  void
+  reset ();
+
+  /**
    * @brief Destructor
    */
   ~Digest ();
@@ -65,7 +71,7 @@
   operator == (Digest &digest);
 
   /**
-   * @brief Combine digests
+   * @brief Add existing digest to digest calculation
    * @param src digest to combine with
    *
    * The result of this combination is  hash (hash (...))
@@ -73,14 +79,42 @@
   Digest &
   operator << (const Digest &src);
 
+  /**
+   * @brief Add string to digest calculation
+   * @param str string to put into digest
+   */
+  inline Digest &
+  operator << (const std::string &str);
 
-  
+  inline Digest &
+  operator << (uint32_t value);
+
+  // /**
+  //  * @brief Add integer to digest calculation
+  //  * @param value the value to add to the digest
+  //  */
+  // template<class INT>
+  // inline Digest &
+  // operator << (INT value);
   
 private:
   /**
+   * @brief Disabled copy operator 
+   */
+  Digest &
+  operator = (Digest &digest) { return *this; }
+  
+  /**
    * @brief Finalize digest. All subsequent calls to "operator <<" will fire an exception
    */
-  void Finalize ();
+  void
+  finalize ();
+
+  /**
+   * @brief Add size bytes of buffer to the hash
+   */
+  void
+  update (const uint8_t *buffer, size_t size);
   
 private:
   EVP_MD_CTX *m_context;
@@ -90,6 +124,30 @@
 
 struct DigestCalculationError : virtual boost::exception { };
 
+
+Digest &
+Digest::operator << (const std::string &str)
+{
+  update (reinterpret_cast<const uint8_t*> (str.c_str ()), str.size ());
+  return *this;
+}
+
+inline Digest &
+Digest::operator << (uint32_t value)
+{
+  update (reinterpret_cast<const uint8_t*> (&value), sizeof (uint32_t));
+  return *this;
+}
+
+// template<class INT>
+// Digest &
+// Digest::operator << (INT value)
+// {
+//   update (&value, sizeof (INT));
+//   return *this;
+// }
+
+
 } // Sync
 
 #endif // SYNC_DIGEST_H
diff --git a/model/sync-full-leaf.cc b/model/sync-full-leaf.cc
new file mode 100644
index 0000000..f575056
--- /dev/null
+++ b/model/sync-full-leaf.cc
@@ -0,0 +1,51 @@
+/* -*- 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>
+ */
+
+#include "sync-full-leaf.h"
+#include <boost/ref.hpp>
+
+using namespace boost;
+
+namespace Sync {
+
+FullLeaf::FullLeaf (NameInfoConstPtr info, const SeqNo &seq)
+  : Leaf (info, seq)
+{
+  updateDigest ();
+}
+
+void
+FullLeaf::updateDigest ()
+{
+  m_digest.reset ();
+  m_digest << getInfo ().getDigest () << getSeq ().getDigest ();
+}
+
+// from Leaf
+void
+FullLeaf::setSeq (const SeqNo &seq)
+{
+  Leaf::setSeq (seq);
+  updateDigest ();
+}
+
+} // Sync
diff --git a/model/sync-full-leaf.h b/model/sync-full-leaf.h
new file mode 100644
index 0000000..2851c84
--- /dev/null
+++ b/model/sync-full-leaf.h
@@ -0,0 +1,70 @@
+/* -*- 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>
+ */
+
+#ifndef SYNC_FULL_LEAF_H
+#define SYNC_FULL_LEAF_H
+
+#include "sync-leaf.h"
+
+namespace Sync {
+
+/**
+ * @ingroup sync
+ * @brief SYNC leaf for the full state (with support of Digest calculation) 
+ */
+class FullLeaf : public Leaf
+{
+public:
+  /**
+   * @brief Constructor to create an UPDATE diff leaf
+   * @param info Smart pointer to leaf's name
+   * @param seq  Initial sequence number of the pointer
+   */
+  FullLeaf (NameInfoConstPtr info, const SeqNo &seq);
+  virtual ~FullLeaf () { }
+
+  /**
+   * @brief Get hash digest of the leaf
+   *
+   * The underlying Digest object is recalculated on every update or removal
+   * (including updates of child classes)
+   */
+  const Digest &
+  getDigest () const { return m_digest; }  
+
+  // from Leaf
+  virtual void
+  setSeq (const SeqNo &seq);
+  
+private:
+  void
+  updateDigest ();
+
+private:
+  Digest m_digest;
+};
+
+typedef boost::shared_ptr<FullLeaf> FullLeafPtr;
+
+} // Sync
+
+#endif // SYNC_FULL_LEAF_H
diff --git a/model/sync-leaf.cc b/model/sync-leaf.cc
index 2680859..6ff48bc 100644
--- a/model/sync-leaf.cc
+++ b/model/sync-leaf.cc
@@ -19,3 +19,21 @@
  *         卞超轶 Chaoyi Bian <bcy@pku.edu.cn>
  *	   Alexander Afanasyev <alexander.afanasyev@ucla.edu>
  */
+
+#include "sync-leaf.h"
+
+namespace Sync {
+
+Leaf::Leaf (NameInfoConstPtr info, const SeqNo &seq)
+  : m_info (info)
+  , m_seq (seq)
+{
+}
+
+void
+Leaf::setSeq (const SeqNo &seq)
+{
+  m_seq = std::max (m_seq, seq);
+}
+
+} // Sync
diff --git a/model/sync-leaf.h b/model/sync-leaf.h
index 79e6b45..a4c64cf 100644
--- a/model/sync-leaf.h
+++ b/model/sync-leaf.h
@@ -40,32 +40,20 @@
    * @param info Smart pointer to leaf's name
    * @param seq  Initial sequence number of the pointer
    */
-  Leaf (boost::shared_ptr<const NameInfo> info, const SeqNo &seq)
-    : m_info (info)
-    , m_seq (seq)
-  { }
-
-  virtual ~Leaf ()
-  {
-  }
+  Leaf (NameInfoConstPtr info, const SeqNo &seq);
+  virtual ~Leaf () { }
   
   /**
    * @brief Get name of the leaf
    */
   const NameInfo &
-  getInfo () const
-  {
-    return *m_info;
-  }
+  getInfo () const { return *m_info; }
 
   /**
    * @brief Get sequence number of the leaf
    */
   const SeqNo&
-  getSeq () const
-  {
-    return m_seq;
-  }
+  getSeq () const { return m_seq; }
 
   /**
    * @brief Update sequence number of the leaf
@@ -73,11 +61,8 @@
    *
    * Sequence number is updated to the largest value among this->m_seq and seq
    */
-  void
-  setSeq (const SeqNo &seq)
-  {
-    m_seq = std::max (m_seq, seq);
-  }
+  virtual void
+  setSeq (const SeqNo &seq);
   
 private:
   NameInfoConstPtr m_info;
diff --git a/model/sync-ns3-name-info.cc b/model/sync-ns3-name-info.cc
index 459486f..dc3b561 100644
--- a/model/sync-ns3-name-info.cc
+++ b/model/sync-ns3-name-info.cc
@@ -23,6 +23,7 @@
 #include "sync-ns3-name-info.h"
 #include "ns3/ccnx-name-components.h"
 
+#include <boost/foreach.hpp>
 #include <boost/lexical_cast.hpp>
 #include <utility>
 
@@ -31,6 +32,7 @@
 
 namespace Sync {
 
+
 NameInfoConstPtr
 Ns3NameInfo::FindOrCreate (ns3::Ptr<const ns3::CcnxNameComponents> name)
 {
@@ -47,7 +49,8 @@
   : m_name (name)
 {
   m_id = m_ids ++; // set ID for a newly inserted element
-  // m_digest << *name;
+  m_digest << *name;
+  m_digest.getHash (); // finalize digest
 }
 
 string
@@ -69,5 +72,20 @@
     }
 }
 
+Digest &
+operator << (Digest &digest, const ns3::CcnxNameComponents &name)
+{
+  BOOST_FOREACH (const std::string &component, name.GetComponents ())
+    {
+      Digest subhash;
+      subhash << component;
+      subhash.getHash (); // finalize hash
+
+      digest << subhash;
+    }
+
+  return digest;
+}
+
 
 } // Sync
diff --git a/model/sync-ns3-name-info.h b/model/sync-ns3-name-info.h
index ffc26d5..3931c5b 100644
--- a/model/sync-ns3-name-info.h
+++ b/model/sync-ns3-name-info.h
@@ -64,6 +64,9 @@
   ns3::Ptr<const ns3::CcnxNameComponents> m_name;
 };
 
+Digest &
+operator << (Digest &, const ns3::CcnxNameComponents &name);
+
 } // Sync
 
 #endif // SYNC_CCNX_NAME_INFO_H
diff --git a/model/sync-seq-no.h b/model/sync-seq-no.h
index bc6fc0f..fb9e6b8 100644
--- a/model/sync-seq-no.h
+++ b/model/sync-seq-no.h
@@ -24,6 +24,7 @@
 #define SYNC_SEQ_NO_H
 
 #include <boost/cstdint.hpp>
+#include "sync-digest.h"
 
 namespace Sync {
 
@@ -32,7 +33,7 @@
  *
  * 
  */
-struct SeqNo
+class SeqNo
 {
 public:
   /**
@@ -53,23 +54,9 @@
     : m_session (session)
     , m_seq (seq)
   { }
-  
-  /**
-   * @brief Session ID (e.g., after crash, application will choose new session ID.
-   *
-   * Note that session IDs for the same name should always increase. So, the good choice
-   * for the session ID is client's timestamp
-   */
-  uint32_t m_session;
 
-  /**
-   * @brief Sequence number
-   *
-   * Sequence number for a session always starts with 0 and goes to max value.
-   *
-   * For now, wrapping sequence number after max to zero is not supported
-   */
-  uint32_t m_seq;
+  inline Digest
+  getDigest () const;
 
   /**
    * @brief Compare if one sequence number is lower
@@ -94,8 +81,57 @@
   {
     return m_session == seq.m_session && m_seq == seq.m_seq;
   }
+
+  SeqNo &
+  operator = (const SeqNo &seq)
+  {
+    m_session = seq.m_session;
+    m_seq = seq.m_seq;
+
+    return *this;
+  }
+  
+private:
+  inline void
+  updateDigest ();
+  
+private:
+  /**
+   * @brief Session ID (e.g., after crash, application will choose new session ID.
+   *
+   * Note that session IDs for the same name should always increase. So, the good choice
+   * for the session ID is client's timestamp
+   */
+  uint32_t m_session;
+
+  /**
+   * @brief Sequence number
+   *
+   * Sequence number for a session always starts with 0 and goes to max value.
+   *
+   * For now, wrapping sequence number after max to zero is not supported
+   */
+  uint32_t m_seq;
+
+  Digest m_digest;
 };
 
+
+void
+SeqNo::updateDigest ()
+{
+  m_digest.reset ();
+  m_digest << m_session << m_seq;
+}
+  
+Digest
+SeqNo::getDigest () const
+{
+  Digest digest;
+  return digest;
+}
+
+
 } // Sync
 
 #endif // SYNC_SEQ_NO_H