Better wording for transaction fee notification messages
[novacoin.git] / serialize.h
index 2cc9ab3..383c987 100644 (file)
-// Copyright (c) 2009-2010 Satoshi Nakamoto\r
-// Distributed under the MIT/X11 software license, see the accompanying\r
-// file license.txt or http://www.opensource.org/licenses/mit-license.php.\r
-\r
-#include <vector>\r
-#include <map>\r
-#include <boost/type_traits/is_fundamental.hpp>\r
-#if defined(_MSC_VER) || defined(__BORLANDC__)\r
-typedef __int64  int64;\r
-typedef unsigned __int64  uint64;\r
-#else\r
-typedef long long  int64;\r
-typedef unsigned long long  uint64;\r
-#endif\r
-#if defined(_MSC_VER) && _MSC_VER < 1300\r
-#define for  if (false) ; else for\r
-#endif\r
-class CScript;\r
-class CDataStream;\r
-class CAutoFile;\r
-\r
-static const int VERSION = 310;\r
-static const char* pszSubVer = ".5";\r
-\r
-\r
-\r
-\r
-\r
-/////////////////////////////////////////////////////////////////\r
-//\r
-// Templates for serializing to anything that looks like a stream,\r
-// i.e. anything that supports .read(char*, int) and .write(char*, int)\r
-//\r
-\r
-enum\r
-{\r
-    // primary actions\r
-    SER_NETWORK         = (1 << 0),\r
-    SER_DISK            = (1 << 1),\r
-    SER_GETHASH         = (1 << 2),\r
-\r
-    // modifiers\r
-    SER_SKIPSIG         = (1 << 16),\r
-    SER_BLOCKHEADERONLY = (1 << 17),\r
-};\r
-\r
-#define IMPLEMENT_SERIALIZE(statements)    \\r
-    unsigned int GetSerializeSize(int nType=0, int nVersion=VERSION) const  \\r
-    {                                           \\r
-        CSerActionGetSerializeSize ser_action;  \\r
-        const bool fGetSize = true;             \\r
-        const bool fWrite = false;              \\r
-        const bool fRead = false;               \\r
-        unsigned int nSerSize = 0;              \\r
-        ser_streamplaceholder s;                \\r
-        s.nType = nType;                        \\r
-        s.nVersion = nVersion;                  \\r
-        {statements}                            \\r
-        return nSerSize;                        \\r
-    }                                           \\r
-    template<typename Stream>                   \\r
-    void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const  \\r
-    {                                           \\r
-        CSerActionSerialize ser_action;         \\r
-        const bool fGetSize = false;            \\r
-        const bool fWrite = true;               \\r
-        const bool fRead = false;               \\r
-        unsigned int nSerSize = 0;              \\r
-        {statements}                            \\r
-    }                                           \\r
-    template<typename Stream>                   \\r
-    void Unserialize(Stream& s, int nType=0, int nVersion=VERSION)  \\r
-    {                                           \\r
-        CSerActionUnserialize ser_action;       \\r
-        const bool fGetSize = false;            \\r
-        const bool fWrite = false;              \\r
-        const bool fRead = true;                \\r
-        unsigned int nSerSize = 0;              \\r
-        {statements}                            \\r
-    }\r
-\r
-#define READWRITE(obj)      (nSerSize += ::SerReadWrite(s, (obj), nType, nVersion, ser_action))\r
-\r
-#define READWRITEVER(obj)       \\r
-    do {                        \\r
-        READWRITE((obj));       \\r
-        if ((obj) == 10300)     \\r
-            (obj) = 300;        \\r
-    } while (false)\r
-\r
-\r
-\r
-\r
-\r
-\r
-//\r
-// Basic types\r
-//\r
-#define WRITEDATA(s, obj)   s.write((char*)&(obj), sizeof(obj))\r
-#define READDATA(s, obj)    s.read((char*)&(obj), sizeof(obj))\r
-\r
-inline unsigned int GetSerializeSize(char a,           int, int=0) { return sizeof(a); }\r
-inline unsigned int GetSerializeSize(signed char a,    int, int=0) { return sizeof(a); }\r
-inline unsigned int GetSerializeSize(unsigned char a,  int, int=0) { return sizeof(a); }\r
-inline unsigned int GetSerializeSize(signed short a,   int, int=0) { return sizeof(a); }\r
-inline unsigned int GetSerializeSize(unsigned short a, int, int=0) { return sizeof(a); }\r
-inline unsigned int GetSerializeSize(signed int a,     int, int=0) { return sizeof(a); }\r
-inline unsigned int GetSerializeSize(unsigned int a,   int, int=0) { return sizeof(a); }\r
-inline unsigned int GetSerializeSize(signed long a,    int, int=0) { return sizeof(a); }\r
-inline unsigned int GetSerializeSize(unsigned long a,  int, int=0) { return sizeof(a); }\r
-inline unsigned int GetSerializeSize(int64 a,          int, int=0) { return sizeof(a); }\r
-inline unsigned int GetSerializeSize(uint64 a,         int, int=0) { return sizeof(a); }\r
-inline unsigned int GetSerializeSize(float a,          int, int=0) { return sizeof(a); }\r
-inline unsigned int GetSerializeSize(double a,         int, int=0) { return sizeof(a); }\r
-\r
-template<typename Stream> inline void Serialize(Stream& s, char a,           int, int=0) { WRITEDATA(s, a); }\r
-template<typename Stream> inline void Serialize(Stream& s, signed char a,    int, int=0) { WRITEDATA(s, a); }\r
-template<typename Stream> inline void Serialize(Stream& s, unsigned char a,  int, int=0) { WRITEDATA(s, a); }\r
-template<typename Stream> inline void Serialize(Stream& s, signed short a,   int, int=0) { WRITEDATA(s, a); }\r
-template<typename Stream> inline void Serialize(Stream& s, unsigned short a, int, int=0) { WRITEDATA(s, a); }\r
-template<typename Stream> inline void Serialize(Stream& s, signed int a,     int, int=0) { WRITEDATA(s, a); }\r
-template<typename Stream> inline void Serialize(Stream& s, unsigned int a,   int, int=0) { WRITEDATA(s, a); }\r
-template<typename Stream> inline void Serialize(Stream& s, signed long a,    int, int=0) { WRITEDATA(s, a); }\r
-template<typename Stream> inline void Serialize(Stream& s, unsigned long a,  int, int=0) { WRITEDATA(s, a); }\r
-template<typename Stream> inline void Serialize(Stream& s, int64 a,          int, int=0) { WRITEDATA(s, a); }\r
-template<typename Stream> inline void Serialize(Stream& s, uint64 a,         int, int=0) { WRITEDATA(s, a); }\r
-template<typename Stream> inline void Serialize(Stream& s, float a,          int, int=0) { WRITEDATA(s, a); }\r
-template<typename Stream> inline void Serialize(Stream& s, double a,         int, int=0) { WRITEDATA(s, a); }\r
-\r
-template<typename Stream> inline void Unserialize(Stream& s, char& a,           int, int=0) { READDATA(s, a); }\r
-template<typename Stream> inline void Unserialize(Stream& s, signed char& a,    int, int=0) { READDATA(s, a); }\r
-template<typename Stream> inline void Unserialize(Stream& s, unsigned char& a,  int, int=0) { READDATA(s, a); }\r
-template<typename Stream> inline void Unserialize(Stream& s, signed short& a,   int, int=0) { READDATA(s, a); }\r
-template<typename Stream> inline void Unserialize(Stream& s, unsigned short& a, int, int=0) { READDATA(s, a); }\r
-template<typename Stream> inline void Unserialize(Stream& s, signed int& a,     int, int=0) { READDATA(s, a); }\r
-template<typename Stream> inline void Unserialize(Stream& s, unsigned int& a,   int, int=0) { READDATA(s, a); }\r
-template<typename Stream> inline void Unserialize(Stream& s, signed long& a,    int, int=0) { READDATA(s, a); }\r
-template<typename Stream> inline void Unserialize(Stream& s, unsigned long& a,  int, int=0) { READDATA(s, a); }\r
-template<typename Stream> inline void Unserialize(Stream& s, int64& a,          int, int=0) { READDATA(s, a); }\r
-template<typename Stream> inline void Unserialize(Stream& s, uint64& a,         int, int=0) { READDATA(s, a); }\r
-template<typename Stream> inline void Unserialize(Stream& s, float& a,          int, int=0) { READDATA(s, a); }\r
-template<typename Stream> inline void Unserialize(Stream& s, double& a,         int, int=0) { READDATA(s, a); }\r
-\r
-inline unsigned int GetSerializeSize(bool a, int, int=0)                          { return sizeof(char); }\r
-template<typename Stream> inline void Serialize(Stream& s, bool a, int, int=0)    { char f=a; WRITEDATA(s, f); }\r
-template<typename Stream> inline void Unserialize(Stream& s, bool& a, int, int=0) { char f; READDATA(s, f); a=f; }\r
-\r
-\r
-\r
-\r
-\r
-\r
-//\r
-// Compact size\r
-//  size <  253        -- 1 byte\r
-//  size <= USHRT_MAX  -- 3 bytes  (253 + 2 bytes)\r
-//  size <= UINT_MAX   -- 5 bytes  (254 + 4 bytes)\r
-//  size >  UINT_MAX   -- 9 bytes  (255 + 8 bytes)\r
-//\r
-inline unsigned int GetSizeOfCompactSize(uint64 nSize)\r
-{\r
-    if (nSize < UCHAR_MAX-2)     return sizeof(unsigned char);\r
-    else if (nSize <= USHRT_MAX) return sizeof(unsigned char) + sizeof(unsigned short);\r
-    else if (nSize <= UINT_MAX)  return sizeof(unsigned char) + sizeof(unsigned int);\r
-    else                         return sizeof(unsigned char) + sizeof(uint64);\r
-}\r
-\r
-template<typename Stream>\r
-void WriteCompactSize(Stream& os, uint64 nSize)\r
-{\r
-    if (nSize < UCHAR_MAX-2)\r
-    {\r
-        unsigned char chSize = nSize;\r
-        WRITEDATA(os, chSize);\r
-    }\r
-    else if (nSize <= USHRT_MAX)\r
-    {\r
-        unsigned char chSize = UCHAR_MAX-2;\r
-        unsigned short xSize = nSize;\r
-        WRITEDATA(os, chSize);\r
-        WRITEDATA(os, xSize);\r
-    }\r
-    else if (nSize <= UINT_MAX)\r
-    {\r
-        unsigned char chSize = UCHAR_MAX-1;\r
-        unsigned int xSize = nSize;\r
-        WRITEDATA(os, chSize);\r
-        WRITEDATA(os, xSize);\r
-    }\r
-    else\r
-    {\r
-        unsigned char chSize = UCHAR_MAX;\r
-        WRITEDATA(os, chSize);\r
-        WRITEDATA(os, nSize);\r
-    }\r
-    return;\r
-}\r
-\r
-template<typename Stream>\r
-uint64 ReadCompactSize(Stream& is)\r
-{\r
-    unsigned char chSize;\r
-    READDATA(is, chSize);\r
-    uint64 nSizeRet = 0;\r
-    if (chSize < UCHAR_MAX-2)\r
-    {\r
-        nSizeRet = chSize;\r
-    }\r
-    else if (chSize == UCHAR_MAX-2)\r
-    {\r
-        unsigned short nSize;\r
-        READDATA(is, nSize);\r
-        nSizeRet = nSize;\r
-    }\r
-    else if (chSize == UCHAR_MAX-1)\r
-    {\r
-        unsigned int nSize;\r
-        READDATA(is, nSize);\r
-        nSizeRet = nSize;\r
-    }\r
-    else\r
-    {\r
-        uint64 nSize;\r
-        READDATA(is, nSize);\r
-        nSizeRet = nSize;\r
-    }\r
-    if (nSizeRet > (uint64)INT_MAX)\r
-        throw std::ios_base::failure("ReadCompactSize() : size too large");\r
-    return nSizeRet;\r
-}\r
-\r
-\r
-\r
-//\r
-// Wrapper for serializing arrays and POD\r
-// There's a clever template way to make arrays serialize normally, but MSVC6 doesn't support it\r
-//\r
-#define FLATDATA(obj)   REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj)))\r
-class CFlatData\r
-{\r
-protected:\r
-    char* pbegin;\r
-    char* pend;\r
-public:\r
-    CFlatData(void* pbeginIn, void* pendIn) : pbegin((char*)pbeginIn), pend((char*)pendIn) { }\r
-    char* begin() { return pbegin; }\r
-    const char* begin() const { return pbegin; }\r
-    char* end() { return pend; }\r
-    const char* end() const { return pend; }\r
-\r
-    unsigned int GetSerializeSize(int, int=0) const\r
-    {\r
-        return pend - pbegin;\r
-    }\r
-\r
-    template<typename Stream>\r
-    void Serialize(Stream& s, int, int=0) const\r
-    {\r
-        s.write(pbegin, pend - pbegin);\r
-    }\r
-\r
-    template<typename Stream>\r
-    void Unserialize(Stream& s, int, int=0)\r
-    {\r
-        s.read(pbegin, pend - pbegin);\r
-    }\r
-};\r
-\r
-\r
-\r
-//\r
-// string stored as a fixed length field\r
-//\r
-template<std::size_t LEN>\r
-class CFixedFieldString\r
-{\r
-protected:\r
-    const string* pcstr;\r
-    string* pstr;\r
-public:\r
-    explicit CFixedFieldString(const string& str) : pcstr(&str), pstr(NULL) { }\r
-    explicit CFixedFieldString(string& str) : pcstr(&str), pstr(&str) { }\r
-\r
-    unsigned int GetSerializeSize(int, int=0) const\r
-    {\r
-        return LEN;\r
-    }\r
-\r
-    template<typename Stream>\r
-    void Serialize(Stream& s, int, int=0) const\r
-    {\r
-        char pszBuf[LEN];\r
-        strncpy(pszBuf, pcstr->c_str(), LEN);\r
-        s.write(pszBuf, LEN);\r
-    }\r
-\r
-    template<typename Stream>\r
-    void Unserialize(Stream& s, int, int=0)\r
-    {\r
-        if (pstr == NULL)\r
-            throw std::ios_base::failure("CFixedFieldString::Unserialize : trying to unserialize to const string");\r
-        char pszBuf[LEN+1];\r
-        s.read(pszBuf, LEN);\r
-        pszBuf[LEN] = '\0';\r
-        *pstr = pszBuf;\r
-    }\r
-};\r
-\r
-\r
-\r
-\r
-\r
-//\r
-// Forward declarations\r
-//\r
-\r
-// string\r
-template<typename C> unsigned int GetSerializeSize(const basic_string<C>& str, int, int=0);\r
-template<typename Stream, typename C> void Serialize(Stream& os, const basic_string<C>& str, int, int=0);\r
-template<typename Stream, typename C> void Unserialize(Stream& is, basic_string<C>& str, int, int=0);\r
-\r
-// vector\r
-template<typename T, typename A> unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&);\r
-template<typename T, typename A> unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&);\r
-template<typename T, typename A> inline unsigned int GetSerializeSize(const std::vector<T, A>& v, int nType, int nVersion=VERSION);\r
-template<typename Stream, typename T, typename A> void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&);\r
-template<typename Stream, typename T, typename A> void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&);\r
-template<typename Stream, typename T, typename A> inline void Serialize(Stream& os, const std::vector<T, A>& v, int nType, int nVersion=VERSION);\r
-template<typename Stream, typename T, typename A> void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&);\r
-template<typename Stream, typename T, typename A> void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&);\r
-template<typename Stream, typename T, typename A> inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersion=VERSION);\r
-\r
-// others derived from vector\r
-extern inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion=VERSION);\r
-template<typename Stream> void Serialize(Stream& os, const CScript& v, int nType, int nVersion=VERSION);\r
-template<typename Stream> void Unserialize(Stream& is, CScript& v, int nType, int nVersion=VERSION);\r
-\r
-// pair\r
-template<typename K, typename T> unsigned int GetSerializeSize(const std::pair<K, T>& item, int nType, int nVersion=VERSION);\r
-template<typename Stream, typename K, typename T> void Serialize(Stream& os, const std::pair<K, T>& item, int nType, int nVersion=VERSION);\r
-template<typename Stream, typename K, typename T> void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion=VERSION);\r
-\r
-// map\r
-template<typename K, typename T, typename Pred, typename A> unsigned int GetSerializeSize(const std::map<K, T, Pred, A>& m, int nType, int nVersion=VERSION);\r
-template<typename Stream, typename K, typename T, typename Pred, typename A> void Serialize(Stream& os, const std::map<K, T, Pred, A>& m, int nType, int nVersion=VERSION);\r
-template<typename Stream, typename K, typename T, typename Pred, typename A> void Unserialize(Stream& is, std::map<K, T, Pred, A>& m, int nType, int nVersion=VERSION);\r
-\r
-// set\r
-template<typename K, typename Pred, typename A> unsigned int GetSerializeSize(const std::set<K, Pred, A>& m, int nType, int nVersion=VERSION);\r
-template<typename Stream, typename K, typename Pred, typename A> void Serialize(Stream& os, const std::set<K, Pred, A>& m, int nType, int nVersion=VERSION);\r
-template<typename Stream, typename K, typename Pred, typename A> void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion=VERSION);\r
-\r
-\r
-\r
-\r
-\r
-//\r
-// If none of the specialized versions above matched, default to calling member function.\r
-// "int nType" is changed to "long nType" to keep from getting an ambiguous overload error.\r
-// The compiler will only cast int to long if none of the other templates matched.\r
-// Thanks to Boost serialization for this idea.\r
-//\r
-template<typename T>\r
-inline unsigned int GetSerializeSize(const T& a, long nType, int nVersion=VERSION)\r
-{\r
-    return a.GetSerializeSize((int)nType, nVersion);\r
-}\r
-\r
-template<typename Stream, typename T>\r
-inline void Serialize(Stream& os, const T& a, long nType, int nVersion=VERSION)\r
-{\r
-    a.Serialize(os, (int)nType, nVersion);\r
-}\r
-\r
-template<typename Stream, typename T>\r
-inline void Unserialize(Stream& is, T& a, long nType, int nVersion=VERSION)\r
-{\r
-    a.Unserialize(is, (int)nType, nVersion);\r
-}\r
-\r
-\r
-\r
-\r
-\r
-//\r
-// string\r
-//\r
-template<typename C>\r
-unsigned int GetSerializeSize(const basic_string<C>& str, int, int)\r
-{\r
-    return GetSizeOfCompactSize(str.size()) + str.size() * sizeof(str[0]);\r
-}\r
-\r
-template<typename Stream, typename C>\r
-void Serialize(Stream& os, const basic_string<C>& str, int, int)\r
-{\r
-    WriteCompactSize(os, str.size());\r
-    if (!str.empty())\r
-        os.write((char*)&str[0], str.size() * sizeof(str[0]));\r
-}\r
-\r
-template<typename Stream, typename C>\r
-void Unserialize(Stream& is, basic_string<C>& str, int, int)\r
-{\r
-    unsigned int nSize = ReadCompactSize(is);\r
-    str.resize(nSize);\r
-    if (nSize != 0)\r
-        is.read((char*)&str[0], nSize * sizeof(str[0]));\r
-}\r
-\r
-\r
-\r
-//\r
-// vector\r
-//\r
-template<typename T, typename A>\r
-unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&)\r
-{\r
-    return (GetSizeOfCompactSize(v.size()) + v.size() * sizeof(T));\r
-}\r
-\r
-template<typename T, typename A>\r
-unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&)\r
-{\r
-    unsigned int nSize = GetSizeOfCompactSize(v.size());\r
-    for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi)\r
-        nSize += GetSerializeSize((*vi), nType, nVersion);\r
-    return nSize;\r
-}\r
-\r
-template<typename T, typename A>\r
-inline unsigned int GetSerializeSize(const std::vector<T, A>& v, int nType, int nVersion)\r
-{\r
-    return GetSerializeSize_impl(v, nType, nVersion, boost::is_fundamental<T>());\r
-}\r
-\r
-\r
-template<typename Stream, typename T, typename A>\r
-void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&)\r
-{\r
-    WriteCompactSize(os, v.size());\r
-    if (!v.empty())\r
-        os.write((char*)&v[0], v.size() * sizeof(T));\r
-}\r
-\r
-template<typename Stream, typename T, typename A>\r
-void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&)\r
-{\r
-    WriteCompactSize(os, v.size());\r
-    for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi)\r
-        ::Serialize(os, (*vi), nType, nVersion);\r
-}\r
-\r
-template<typename Stream, typename T, typename A>\r
-inline void Serialize(Stream& os, const std::vector<T, A>& v, int nType, int nVersion)\r
-{\r
-    Serialize_impl(os, v, nType, nVersion, boost::is_fundamental<T>());\r
-}\r
-\r
-\r
-template<typename Stream, typename T, typename A>\r
-void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&)\r
-{\r
-    //unsigned int nSize = ReadCompactSize(is);\r
-    //v.resize(nSize);\r
-    //is.read((char*)&v[0], nSize * sizeof(T));\r
-\r
-    // Limit size per read so bogus size value won't cause out of memory\r
-    v.clear();\r
-    unsigned int nSize = ReadCompactSize(is);\r
-    unsigned int i = 0;\r
-    while (i < nSize)\r
-    {\r
-        unsigned int blk = min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));\r
-        v.resize(i + blk);\r
-        is.read((char*)&v[i], blk * sizeof(T));\r
-        i += blk;\r
-    }\r
-}\r
-\r
-template<typename Stream, typename T, typename A>\r
-void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&)\r
-{\r
-    //unsigned int nSize = ReadCompactSize(is);\r
-    //v.resize(nSize);\r
-    //for (std::vector<T, A>::iterator vi = v.begin(); vi != v.end(); ++vi)\r
-    //    Unserialize(is, (*vi), nType, nVersion);\r
-\r
-    v.clear();\r
-    unsigned int nSize = ReadCompactSize(is);\r
-    unsigned int i = 0;\r
-    unsigned int nMid = 0;\r
-    while (nMid < nSize)\r
-    {\r
-        nMid += 5000000 / sizeof(T);\r
-        if (nMid > nSize)\r
-            nMid = nSize;\r
-        v.resize(nMid);\r
-        for (; i < nMid; i++)\r
-            Unserialize(is, v[i], nType, nVersion);\r
-    }\r
-}\r
-\r
-template<typename Stream, typename T, typename A>\r
-inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersion)\r
-{\r
-    Unserialize_impl(is, v, nType, nVersion, boost::is_fundamental<T>());\r
-}\r
-\r
-\r
-\r
-//\r
-// others derived from vector\r
-//\r
-inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion)\r
-{\r
-    return GetSerializeSize((const vector<unsigned char>&)v, nType, nVersion);\r
-}\r
-\r
-template<typename Stream>\r
-void Serialize(Stream& os, const CScript& v, int nType, int nVersion)\r
-{\r
-    Serialize(os, (const vector<unsigned char>&)v, nType, nVersion);\r
-}\r
-\r
-template<typename Stream>\r
-void Unserialize(Stream& is, CScript& v, int nType, int nVersion)\r
-{\r
-    Unserialize(is, (vector<unsigned char>&)v, nType, nVersion);\r
-}\r
-\r
-\r
-\r
-//\r
-// pair\r
-//\r
-template<typename K, typename T>\r
-unsigned int GetSerializeSize(const std::pair<K, T>& item, int nType, int nVersion)\r
-{\r
-    return GetSerializeSize(item.first, nType, nVersion) + GetSerializeSize(item.second, nType, nVersion);\r
-}\r
-\r
-template<typename Stream, typename K, typename T>\r
-void Serialize(Stream& os, const std::pair<K, T>& item, int nType, int nVersion)\r
-{\r
-    Serialize(os, item.first, nType, nVersion);\r
-    Serialize(os, item.second, nType, nVersion);\r
-}\r
-\r
-template<typename Stream, typename K, typename T>\r
-void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion)\r
-{\r
-    Unserialize(is, item.first, nType, nVersion);\r
-    Unserialize(is, item.second, nType, nVersion);\r
-}\r
-\r
-\r
-\r
-//\r
-// map\r
-//\r
-template<typename K, typename T, typename Pred, typename A>\r
-unsigned int GetSerializeSize(const std::map<K, T, Pred, A>& m, int nType, int nVersion)\r
-{\r
-    unsigned int nSize = GetSizeOfCompactSize(m.size());\r
-    for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi)\r
-        nSize += GetSerializeSize((*mi), nType, nVersion);\r
-    return nSize;\r
-}\r
-\r
-template<typename Stream, typename K, typename T, typename Pred, typename A>\r
-void Serialize(Stream& os, const std::map<K, T, Pred, A>& m, int nType, int nVersion)\r
-{\r
-    WriteCompactSize(os, m.size());\r
-    for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi)\r
-        Serialize(os, (*mi), nType, nVersion);\r
-}\r
-\r
-template<typename Stream, typename K, typename T, typename Pred, typename A>\r
-void Unserialize(Stream& is, std::map<K, T, Pred, A>& m, int nType, int nVersion)\r
-{\r
-    m.clear();\r
-    unsigned int nSize = ReadCompactSize(is);\r
-    typename std::map<K, T, Pred, A>::iterator mi = m.begin();\r
-    for (unsigned int i = 0; i < nSize; i++)\r
-    {\r
-        pair<K, T> item;\r
-        Unserialize(is, item, nType, nVersion);\r
-        mi = m.insert(mi, item);\r
-    }\r
-}\r
-\r
-\r
-\r
-//\r
-// set\r
-//\r
-template<typename K, typename Pred, typename A>\r
-unsigned int GetSerializeSize(const std::set<K, Pred, A>& m, int nType, int nVersion)\r
-{\r
-    unsigned int nSize = GetSizeOfCompactSize(m.size());\r
-    for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it)\r
-        nSize += GetSerializeSize((*it), nType, nVersion);\r
-    return nSize;\r
-}\r
-\r
-template<typename Stream, typename K, typename Pred, typename A>\r
-void Serialize(Stream& os, const std::set<K, Pred, A>& m, int nType, int nVersion)\r
-{\r
-    WriteCompactSize(os, m.size());\r
-    for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it)\r
-        Serialize(os, (*it), nType, nVersion);\r
-}\r
-\r
-template<typename Stream, typename K, typename Pred, typename A>\r
-void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion)\r
-{\r
-    m.clear();\r
-    unsigned int nSize = ReadCompactSize(is);\r
-    typename std::set<K, Pred, A>::iterator it = m.begin();\r
-    for (unsigned int i = 0; i < nSize; i++)\r
-    {\r
-        K key;\r
-        Unserialize(is, key, nType, nVersion);\r
-        it = m.insert(it, key);\r
-    }\r
-}\r
-\r
-\r
-\r
-//\r
-// Support for IMPLEMENT_SERIALIZE and READWRITE macro\r
-//\r
-class CSerActionGetSerializeSize { };\r
-class CSerActionSerialize { };\r
-class CSerActionUnserialize { };\r
-\r
-template<typename Stream, typename T>\r
-inline unsigned int SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionGetSerializeSize ser_action)\r
-{\r
-    return ::GetSerializeSize(obj, nType, nVersion);\r
-}\r
-\r
-template<typename Stream, typename T>\r
-inline unsigned int SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionSerialize ser_action)\r
-{\r
-    ::Serialize(s, obj, nType, nVersion);\r
-    return 0;\r
-}\r
-\r
-template<typename Stream, typename T>\r
-inline unsigned int SerReadWrite(Stream& s, T& obj, int nType, int nVersion, CSerActionUnserialize ser_action)\r
-{\r
-    ::Unserialize(s, obj, nType, nVersion);\r
-    return 0;\r
-}\r
-\r
-struct ser_streamplaceholder\r
-{\r
-    int nType;\r
-    int nVersion;\r
-};\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-//\r
-// Allocator that clears its contents before deletion\r
-//\r
-template<typename T>\r
-struct secure_allocator : public std::allocator<T>\r
-{\r
-    // MSVC8 default copy constructor is broken\r
-    typedef std::allocator<T> base;\r
-    typedef typename base::size_type size_type;\r
-    typedef typename base::difference_type  difference_type;\r
-    typedef typename base::pointer pointer;\r
-    typedef typename base::const_pointer const_pointer;\r
-    typedef typename base::reference reference;\r
-    typedef typename base::const_reference const_reference;\r
-    typedef typename base::value_type value_type;\r
-    secure_allocator() throw() {}\r
-    secure_allocator(const secure_allocator& a) throw() : base(a) {}\r
-    ~secure_allocator() throw() {}\r
-    template<typename _Other> struct rebind\r
-    { typedef secure_allocator<_Other> other; };\r
-\r
-    void deallocate(T* p, std::size_t n)\r
-    {\r
-        if (p != NULL)\r
-            memset(p, 0, sizeof(T) * n);\r
-        allocator<T>::deallocate(p, n);\r
-    }\r
-};\r
-\r
-\r
-\r
-//\r
-// Double ended buffer combining vector and stream-like interfaces.\r
-// >> and << read and write unformatted data using the above serialization templates.\r
-// Fills with data in linear time; some stringstream implementations take N^2 time.\r
-//\r
-class CDataStream\r
-{\r
-protected:\r
-    typedef vector<char, secure_allocator<char> > vector_type;\r
-    vector_type vch;\r
-    unsigned int nReadPos;\r
-    short state;\r
-    short exceptmask;\r
-public:\r
-    int nType;\r
-    int nVersion;\r
-\r
-    typedef vector_type::allocator_type   allocator_type;\r
-    typedef vector_type::size_type        size_type;\r
-    typedef vector_type::difference_type  difference_type;\r
-    typedef vector_type::reference        reference;\r
-    typedef vector_type::const_reference  const_reference;\r
-    typedef vector_type::value_type       value_type;\r
-    typedef vector_type::iterator         iterator;\r
-    typedef vector_type::const_iterator   const_iterator;\r
-    typedef vector_type::reverse_iterator reverse_iterator;\r
-\r
-    explicit CDataStream(int nTypeIn=0, int nVersionIn=VERSION)\r
-    {\r
-        Init(nTypeIn, nVersionIn);\r
-    }\r
-\r
-    CDataStream(const_iterator pbegin, const_iterator pend, int nTypeIn=0, int nVersionIn=VERSION) : vch(pbegin, pend)\r
-    {\r
-        Init(nTypeIn, nVersionIn);\r
-    }\r
-\r
-#if !defined(_MSC_VER) || _MSC_VER >= 1300\r
-    CDataStream(const char* pbegin, const char* pend, int nTypeIn=0, int nVersionIn=VERSION) : vch(pbegin, pend)\r
-    {\r
-        Init(nTypeIn, nVersionIn);\r
-    }\r
-#endif\r
-\r
-    CDataStream(const vector_type& vchIn, int nTypeIn=0, int nVersionIn=VERSION) : vch(vchIn.begin(), vchIn.end())\r
-    {\r
-        Init(nTypeIn, nVersionIn);\r
-    }\r
-\r
-    CDataStream(const vector<char>& vchIn, int nTypeIn=0, int nVersionIn=VERSION) : vch(vchIn.begin(), vchIn.end())\r
-    {\r
-        Init(nTypeIn, nVersionIn);\r
-    }\r
-\r
-    CDataStream(const vector<unsigned char>& vchIn, int nTypeIn=0, int nVersionIn=VERSION) : vch((char*)&vchIn.begin()[0], (char*)&vchIn.end()[0])\r
-    {\r
-        Init(nTypeIn, nVersionIn);\r
-    }\r
-\r
-    void Init(int nTypeIn=0, int nVersionIn=VERSION)\r
-    {\r
-        nReadPos = 0;\r
-        nType = nTypeIn;\r
-        nVersion = nVersionIn;\r
-        state = 0;\r
-        exceptmask = ios::badbit | ios::failbit;\r
-    }\r
-\r
-    CDataStream& operator+=(const CDataStream& b)\r
-    {\r
-        vch.insert(vch.end(), b.begin(), b.end());\r
-        return *this;\r
-    }\r
-\r
-    friend CDataStream operator+(const CDataStream& a, const CDataStream& b)\r
-    {\r
-        CDataStream ret = a;\r
-        ret += b;\r
-        return (ret);\r
-    }\r
-\r
-    string str() const\r
-    {\r
-        return (string(begin(), end()));\r
-    }\r
-\r
-\r
-    //\r
-    // Vector subset\r
-    //\r
-    const_iterator begin() const                     { return vch.begin() + nReadPos; }\r
-    iterator begin()                                 { return vch.begin() + nReadPos; }\r
-    const_iterator end() const                       { return vch.end(); }\r
-    iterator end()                                   { return vch.end(); }\r
-    size_type size() const                           { return vch.size() - nReadPos; }\r
-    bool empty() const                               { return vch.size() == nReadPos; }\r
-    void resize(size_type n, value_type c=0)         { vch.resize(n + nReadPos, c); }\r
-    void reserve(size_type n)                        { vch.reserve(n + nReadPos); }\r
-    const_reference operator[](size_type pos) const  { return vch[pos + nReadPos]; }\r
-    reference operator[](size_type pos)              { return vch[pos + nReadPos]; }\r
-    void clear()                                     { vch.clear(); nReadPos = 0; }\r
-    iterator insert(iterator it, const char& x=char()) { return vch.insert(it, x); }\r
-    void insert(iterator it, size_type n, const char& x) { vch.insert(it, n, x); }\r
-\r
-    void insert(iterator it, const_iterator first, const_iterator last)\r
-    {\r
-        if (it == vch.begin() + nReadPos && last - first <= nReadPos)\r
-        {\r
-            // special case for inserting at the front when there's room\r
-            nReadPos -= (last - first);\r
-            memcpy(&vch[nReadPos], &first[0], last - first);\r
-        }\r
-        else\r
-            vch.insert(it, first, last);\r
-    }\r
-\r
-    void insert(iterator it, vector<char>::const_iterator first, vector<char>::const_iterator last)\r
-    {\r
-        if (it == vch.begin() + nReadPos && last - first <= nReadPos)\r
-        {\r
-            // special case for inserting at the front when there's room\r
-            nReadPos -= (last - first);\r
-            memcpy(&vch[nReadPos], &first[0], last - first);\r
-        }\r
-        else\r
-            vch.insert(it, first, last);\r
-    }\r
-\r
-#if !defined(_MSC_VER) || _MSC_VER >= 1300\r
-    void insert(iterator it, const char* first, const char* last)\r
-    {\r
-        if (it == vch.begin() + nReadPos && last - first <= nReadPos)\r
-        {\r
-            // special case for inserting at the front when there's room\r
-            nReadPos -= (last - first);\r
-            memcpy(&vch[nReadPos], &first[0], last - first);\r
-        }\r
-        else\r
-            vch.insert(it, first, last);\r
-    }\r
-#endif\r
-\r
-    iterator erase(iterator it)\r
-    {\r
-        if (it == vch.begin() + nReadPos)\r
-        {\r
-            // special case for erasing from the front\r
-            if (++nReadPos >= vch.size())\r
-            {\r
-                // whenever we reach the end, we take the opportunity to clear the buffer\r
-                nReadPos = 0;\r
-                return vch.erase(vch.begin(), vch.end());\r
-            }\r
-            return vch.begin() + nReadPos;\r
-        }\r
-        else\r
-            return vch.erase(it);\r
-    }\r
-\r
-    iterator erase(iterator first, iterator last)\r
-    {\r
-        if (first == vch.begin() + nReadPos)\r
-        {\r
-            // special case for erasing from the front\r
-            if (last == vch.end())\r
-            {\r
-                nReadPos = 0;\r
-                return vch.erase(vch.begin(), vch.end());\r
-            }\r
-            else\r
-            {\r
-                nReadPos = (last - vch.begin());\r
-                return last;\r
-            }\r
-        }\r
-        else\r
-            return vch.erase(first, last);\r
-    }\r
-\r
-    inline void Compact()\r
-    {\r
-        vch.erase(vch.begin(), vch.begin() + nReadPos);\r
-        nReadPos = 0;\r
-    }\r
-\r
-    bool Rewind(size_type n)\r
-    {\r
-        // Rewind by n characters if the buffer hasn't been compacted yet\r
-        if (n > nReadPos)\r
-            return false;\r
-        nReadPos -= n;\r
-        return true;\r
-    }\r
-\r
-\r
-    //\r
-    // Stream subset\r
-    //\r
-    void setstate(short bits, const char* psz)\r
-    {\r
-        state |= bits;\r
-        if (state & exceptmask)\r
-            throw std::ios_base::failure(psz);\r
-    }\r
-\r
-    bool eof() const             { return size() == 0; }\r
-    bool fail() const            { return state & (ios::badbit | ios::failbit); }\r
-    bool good() const            { return !eof() && (state == 0); }\r
-    void clear(short n)          { state = n; }  // name conflict with vector clear()\r
-    short exceptions()           { return exceptmask; }\r
-    short exceptions(short mask) { short prev = exceptmask; exceptmask = mask; setstate(0, "CDataStream"); return prev; }\r
-    CDataStream* rdbuf()         { return this; }\r
-    int in_avail()               { return size(); }\r
-\r
-    void SetType(int n)          { nType = n; }\r
-    int GetType()                { return nType; }\r
-    void SetVersion(int n)       { nVersion = n; }\r
-    int GetVersion()             { return nVersion; }\r
-    void ReadVersion()           { *this >> nVersion; }\r
-    void WriteVersion()          { *this << nVersion; }\r
-\r
-    CDataStream& read(char* pch, int nSize)\r
-    {\r
-        // Read from the beginning of the buffer\r
-        assert(nSize >= 0);\r
-        unsigned int nReadPosNext = nReadPos + nSize;\r
-        if (nReadPosNext >= vch.size())\r
-        {\r
-            if (nReadPosNext > vch.size())\r
-            {\r
-                setstate(ios::failbit, "CDataStream::read() : end of data");\r
-                memset(pch, 0, nSize);\r
-                nSize = vch.size() - nReadPos;\r
-            }\r
-            memcpy(pch, &vch[nReadPos], nSize);\r
-            nReadPos = 0;\r
-            vch.clear();\r
-            return (*this);\r
-        }\r
-        memcpy(pch, &vch[nReadPos], nSize);\r
-        nReadPos = nReadPosNext;\r
-        return (*this);\r
-    }\r
-\r
-    CDataStream& ignore(int nSize)\r
-    {\r
-        // Ignore from the beginning of the buffer\r
-        assert(nSize >= 0);\r
-        unsigned int nReadPosNext = nReadPos + nSize;\r
-        if (nReadPosNext >= vch.size())\r
-        {\r
-            if (nReadPosNext > vch.size())\r
-            {\r
-                setstate(ios::failbit, "CDataStream::ignore() : end of data");\r
-                nSize = vch.size() - nReadPos;\r
-            }\r
-            nReadPos = 0;\r
-            vch.clear();\r
-            return (*this);\r
-        }\r
-        nReadPos = nReadPosNext;\r
-        return (*this);\r
-    }\r
-\r
-    CDataStream& write(const char* pch, int nSize)\r
-    {\r
-        // Write to the end of the buffer\r
-        assert(nSize >= 0);\r
-        vch.insert(vch.end(), pch, pch + nSize);\r
-        return (*this);\r
-    }\r
-\r
-    template<typename Stream>\r
-    void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const\r
-    {\r
-        // Special case: stream << stream concatenates like stream += stream\r
-        if (!vch.empty())\r
-            s.write((char*)&vch[0], vch.size() * sizeof(vch[0]));\r
-    }\r
-\r
-    template<typename T>\r
-    unsigned int GetSerializeSize(const T& obj)\r
-    {\r
-        // Tells the size of the object if serialized to this stream\r
-        return ::GetSerializeSize(obj, nType, nVersion);\r
-    }\r
-\r
-    template<typename T>\r
-    CDataStream& operator<<(const T& obj)\r
-    {\r
-        // Serialize to this stream\r
-        ::Serialize(*this, obj, nType, nVersion);\r
-        return (*this);\r
-    }\r
-\r
-    template<typename T>\r
-    CDataStream& operator>>(T& obj)\r
-    {\r
-        // Unserialize from this stream\r
-        ::Unserialize(*this, obj, nType, nVersion);\r
-        return (*this);\r
-    }\r
-};\r
-\r
-#ifdef TESTCDATASTREAM\r
-// VC6sp6\r
-// CDataStream:\r
-// n=1000       0 seconds\r
-// n=2000       0 seconds\r
-// n=4000       0 seconds\r
-// n=8000       0 seconds\r
-// n=16000      0 seconds\r
-// n=32000      0 seconds\r
-// n=64000      1 seconds\r
-// n=128000     1 seconds\r
-// n=256000     2 seconds\r
-// n=512000     4 seconds\r
-// n=1024000    8 seconds\r
-// n=2048000    16 seconds\r
-// n=4096000    32 seconds\r
-// stringstream:\r
-// n=1000       1 seconds\r
-// n=2000       1 seconds\r
-// n=4000       13 seconds\r
-// n=8000       87 seconds\r
-// n=16000      400 seconds\r
-// n=32000      1660 seconds\r
-// n=64000      6749 seconds\r
-// n=128000     27241 seconds\r
-// n=256000     109804 seconds\r
-#include <iostream>\r
-int main(int argc, char *argv[])\r
-{\r
-    vector<unsigned char> vch(0xcc, 250);\r
-    printf("CDataStream:\n");\r
-    for (int n = 1000; n <= 4500000; n *= 2)\r
-    {\r
-        CDataStream ss;\r
-        time_t nStart = time(NULL);\r
-        for (int i = 0; i < n; i++)\r
-            ss.write((char*)&vch[0], vch.size());\r
-        printf("n=%-10d %d seconds\n", n, time(NULL) - nStart);\r
-    }\r
-    printf("stringstream:\n");\r
-    for (int n = 1000; n <= 4500000; n *= 2)\r
-    {\r
-        stringstream ss;\r
-        time_t nStart = time(NULL);\r
-        for (int i = 0; i < n; i++)\r
-            ss.write((char*)&vch[0], vch.size());\r
-        printf("n=%-10d %d seconds\n", n, time(NULL) - nStart);\r
-    }\r
-}\r
-#endif\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-//\r
-// Automatic closing wrapper for FILE*\r
-//  - Will automatically close the file when it goes out of scope if not null.\r
-//  - If you're returning the file pointer, return file.release().\r
-//  - If you need to close the file early, use file.fclose() instead of fclose(file).\r
-//\r
-class CAutoFile\r
-{\r
-protected:\r
-    FILE* file;\r
-    short state;\r
-    short exceptmask;\r
-public:\r
-    int nType;\r
-    int nVersion;\r
-\r
-    typedef FILE element_type;\r
-\r
-    CAutoFile(FILE* filenew=NULL, int nTypeIn=SER_DISK, int nVersionIn=VERSION)\r
-    {\r
-        file = filenew;\r
-        nType = nTypeIn;\r
-        nVersion = nVersionIn;\r
-        state = 0;\r
-        exceptmask = ios::badbit | ios::failbit;\r
-    }\r
-\r
-    ~CAutoFile()\r
-    {\r
-        fclose();\r
-    }\r
-\r
-    void fclose()\r
-    {\r
-        if (file != NULL && file != stdin && file != stdout && file != stderr)\r
-            ::fclose(file);\r
-        file = NULL;\r
-    }\r
-\r
-    FILE* release()             { FILE* ret = file; file = NULL; return ret; }\r
-    operator FILE*()            { return file; }\r
-    FILE* operator->()          { return file; }\r
-    FILE& operator*()           { return *file; }\r
-    FILE** operator&()          { return &file; }\r
-    FILE* operator=(FILE* pnew) { return file = pnew; }\r
-    bool operator!()            { return (file == NULL); }\r
-\r
-\r
-    //\r
-    // Stream subset\r
-    //\r
-    void setstate(short bits, const char* psz)\r
-    {\r
-        state |= bits;\r
-        if (state & exceptmask)\r
-            throw std::ios_base::failure(psz);\r
-    }\r
-\r
-    bool fail() const            { return state & (ios::badbit | ios::failbit); }\r
-    bool good() const            { return state == 0; }\r
-    void clear(short n = 0)      { state = n; }\r
-    short exceptions()           { return exceptmask; }\r
-    short exceptions(short mask) { short prev = exceptmask; exceptmask = mask; setstate(0, "CAutoFile"); return prev; }\r
-\r
-    void SetType(int n)          { nType = n; }\r
-    int GetType()                { return nType; }\r
-    void SetVersion(int n)       { nVersion = n; }\r
-    int GetVersion()             { return nVersion; }\r
-    void ReadVersion()           { *this >> nVersion; }\r
-    void WriteVersion()          { *this << nVersion; }\r
-\r
-    CAutoFile& read(char* pch, int nSize)\r
-    {\r
-        if (!file)\r
-            throw std::ios_base::failure("CAutoFile::read : file handle is NULL");\r
-        if (fread(pch, 1, nSize, file) != nSize)\r
-            setstate(ios::failbit, feof(file) ? "CAutoFile::read : end of file" : "CAutoFile::read : fread failed");\r
-        return (*this);\r
-    }\r
-\r
-    CAutoFile& write(const char* pch, int nSize)\r
-    {\r
-        if (!file)\r
-            throw std::ios_base::failure("CAutoFile::write : file handle is NULL");\r
-        if (fwrite(pch, 1, nSize, file) != nSize)\r
-            setstate(ios::failbit, "CAutoFile::write : write failed");\r
-        return (*this);\r
-    }\r
-\r
-    template<typename T>\r
-    unsigned int GetSerializeSize(const T& obj)\r
-    {\r
-        // Tells the size of the object if serialized to this stream\r
-        return ::GetSerializeSize(obj, nType, nVersion);\r
-    }\r
-\r
-    template<typename T>\r
-    CAutoFile& operator<<(const T& obj)\r
-    {\r
-        // Serialize to this stream\r
-        if (!file)\r
-            throw std::ios_base::failure("CAutoFile::operator<< : file handle is NULL");\r
-        ::Serialize(*this, obj, nType, nVersion);\r
-        return (*this);\r
-    }\r
-\r
-    template<typename T>\r
-    CAutoFile& operator>>(T& obj)\r
-    {\r
-        // Unserialize from this stream\r
-        if (!file)\r
-            throw std::ios_base::failure("CAutoFile::operator>> : file handle is NULL");\r
-        ::Unserialize(*this, obj, nType, nVersion);\r
-        return (*this);\r
-    }\r
-};\r
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Distributed under the MIT/X11 software license, see the accompanying
+// file license.txt or http://www.opensource.org/licenses/mit-license.php.
+
+#include <string>
+#include <vector>
+#include <map>
+#include <set>
+#include <boost/type_traits/is_fundamental.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/tuple/tuple_comparison.hpp>
+#include <boost/tuple/tuple_io.hpp>
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef __int64  int64;
+typedef unsigned __int64  uint64;
+#else
+typedef long long  int64;
+typedef unsigned long long  uint64;
+#endif
+#if defined(_MSC_VER) && _MSC_VER < 1300
+#define for  if (false) ; else for
+#endif
+class CScript;
+class CDataStream;
+class CAutoFile;
+static const unsigned int MAX_SIZE = 0x02000000;
+
+static const int VERSION = 32100;
+static const char* pszSubVer = "";
+static const bool VERSION_IS_BETA = true;
+
+
+
+
+
+
+/////////////////////////////////////////////////////////////////
+//
+// Templates for serializing to anything that looks like a stream,
+// i.e. anything that supports .read(char*, int) and .write(char*, int)
+//
+
+enum
+{
+    // primary actions
+    SER_NETWORK         = (1 << 0),
+    SER_DISK            = (1 << 1),
+    SER_GETHASH         = (1 << 2),
+
+    // modifiers
+    SER_SKIPSIG         = (1 << 16),
+    SER_BLOCKHEADERONLY = (1 << 17),
+};
+
+#define IMPLEMENT_SERIALIZE(statements)    \
+    unsigned int GetSerializeSize(int nType=0, int nVersion=VERSION) const  \
+    {                                           \
+        CSerActionGetSerializeSize ser_action;  \
+        const bool fGetSize = true;             \
+        const bool fWrite = false;              \
+        const bool fRead = false;               \
+        unsigned int nSerSize = 0;              \
+        ser_streamplaceholder s;                \
+        s.nType = nType;                        \
+        s.nVersion = nVersion;                  \
+        {statements}                            \
+        return nSerSize;                        \
+    }                                           \
+    template<typename Stream>                   \
+    void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const  \
+    {                                           \
+        CSerActionSerialize ser_action;         \
+        const bool fGetSize = false;            \
+        const bool fWrite = true;               \
+        const bool fRead = false;               \
+        unsigned int nSerSize = 0;              \
+        {statements}                            \
+    }                                           \
+    template<typename Stream>                   \
+    void Unserialize(Stream& s, int nType=0, int nVersion=VERSION)  \
+    {                                           \
+        CSerActionUnserialize ser_action;       \
+        const bool fGetSize = false;            \
+        const bool fWrite = false;              \
+        const bool fRead = true;                \
+        unsigned int nSerSize = 0;              \
+        {statements}                            \
+    }
+
+#define READWRITE(obj)      (nSerSize += ::SerReadWrite(s, (obj), nType, nVersion, ser_action))
+
+
+
+
+
+
+//
+// Basic types
+//
+#define WRITEDATA(s, obj)   s.write((char*)&(obj), sizeof(obj))
+#define READDATA(s, obj)    s.read((char*)&(obj), sizeof(obj))
+
+inline unsigned int GetSerializeSize(char a,           int, int=0) { return sizeof(a); }
+inline unsigned int GetSerializeSize(signed char a,    int, int=0) { return sizeof(a); }
+inline unsigned int GetSerializeSize(unsigned char a,  int, int=0) { return sizeof(a); }
+inline unsigned int GetSerializeSize(signed short a,   int, int=0) { return sizeof(a); }
+inline unsigned int GetSerializeSize(unsigned short a, int, int=0) { return sizeof(a); }
+inline unsigned int GetSerializeSize(signed int a,     int, int=0) { return sizeof(a); }
+inline unsigned int GetSerializeSize(unsigned int a,   int, int=0) { return sizeof(a); }
+inline unsigned int GetSerializeSize(signed long a,    int, int=0) { return sizeof(a); }
+inline unsigned int GetSerializeSize(unsigned long a,  int, int=0) { return sizeof(a); }
+inline unsigned int GetSerializeSize(int64 a,          int, int=0) { return sizeof(a); }
+inline unsigned int GetSerializeSize(uint64 a,         int, int=0) { return sizeof(a); }
+inline unsigned int GetSerializeSize(float a,          int, int=0) { return sizeof(a); }
+inline unsigned int GetSerializeSize(double a,         int, int=0) { return sizeof(a); }
+
+template<typename Stream> inline void Serialize(Stream& s, char a,           int, int=0) { WRITEDATA(s, a); }
+template<typename Stream> inline void Serialize(Stream& s, signed char a,    int, int=0) { WRITEDATA(s, a); }
+template<typename Stream> inline void Serialize(Stream& s, unsigned char a,  int, int=0) { WRITEDATA(s, a); }
+template<typename Stream> inline void Serialize(Stream& s, signed short a,   int, int=0) { WRITEDATA(s, a); }
+template<typename Stream> inline void Serialize(Stream& s, unsigned short a, int, int=0) { WRITEDATA(s, a); }
+template<typename Stream> inline void Serialize(Stream& s, signed int a,     int, int=0) { WRITEDATA(s, a); }
+template<typename Stream> inline void Serialize(Stream& s, unsigned int a,   int, int=0) { WRITEDATA(s, a); }
+template<typename Stream> inline void Serialize(Stream& s, signed long a,    int, int=0) { WRITEDATA(s, a); }
+template<typename Stream> inline void Serialize(Stream& s, unsigned long a,  int, int=0) { WRITEDATA(s, a); }
+template<typename Stream> inline void Serialize(Stream& s, int64 a,          int, int=0) { WRITEDATA(s, a); }
+template<typename Stream> inline void Serialize(Stream& s, uint64 a,         int, int=0) { WRITEDATA(s, a); }
+template<typename Stream> inline void Serialize(Stream& s, float a,          int, int=0) { WRITEDATA(s, a); }
+template<typename Stream> inline void Serialize(Stream& s, double a,         int, int=0) { WRITEDATA(s, a); }
+
+template<typename Stream> inline void Unserialize(Stream& s, char& a,           int, int=0) { READDATA(s, a); }
+template<typename Stream> inline void Unserialize(Stream& s, signed char& a,    int, int=0) { READDATA(s, a); }
+template<typename Stream> inline void Unserialize(Stream& s, unsigned char& a,  int, int=0) { READDATA(s, a); }
+template<typename Stream> inline void Unserialize(Stream& s, signed short& a,   int, int=0) { READDATA(s, a); }
+template<typename Stream> inline void Unserialize(Stream& s, unsigned short& a, int, int=0) { READDATA(s, a); }
+template<typename Stream> inline void Unserialize(Stream& s, signed int& a,     int, int=0) { READDATA(s, a); }
+template<typename Stream> inline void Unserialize(Stream& s, unsigned int& a,   int, int=0) { READDATA(s, a); }
+template<typename Stream> inline void Unserialize(Stream& s, signed long& a,    int, int=0) { READDATA(s, a); }
+template<typename Stream> inline void Unserialize(Stream& s, unsigned long& a,  int, int=0) { READDATA(s, a); }
+template<typename Stream> inline void Unserialize(Stream& s, int64& a,          int, int=0) { READDATA(s, a); }
+template<typename Stream> inline void Unserialize(Stream& s, uint64& a,         int, int=0) { READDATA(s, a); }
+template<typename Stream> inline void Unserialize(Stream& s, float& a,          int, int=0) { READDATA(s, a); }
+template<typename Stream> inline void Unserialize(Stream& s, double& a,         int, int=0) { READDATA(s, a); }
+
+inline unsigned int GetSerializeSize(bool a, int, int=0)                          { return sizeof(char); }
+template<typename Stream> inline void Serialize(Stream& s, bool a, int, int=0)    { char f=a; WRITEDATA(s, f); }
+template<typename Stream> inline void Unserialize(Stream& s, bool& a, int, int=0) { char f; READDATA(s, f); a=f; }
+
+
+
+
+
+
+//
+// Compact size
+//  size <  253        -- 1 byte
+//  size <= USHRT_MAX  -- 3 bytes  (253 + 2 bytes)
+//  size <= UINT_MAX   -- 5 bytes  (254 + 4 bytes)
+//  size >  UINT_MAX   -- 9 bytes  (255 + 8 bytes)
+//
+inline unsigned int GetSizeOfCompactSize(uint64 nSize)
+{
+    if (nSize < 253)             return sizeof(unsigned char);
+    else if (nSize <= USHRT_MAX) return sizeof(unsigned char) + sizeof(unsigned short);
+    else if (nSize <= UINT_MAX)  return sizeof(unsigned char) + sizeof(unsigned int);
+    else                         return sizeof(unsigned char) + sizeof(uint64);
+}
+
+template<typename Stream>
+void WriteCompactSize(Stream& os, uint64 nSize)
+{
+    if (nSize < 253)
+    {
+        unsigned char chSize = nSize;
+        WRITEDATA(os, chSize);
+    }
+    else if (nSize <= USHRT_MAX)
+    {
+        unsigned char chSize = 253;
+        unsigned short xSize = nSize;
+        WRITEDATA(os, chSize);
+        WRITEDATA(os, xSize);
+    }
+    else if (nSize <= UINT_MAX)
+    {
+        unsigned char chSize = 254;
+        unsigned int xSize = nSize;
+        WRITEDATA(os, chSize);
+        WRITEDATA(os, xSize);
+    }
+    else
+    {
+        unsigned char chSize = 255;
+        uint64 xSize = nSize;
+        WRITEDATA(os, chSize);
+        WRITEDATA(os, xSize);
+    }
+    return;
+}
+
+template<typename Stream>
+uint64 ReadCompactSize(Stream& is)
+{
+    unsigned char chSize;
+    READDATA(is, chSize);
+    uint64 nSizeRet = 0;
+    if (chSize < 253)
+    {
+        nSizeRet = chSize;
+    }
+    else if (chSize == 253)
+    {
+        unsigned short xSize;
+        READDATA(is, xSize);
+        nSizeRet = xSize;
+    }
+    else if (chSize == 254)
+    {
+        unsigned int xSize;
+        READDATA(is, xSize);
+        nSizeRet = xSize;
+    }
+    else
+    {
+        uint64 xSize;
+        READDATA(is, xSize);
+        nSizeRet = xSize;
+    }
+    if (nSizeRet > (uint64)MAX_SIZE)
+        throw std::ios_base::failure("ReadCompactSize() : size too large");
+    return nSizeRet;
+}
+
+
+
+//
+// Wrapper for serializing arrays and POD
+// There's a clever template way to make arrays serialize normally, but MSVC6 doesn't support it
+//
+#define FLATDATA(obj)   REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj)))
+class CFlatData
+{
+protected:
+    char* pbegin;
+    char* pend;
+public:
+    CFlatData(void* pbeginIn, void* pendIn) : pbegin((char*)pbeginIn), pend((char*)pendIn) { }
+    char* begin() { return pbegin; }
+    const char* begin() const { return pbegin; }
+    char* end() { return pend; }
+    const char* end() const { return pend; }
+
+    unsigned int GetSerializeSize(int, int=0) const
+    {
+        return pend - pbegin;
+    }
+
+    template<typename Stream>
+    void Serialize(Stream& s, int, int=0) const
+    {
+        s.write(pbegin, pend - pbegin);
+    }
+
+    template<typename Stream>
+    void Unserialize(Stream& s, int, int=0)
+    {
+        s.read(pbegin, pend - pbegin);
+    }
+};
+
+
+
+//
+// string stored as a fixed length field
+//
+template<std::size_t LEN>
+class CFixedFieldString
+{
+protected:
+    const string* pcstr;
+    string* pstr;
+public:
+    explicit CFixedFieldString(const string& str) : pcstr(&str), pstr(NULL) { }
+    explicit CFixedFieldString(string& str) : pcstr(&str), pstr(&str) { }
+
+    unsigned int GetSerializeSize(int, int=0) const
+    {
+        return LEN;
+    }
+
+    template<typename Stream>
+    void Serialize(Stream& s, int, int=0) const
+    {
+        char pszBuf[LEN];
+        strncpy(pszBuf, pcstr->c_str(), LEN);
+        s.write(pszBuf, LEN);
+    }
+
+    template<typename Stream>
+    void Unserialize(Stream& s, int, int=0)
+    {
+        if (pstr == NULL)
+            throw std::ios_base::failure("CFixedFieldString::Unserialize : trying to unserialize to const string");
+        char pszBuf[LEN+1];
+        s.read(pszBuf, LEN);
+        pszBuf[LEN] = '\0';
+        *pstr = pszBuf;
+    }
+};
+
+
+
+
+
+//
+// Forward declarations
+//
+
+// string
+template<typename C> unsigned int GetSerializeSize(const basic_string<C>& str, int, int=0);
+template<typename Stream, typename C> void Serialize(Stream& os, const basic_string<C>& str, int, int=0);
+template<typename Stream, typename C> void Unserialize(Stream& is, basic_string<C>& str, int, int=0);
+
+// vector
+template<typename T, typename A> unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&);
+template<typename T, typename A> unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&);
+template<typename T, typename A> inline unsigned int GetSerializeSize(const std::vector<T, A>& v, int nType, int nVersion=VERSION);
+template<typename Stream, typename T, typename A> void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&);
+template<typename Stream, typename T, typename A> void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&);
+template<typename Stream, typename T, typename A> inline void Serialize(Stream& os, const std::vector<T, A>& v, int nType, int nVersion=VERSION);
+template<typename Stream, typename T, typename A> void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&);
+template<typename Stream, typename T, typename A> void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&);
+template<typename Stream, typename T, typename A> inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersion=VERSION);
+
+// others derived from vector
+extern inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion=VERSION);
+template<typename Stream> void Serialize(Stream& os, const CScript& v, int nType, int nVersion=VERSION);
+template<typename Stream> void Unserialize(Stream& is, CScript& v, int nType, int nVersion=VERSION);
+
+// pair
+template<typename K, typename T> unsigned int GetSerializeSize(const std::pair<K, T>& item, int nType, int nVersion=VERSION);
+template<typename Stream, typename K, typename T> void Serialize(Stream& os, const std::pair<K, T>& item, int nType, int nVersion=VERSION);
+template<typename Stream, typename K, typename T> void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion=VERSION);
+
+// 3 tuple
+template<typename T0, typename T1, typename T2> unsigned int GetSerializeSize(const boost::tuple<T0, T1, T2>& item, int nType, int nVersion=VERSION);
+template<typename Stream, typename T0, typename T1, typename T2> void Serialize(Stream& os, const boost::tuple<T0, T1, T2>& item, int nType, int nVersion=VERSION);
+template<typename Stream, typename T0, typename T1, typename T2> void Unserialize(Stream& is, boost::tuple<T0, T1, T2>& item, int nType, int nVersion=VERSION);
+
+// 4 tuple
+template<typename T0, typename T1, typename T2, typename T3> unsigned int GetSerializeSize(const boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion=VERSION);
+template<typename Stream, typename T0, typename T1, typename T2, typename T3> void Serialize(Stream& os, const boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion=VERSION);
+template<typename Stream, typename T0, typename T1, typename T2, typename T3> void Unserialize(Stream& is, boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion=VERSION);
+
+// map
+template<typename K, typename T, typename Pred, typename A> unsigned int GetSerializeSize(const std::map<K, T, Pred, A>& m, int nType, int nVersion=VERSION);
+template<typename Stream, typename K, typename T, typename Pred, typename A> void Serialize(Stream& os, const std::map<K, T, Pred, A>& m, int nType, int nVersion=VERSION);
+template<typename Stream, typename K, typename T, typename Pred, typename A> void Unserialize(Stream& is, std::map<K, T, Pred, A>& m, int nType, int nVersion=VERSION);
+
+// set
+template<typename K, typename Pred, typename A> unsigned int GetSerializeSize(const std::set<K, Pred, A>& m, int nType, int nVersion=VERSION);
+template<typename Stream, typename K, typename Pred, typename A> void Serialize(Stream& os, const std::set<K, Pred, A>& m, int nType, int nVersion=VERSION);
+template<typename Stream, typename K, typename Pred, typename A> void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion=VERSION);
+
+
+
+
+
+//
+// If none of the specialized versions above matched, default to calling member function.
+// "int nType" is changed to "long nType" to keep from getting an ambiguous overload error.
+// The compiler will only cast int to long if none of the other templates matched.
+// Thanks to Boost serialization for this idea.
+//
+template<typename T>
+inline unsigned int GetSerializeSize(const T& a, long nType, int nVersion=VERSION)
+{
+    return a.GetSerializeSize((int)nType, nVersion);
+}
+
+template<typename Stream, typename T>
+inline void Serialize(Stream& os, const T& a, long nType, int nVersion=VERSION)
+{
+    a.Serialize(os, (int)nType, nVersion);
+}
+
+template<typename Stream, typename T>
+inline void Unserialize(Stream& is, T& a, long nType, int nVersion=VERSION)
+{
+    a.Unserialize(is, (int)nType, nVersion);
+}
+
+
+
+
+
+//
+// string
+//
+template<typename C>
+unsigned int GetSerializeSize(const basic_string<C>& str, int, int)
+{
+    return GetSizeOfCompactSize(str.size()) + str.size() * sizeof(str[0]);
+}
+
+template<typename Stream, typename C>
+void Serialize(Stream& os, const basic_string<C>& str, int, int)
+{
+    WriteCompactSize(os, str.size());
+    if (!str.empty())
+        os.write((char*)&str[0], str.size() * sizeof(str[0]));
+}
+
+template<typename Stream, typename C>
+void Unserialize(Stream& is, basic_string<C>& str, int, int)
+{
+    unsigned int nSize = ReadCompactSize(is);
+    str.resize(nSize);
+    if (nSize != 0)
+        is.read((char*)&str[0], nSize * sizeof(str[0]));
+}
+
+
+
+//
+// vector
+//
+template<typename T, typename A>
+unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&)
+{
+    return (GetSizeOfCompactSize(v.size()) + v.size() * sizeof(T));
+}
+
+template<typename T, typename A>
+unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&)
+{
+    unsigned int nSize = GetSizeOfCompactSize(v.size());
+    for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi)
+        nSize += GetSerializeSize((*vi), nType, nVersion);
+    return nSize;
+}
+
+template<typename T, typename A>
+inline unsigned int GetSerializeSize(const std::vector<T, A>& v, int nType, int nVersion)
+{
+    return GetSerializeSize_impl(v, nType, nVersion, boost::is_fundamental<T>());
+}
+
+
+template<typename Stream, typename T, typename A>
+void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&)
+{
+    WriteCompactSize(os, v.size());
+    if (!v.empty())
+        os.write((char*)&v[0], v.size() * sizeof(T));
+}
+
+template<typename Stream, typename T, typename A>
+void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&)
+{
+    WriteCompactSize(os, v.size());
+    for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi)
+        ::Serialize(os, (*vi), nType, nVersion);
+}
+
+template<typename Stream, typename T, typename A>
+inline void Serialize(Stream& os, const std::vector<T, A>& v, int nType, int nVersion)
+{
+    Serialize_impl(os, v, nType, nVersion, boost::is_fundamental<T>());
+}
+
+
+template<typename Stream, typename T, typename A>
+void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&)
+{
+    //unsigned int nSize = ReadCompactSize(is);
+    //v.resize(nSize);
+    //is.read((char*)&v[0], nSize * sizeof(T));
+
+    // Limit size per read so bogus size value won't cause out of memory
+    v.clear();
+    unsigned int nSize = ReadCompactSize(is);
+    unsigned int i = 0;
+    while (i < nSize)
+    {
+        unsigned int blk = min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
+        v.resize(i + blk);
+        is.read((char*)&v[i], blk * sizeof(T));
+        i += blk;
+    }
+}
+
+template<typename Stream, typename T, typename A>
+void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&)
+{
+    //unsigned int nSize = ReadCompactSize(is);
+    //v.resize(nSize);
+    //for (std::vector<T, A>::iterator vi = v.begin(); vi != v.end(); ++vi)
+    //    Unserialize(is, (*vi), nType, nVersion);
+
+    v.clear();
+    unsigned int nSize = ReadCompactSize(is);
+    unsigned int i = 0;
+    unsigned int nMid = 0;
+    while (nMid < nSize)
+    {
+        nMid += 5000000 / sizeof(T);
+        if (nMid > nSize)
+            nMid = nSize;
+        v.resize(nMid);
+        for (; i < nMid; i++)
+            Unserialize(is, v[i], nType, nVersion);
+    }
+}
+
+template<typename Stream, typename T, typename A>
+inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersion)
+{
+    Unserialize_impl(is, v, nType, nVersion, boost::is_fundamental<T>());
+}
+
+
+
+//
+// others derived from vector
+//
+inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion)
+{
+    return GetSerializeSize((const vector<unsigned char>&)v, nType, nVersion);
+}
+
+template<typename Stream>
+void Serialize(Stream& os, const CScript& v, int nType, int nVersion)
+{
+    Serialize(os, (const vector<unsigned char>&)v, nType, nVersion);
+}
+
+template<typename Stream>
+void Unserialize(Stream& is, CScript& v, int nType, int nVersion)
+{
+    Unserialize(is, (vector<unsigned char>&)v, nType, nVersion);
+}
+
+
+
+//
+// pair
+//
+template<typename K, typename T>
+unsigned int GetSerializeSize(const std::pair<K, T>& item, int nType, int nVersion)
+{
+    return GetSerializeSize(item.first, nType, nVersion) + GetSerializeSize(item.second, nType, nVersion);
+}
+
+template<typename Stream, typename K, typename T>
+void Serialize(Stream& os, const std::pair<K, T>& item, int nType, int nVersion)
+{
+    Serialize(os, item.first, nType, nVersion);
+    Serialize(os, item.second, nType, nVersion);
+}
+
+template<typename Stream, typename K, typename T>
+void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion)
+{
+    Unserialize(is, item.first, nType, nVersion);
+    Unserialize(is, item.second, nType, nVersion);
+}
+
+
+
+//
+// 3 tuple
+//
+template<typename T0, typename T1, typename T2>
+unsigned int GetSerializeSize(const boost::tuple<T0, T1, T2>& item, int nType, int nVersion)
+{
+    unsigned int nSize = 0;
+    nSize += GetSerializeSize(get<0>(item), nType, nVersion);
+    nSize += GetSerializeSize(get<1>(item), nType, nVersion);
+    nSize += GetSerializeSize(get<2>(item), nType, nVersion);
+    return nSize;
+}
+
+template<typename Stream, typename T0, typename T1, typename T2>
+void Serialize(Stream& os, const boost::tuple<T0, T1, T2>& item, int nType, int nVersion)
+{
+    Serialize(os, get<0>(item), nType, nVersion);
+    Serialize(os, get<1>(item), nType, nVersion);
+    Serialize(os, get<2>(item), nType, nVersion);
+}
+
+template<typename Stream, typename T0, typename T1, typename T2>
+void Unserialize(Stream& is, boost::tuple<T0, T1, T2>& item, int nType, int nVersion)
+{
+    Unserialize(is, get<0>(item), nType, nVersion);
+    Unserialize(is, get<1>(item), nType, nVersion);
+    Unserialize(is, get<2>(item), nType, nVersion);
+}
+
+
+
+//
+// 4 tuple
+//
+template<typename T0, typename T1, typename T2, typename T3>
+unsigned int GetSerializeSize(const boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion)
+{
+    unsigned int nSize = 0;
+    nSize += GetSerializeSize(get<0>(item), nType, nVersion);
+    nSize += GetSerializeSize(get<1>(item), nType, nVersion);
+    nSize += GetSerializeSize(get<2>(item), nType, nVersion);
+    nSize += GetSerializeSize(get<3>(item), nType, nVersion);
+    return nSize;
+}
+
+template<typename Stream, typename T0, typename T1, typename T2, typename T3>
+void Serialize(Stream& os, const boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion)
+{
+    Serialize(os, get<0>(item), nType, nVersion);
+    Serialize(os, get<1>(item), nType, nVersion);
+    Serialize(os, get<2>(item), nType, nVersion);
+    Serialize(os, get<3>(item), nType, nVersion);
+}
+
+template<typename Stream, typename T0, typename T1, typename T2, typename T3>
+void Unserialize(Stream& is, boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion)
+{
+    Unserialize(is, get<0>(item), nType, nVersion);
+    Unserialize(is, get<1>(item), nType, nVersion);
+    Unserialize(is, get<2>(item), nType, nVersion);
+    Unserialize(is, get<3>(item), nType, nVersion);
+}
+
+
+
+//
+// map
+//
+template<typename K, typename T, typename Pred, typename A>
+unsigned int GetSerializeSize(const std::map<K, T, Pred, A>& m, int nType, int nVersion)
+{
+    unsigned int nSize = GetSizeOfCompactSize(m.size());
+    for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi)
+        nSize += GetSerializeSize((*mi), nType, nVersion);
+    return nSize;
+}
+
+template<typename Stream, typename K, typename T, typename Pred, typename A>
+void Serialize(Stream& os, const std::map<K, T, Pred, A>& m, int nType, int nVersion)
+{
+    WriteCompactSize(os, m.size());
+    for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi)
+        Serialize(os, (*mi), nType, nVersion);
+}
+
+template<typename Stream, typename K, typename T, typename Pred, typename A>
+void Unserialize(Stream& is, std::map<K, T, Pred, A>& m, int nType, int nVersion)
+{
+    m.clear();
+    unsigned int nSize = ReadCompactSize(is);
+    typename std::map<K, T, Pred, A>::iterator mi = m.begin();
+    for (unsigned int i = 0; i < nSize; i++)
+    {
+        pair<K, T> item;
+        Unserialize(is, item, nType, nVersion);
+        mi = m.insert(mi, item);
+    }
+}
+
+
+
+//
+// set
+//
+template<typename K, typename Pred, typename A>
+unsigned int GetSerializeSize(const std::set<K, Pred, A>& m, int nType, int nVersion)
+{
+    unsigned int nSize = GetSizeOfCompactSize(m.size());
+    for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it)
+        nSize += GetSerializeSize((*it), nType, nVersion);
+    return nSize;
+}
+
+template<typename Stream, typename K, typename Pred, typename A>
+void Serialize(Stream& os, const std::set<K, Pred, A>& m, int nType, int nVersion)
+{
+    WriteCompactSize(os, m.size());
+    for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it)
+        Serialize(os, (*it), nType, nVersion);
+}
+
+template<typename Stream, typename K, typename Pred, typename A>
+void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion)
+{
+    m.clear();
+    unsigned int nSize = ReadCompactSize(is);
+    typename std::set<K, Pred, A>::iterator it = m.begin();
+    for (unsigned int i = 0; i < nSize; i++)
+    {
+        K key;
+        Unserialize(is, key, nType, nVersion);
+        it = m.insert(it, key);
+    }
+}
+
+
+
+//
+// Support for IMPLEMENT_SERIALIZE and READWRITE macro
+//
+class CSerActionGetSerializeSize { };
+class CSerActionSerialize { };
+class CSerActionUnserialize { };
+
+template<typename Stream, typename T>
+inline unsigned int SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionGetSerializeSize ser_action)
+{
+    return ::GetSerializeSize(obj, nType, nVersion);
+}
+
+template<typename Stream, typename T>
+inline unsigned int SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionSerialize ser_action)
+{
+    ::Serialize(s, obj, nType, nVersion);
+    return 0;
+}
+
+template<typename Stream, typename T>
+inline unsigned int SerReadWrite(Stream& s, T& obj, int nType, int nVersion, CSerActionUnserialize ser_action)
+{
+    ::Unserialize(s, obj, nType, nVersion);
+    return 0;
+}
+
+struct ser_streamplaceholder
+{
+    int nType;
+    int nVersion;
+};
+
+
+
+
+
+
+
+
+
+//
+// Allocator that clears its contents before deletion
+//
+template<typename T>
+struct secure_allocator : public std::allocator<T>
+{
+    // MSVC8 default copy constructor is broken
+    typedef std::allocator<T> base;
+    typedef typename base::size_type size_type;
+    typedef typename base::difference_type  difference_type;
+    typedef typename base::pointer pointer;
+    typedef typename base::const_pointer const_pointer;
+    typedef typename base::reference reference;
+    typedef typename base::const_reference const_reference;
+    typedef typename base::value_type value_type;
+    secure_allocator() throw() {}
+    secure_allocator(const secure_allocator& a) throw() : base(a) {}
+    template <typename U>
+    secure_allocator(const secure_allocator<U>& a) throw() : base(a) {}
+    ~secure_allocator() throw() {}
+    template<typename _Other> struct rebind
+    { typedef secure_allocator<_Other> other; };
+
+    void deallocate(T* p, std::size_t n)
+    {
+        if (p != NULL)
+            memset(p, 0, sizeof(T) * n);
+        allocator<T>::deallocate(p, n);
+    }
+};
+
+
+
+//
+// Double ended buffer combining vector and stream-like interfaces.
+// >> and << read and write unformatted data using the above serialization templates.
+// Fills with data in linear time; some stringstream implementations take N^2 time.
+//
+class CDataStream
+{
+protected:
+    typedef vector<char, secure_allocator<char> > vector_type;
+    vector_type vch;
+    unsigned int nReadPos;
+    short state;
+    short exceptmask;
+public:
+    int nType;
+    int nVersion;
+
+    typedef vector_type::allocator_type   allocator_type;
+    typedef vector_type::size_type        size_type;
+    typedef vector_type::difference_type  difference_type;
+    typedef vector_type::reference        reference;
+    typedef vector_type::const_reference  const_reference;
+    typedef vector_type::value_type       value_type;
+    typedef vector_type::iterator         iterator;
+    typedef vector_type::const_iterator   const_iterator;
+    typedef vector_type::reverse_iterator reverse_iterator;
+
+    explicit CDataStream(int nTypeIn=SER_NETWORK, int nVersionIn=VERSION)
+    {
+        Init(nTypeIn, nVersionIn);
+    }
+
+    CDataStream(const_iterator pbegin, const_iterator pend, int nTypeIn=SER_NETWORK, int nVersionIn=VERSION) : vch(pbegin, pend)
+    {
+        Init(nTypeIn, nVersionIn);
+    }
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1300
+    CDataStream(const char* pbegin, const char* pend, int nTypeIn=SER_NETWORK, int nVersionIn=VERSION) : vch(pbegin, pend)
+    {
+        Init(nTypeIn, nVersionIn);
+    }
+#endif
+
+    CDataStream(const vector_type& vchIn, int nTypeIn=SER_NETWORK, int nVersionIn=VERSION) : vch(vchIn.begin(), vchIn.end())
+    {
+        Init(nTypeIn, nVersionIn);
+    }
+
+    CDataStream(const vector<char>& vchIn, int nTypeIn=SER_NETWORK, int nVersionIn=VERSION) : vch(vchIn.begin(), vchIn.end())
+    {
+        Init(nTypeIn, nVersionIn);
+    }
+
+    CDataStream(const vector<unsigned char>& vchIn, int nTypeIn=SER_NETWORK, int nVersionIn=VERSION) : vch((char*)&vchIn.begin()[0], (char*)&vchIn.end()[0])
+    {
+        Init(nTypeIn, nVersionIn);
+    }
+
+    void Init(int nTypeIn=SER_NETWORK, int nVersionIn=VERSION)
+    {
+        nReadPos = 0;
+        nType = nTypeIn;
+        nVersion = nVersionIn;
+        state = 0;
+        exceptmask = ios::badbit | ios::failbit;
+    }
+
+    CDataStream& operator+=(const CDataStream& b)
+    {
+        vch.insert(vch.end(), b.begin(), b.end());
+        return *this;
+    }
+
+    friend CDataStream operator+(const CDataStream& a, const CDataStream& b)
+    {
+        CDataStream ret = a;
+        ret += b;
+        return (ret);
+    }
+
+    string str() const
+    {
+        return (string(begin(), end()));
+    }
+
+
+    //
+    // Vector subset
+    //
+    const_iterator begin() const                     { return vch.begin() + nReadPos; }
+    iterator begin()                                 { return vch.begin() + nReadPos; }
+    const_iterator end() const                       { return vch.end(); }
+    iterator end()                                   { return vch.end(); }
+    size_type size() const                           { return vch.size() - nReadPos; }
+    bool empty() const                               { return vch.size() == nReadPos; }
+    void resize(size_type n, value_type c=0)         { vch.resize(n + nReadPos, c); }
+    void reserve(size_type n)                        { vch.reserve(n + nReadPos); }
+    const_reference operator[](size_type pos) const  { return vch[pos + nReadPos]; }
+    reference operator[](size_type pos)              { return vch[pos + nReadPos]; }
+    void clear()                                     { vch.clear(); nReadPos = 0; }
+    iterator insert(iterator it, const char& x=char()) { return vch.insert(it, x); }
+    void insert(iterator it, size_type n, const char& x) { vch.insert(it, n, x); }
+
+    void insert(iterator it, const_iterator first, const_iterator last)
+    {
+        if (it == vch.begin() + nReadPos && last - first <= nReadPos)
+        {
+            // special case for inserting at the front when there's room
+            nReadPos -= (last - first);
+            memcpy(&vch[nReadPos], &first[0], last - first);
+        }
+        else
+            vch.insert(it, first, last);
+    }
+
+    void insert(iterator it, vector<char>::const_iterator first, vector<char>::const_iterator last)
+    {
+        if (it == vch.begin() + nReadPos && last - first <= nReadPos)
+        {
+            // special case for inserting at the front when there's room
+            nReadPos -= (last - first);
+            memcpy(&vch[nReadPos], &first[0], last - first);
+        }
+        else
+            vch.insert(it, first, last);
+    }
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1300
+    void insert(iterator it, const char* first, const char* last)
+    {
+        if (it == vch.begin() + nReadPos && last - first <= nReadPos)
+        {
+            // special case for inserting at the front when there's room
+            nReadPos -= (last - first);
+            memcpy(&vch[nReadPos], &first[0], last - first);
+        }
+        else
+            vch.insert(it, first, last);
+    }
+#endif
+
+    iterator erase(iterator it)
+    {
+        if (it == vch.begin() + nReadPos)
+        {
+            // special case for erasing from the front
+            if (++nReadPos >= vch.size())
+            {
+                // whenever we reach the end, we take the opportunity to clear the buffer
+                nReadPos = 0;
+                return vch.erase(vch.begin(), vch.end());
+            }
+            return vch.begin() + nReadPos;
+        }
+        else
+            return vch.erase(it);
+    }
+
+    iterator erase(iterator first, iterator last)
+    {
+        if (first == vch.begin() + nReadPos)
+        {
+            // special case for erasing from the front
+            if (last == vch.end())
+            {
+                nReadPos = 0;
+                return vch.erase(vch.begin(), vch.end());
+            }
+            else
+            {
+                nReadPos = (last - vch.begin());
+                return last;
+            }
+        }
+        else
+            return vch.erase(first, last);
+    }
+
+    inline void Compact()
+    {
+        vch.erase(vch.begin(), vch.begin() + nReadPos);
+        nReadPos = 0;
+    }
+
+    bool Rewind(size_type n)
+    {
+        // Rewind by n characters if the buffer hasn't been compacted yet
+        if (n > nReadPos)
+            return false;
+        nReadPos -= n;
+        return true;
+    }
+
+
+    //
+    // Stream subset
+    //
+    void setstate(short bits, const char* psz)
+    {
+        state |= bits;
+        if (state & exceptmask)
+            throw std::ios_base::failure(psz);
+    }
+
+    bool eof() const             { return size() == 0; }
+    bool fail() const            { return state & (ios::badbit | ios::failbit); }
+    bool good() const            { return !eof() && (state == 0); }
+    void clear(short n)          { state = n; }  // name conflict with vector clear()
+    short exceptions()           { return exceptmask; }
+    short exceptions(short mask) { short prev = exceptmask; exceptmask = mask; setstate(0, "CDataStream"); return prev; }
+    CDataStream* rdbuf()         { return this; }
+    int in_avail()               { return size(); }
+
+    void SetType(int n)          { nType = n; }
+    int GetType()                { return nType; }
+    void SetVersion(int n)       { nVersion = n; }
+    int GetVersion()             { return nVersion; }
+    void ReadVersion()           { *this >> nVersion; }
+    void WriteVersion()          { *this << nVersion; }
+
+    CDataStream& read(char* pch, int nSize)
+    {
+        // Read from the beginning of the buffer
+        assert(nSize >= 0);
+        unsigned int nReadPosNext = nReadPos + nSize;
+        if (nReadPosNext >= vch.size())
+        {
+            if (nReadPosNext > vch.size())
+            {
+                setstate(ios::failbit, "CDataStream::read() : end of data");
+                memset(pch, 0, nSize);
+                nSize = vch.size() - nReadPos;
+            }
+            memcpy(pch, &vch[nReadPos], nSize);
+            nReadPos = 0;
+            vch.clear();
+            return (*this);
+        }
+        memcpy(pch, &vch[nReadPos], nSize);
+        nReadPos = nReadPosNext;
+        return (*this);
+    }
+
+    CDataStream& ignore(int nSize)
+    {
+        // Ignore from the beginning of the buffer
+        assert(nSize >= 0);
+        unsigned int nReadPosNext = nReadPos + nSize;
+        if (nReadPosNext >= vch.size())
+        {
+            if (nReadPosNext > vch.size())
+            {
+                setstate(ios::failbit, "CDataStream::ignore() : end of data");
+                nSize = vch.size() - nReadPos;
+            }
+            nReadPos = 0;
+            vch.clear();
+            return (*this);
+        }
+        nReadPos = nReadPosNext;
+        return (*this);
+    }
+
+    CDataStream& write(const char* pch, int nSize)
+    {
+        // Write to the end of the buffer
+        assert(nSize >= 0);
+        vch.insert(vch.end(), pch, pch + nSize);
+        return (*this);
+    }
+
+    template<typename Stream>
+    void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const
+    {
+        // Special case: stream << stream concatenates like stream += stream
+        if (!vch.empty())
+            s.write((char*)&vch[0], vch.size() * sizeof(vch[0]));
+    }
+
+    template<typename T>
+    unsigned int GetSerializeSize(const T& obj)
+    {
+        // Tells the size of the object if serialized to this stream
+        return ::GetSerializeSize(obj, nType, nVersion);
+    }
+
+    template<typename T>
+    CDataStream& operator<<(const T& obj)
+    {
+        // Serialize to this stream
+        ::Serialize(*this, obj, nType, nVersion);
+        return (*this);
+    }
+
+    template<typename T>
+    CDataStream& operator>>(T& obj)
+    {
+        // Unserialize from this stream
+        ::Unserialize(*this, obj, nType, nVersion);
+        return (*this);
+    }
+};
+
+#ifdef TESTCDATASTREAM
+// VC6sp6
+// CDataStream:
+// n=1000       0 seconds
+// n=2000       0 seconds
+// n=4000       0 seconds
+// n=8000       0 seconds
+// n=16000      0 seconds
+// n=32000      0 seconds
+// n=64000      1 seconds
+// n=128000     1 seconds
+// n=256000     2 seconds
+// n=512000     4 seconds
+// n=1024000    8 seconds
+// n=2048000    16 seconds
+// n=4096000    32 seconds
+// stringstream:
+// n=1000       1 seconds
+// n=2000       1 seconds
+// n=4000       13 seconds
+// n=8000       87 seconds
+// n=16000      400 seconds
+// n=32000      1660 seconds
+// n=64000      6749 seconds
+// n=128000     27241 seconds
+// n=256000     109804 seconds
+#include <iostream>
+int main(int argc, char *argv[])
+{
+    vector<unsigned char> vch(0xcc, 250);
+    printf("CDataStream:\n");
+    for (int n = 1000; n <= 4500000; n *= 2)
+    {
+        CDataStream ss;
+        time_t nStart = time(NULL);
+        for (int i = 0; i < n; i++)
+            ss.write((char*)&vch[0], vch.size());
+        printf("n=%-10d %d seconds\n", n, time(NULL) - nStart);
+    }
+    printf("stringstream:\n");
+    for (int n = 1000; n <= 4500000; n *= 2)
+    {
+        stringstream ss;
+        time_t nStart = time(NULL);
+        for (int i = 0; i < n; i++)
+            ss.write((char*)&vch[0], vch.size());
+        printf("n=%-10d %d seconds\n", n, time(NULL) - nStart);
+    }
+}
+#endif
+
+
+
+
+
+
+
+
+
+
+//
+// Automatic closing wrapper for FILE*
+//  - Will automatically close the file when it goes out of scope if not null.
+//  - If you're returning the file pointer, return file.release().
+//  - If you need to close the file early, use file.fclose() instead of fclose(file).
+//
+class CAutoFile
+{
+protected:
+    FILE* file;
+    short state;
+    short exceptmask;
+public:
+    int nType;
+    int nVersion;
+
+    typedef FILE element_type;
+
+    CAutoFile(FILE* filenew=NULL, int nTypeIn=SER_DISK, int nVersionIn=VERSION)
+    {
+        file = filenew;
+        nType = nTypeIn;
+        nVersion = nVersionIn;
+        state = 0;
+        exceptmask = ios::badbit | ios::failbit;
+    }
+
+    ~CAutoFile()
+    {
+        fclose();
+    }
+
+    void fclose()
+    {
+        if (file != NULL && file != stdin && file != stdout && file != stderr)
+            ::fclose(file);
+        file = NULL;
+    }
+
+    FILE* release()             { FILE* ret = file; file = NULL; return ret; }
+    operator FILE*()            { return file; }
+    FILE* operator->()          { return file; }
+    FILE& operator*()           { return *file; }
+    FILE** operator&()          { return &file; }
+    FILE* operator=(FILE* pnew) { return file = pnew; }
+    bool operator!()            { return (file == NULL); }
+
+
+    //
+    // Stream subset
+    //
+    void setstate(short bits, const char* psz)
+    {
+        state |= bits;
+        if (state & exceptmask)
+            throw std::ios_base::failure(psz);
+    }
+
+    bool fail() const            { return state & (ios::badbit | ios::failbit); }
+    bool good() const            { return state == 0; }
+    void clear(short n = 0)      { state = n; }
+    short exceptions()           { return exceptmask; }
+    short exceptions(short mask) { short prev = exceptmask; exceptmask = mask; setstate(0, "CAutoFile"); return prev; }
+
+    void SetType(int n)          { nType = n; }
+    int GetType()                { return nType; }
+    void SetVersion(int n)       { nVersion = n; }
+    int GetVersion()             { return nVersion; }
+    void ReadVersion()           { *this >> nVersion; }
+    void WriteVersion()          { *this << nVersion; }
+
+    CAutoFile& read(char* pch, int nSize)
+    {
+        if (!file)
+            throw std::ios_base::failure("CAutoFile::read : file handle is NULL");
+        if (fread(pch, 1, nSize, file) != nSize)
+            setstate(ios::failbit, feof(file) ? "CAutoFile::read : end of file" : "CAutoFile::read : fread failed");
+        return (*this);
+    }
+
+    CAutoFile& write(const char* pch, int nSize)
+    {
+        if (!file)
+            throw std::ios_base::failure("CAutoFile::write : file handle is NULL");
+        if (fwrite(pch, 1, nSize, file) != nSize)
+            setstate(ios::failbit, "CAutoFile::write : write failed");
+        return (*this);
+    }
+
+    template<typename T>
+    unsigned int GetSerializeSize(const T& obj)
+    {
+        // Tells the size of the object if serialized to this stream
+        return ::GetSerializeSize(obj, nType, nVersion);
+    }
+
+    template<typename T>
+    CAutoFile& operator<<(const T& obj)
+    {
+        // Serialize to this stream
+        if (!file)
+            throw std::ios_base::failure("CAutoFile::operator<< : file handle is NULL");
+        ::Serialize(*this, obj, nType, nVersion);
+        return (*this);
+    }
+
+    template<typename T>
+    CAutoFile& operator>>(T& obj)
+    {
+        // Unserialize from this stream
+        if (!file)
+            throw std::ios_base::failure("CAutoFile::operator>> : file handle is NULL");
+        ::Unserialize(*this, obj, nType, nVersion);
+        return (*this);
+    }
+};