PPCoin: pchMessageStart switch
[novacoin.git] / src / protocol.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #include "protocol.h"
7 #include "util.h"
8 #include "netbase.h"
9
10 #ifndef WIN32
11 # include <arpa/inet.h>
12 #endif
13
14 // The message start string is designed to be unlikely to occur in normal data.
15 // The characters are rarely used upper ascii, not valid as UTF-8, and produce
16 // a large 4-byte int at any alignment.
17
18 // Public testnet message start
19 // unsigned char pchMessageStartTestBitcoin[4] = { 0x9b, 0xa1, 0xb2, 0xb6 };
20 static unsigned char pchMessageStartTestOld[4] = { 0xdb, 0xe1, 0xf2, 0xf6 };
21 static unsigned char pchMessageStartTestNew[4] = { 0xcb, 0xf2, 0xc0, 0xef };
22 static unsigned int nMessageStartTestSwitchTime = 1346200000;
23
24 // PPCoin message start (switch from Bitcoin's in v0.2)
25 static unsigned char pchMessageStartBitcoin[4] = { 0xf9, 0xbe, 0xb4, 0xd9 };
26 static unsigned char pchMessageStartPPCoin[4] = { 0xe6, 0xe8, 0xe9, 0xe5 };
27 static unsigned int nMessageStartSwitchTime = 1347300000;
28
29 void GetMessageStart(unsigned char pchMessageStart[], bool fPersistent)
30 {
31     if (fTestNet)
32         memcpy(pchMessageStart, (fPersistent || GetAdjustedTime() > nMessageStartTestSwitchTime)? pchMessageStartTestNew : pchMessageStartTestOld, sizeof(pchMessageStartTestNew));
33     else
34         memcpy(pchMessageStart, (fPersistent || GetAdjustedTime() > nMessageStartSwitchTime)? pchMessageStartPPCoin : pchMessageStartBitcoin, sizeof(pchMessageStartPPCoin));
35 }
36
37 static const char* ppszTypeName[] =
38 {
39     "ERROR",
40     "tx",
41     "block",
42 };
43
44 CMessageHeader::CMessageHeader()
45 {
46     GetMessageStart(pchMessageStart);
47     memset(pchCommand, 0, sizeof(pchCommand));
48     pchCommand[1] = 1;
49     nMessageSize = -1;
50     nChecksum = 0;
51 }
52
53 CMessageHeader::CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn)
54 {
55     GetMessageStart(pchMessageStart);
56     strncpy(pchCommand, pszCommand, COMMAND_SIZE);
57     nMessageSize = nMessageSizeIn;
58     nChecksum = 0;
59 }
60
61 std::string CMessageHeader::GetCommand() const
62 {
63     if (pchCommand[COMMAND_SIZE-1] == 0)
64         return std::string(pchCommand, pchCommand + strlen(pchCommand));
65     else
66         return std::string(pchCommand, pchCommand + COMMAND_SIZE);
67 }
68
69 bool CMessageHeader::IsValid() const
70 {
71     // Check start string
72     unsigned char pchMessageStartProtocol[4];
73     GetMessageStart(pchMessageStartProtocol);
74     if (memcmp(pchMessageStart, pchMessageStartProtocol, sizeof(pchMessageStart)) != 0)
75         return false;
76
77     // Check the command string for errors
78     for (const char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; p1++)
79     {
80         if (*p1 == 0)
81         {
82             // Must be all zeros after the first zero
83             for (; p1 < pchCommand + COMMAND_SIZE; p1++)
84                 if (*p1 != 0)
85                     return false;
86         }
87         else if (*p1 < ' ' || *p1 > 0x7E)
88             return false;
89     }
90
91     // Message size
92     if (nMessageSize > MAX_SIZE)
93     {
94         printf("CMessageHeader::IsValid() : (%s, %u bytes) nMessageSize > MAX_SIZE\n", GetCommand().c_str(), nMessageSize);
95         return false;
96     }
97
98     return true;
99 }
100
101
102
103 CAddress::CAddress() : CService()
104 {
105     Init();
106 }
107
108 CAddress::CAddress(CService ipIn, uint64 nServicesIn) : CService(ipIn)
109 {
110     Init();
111     nServices = nServicesIn;
112 }
113
114 void CAddress::Init()
115 {
116     nServices = NODE_NETWORK;
117     nTime = 100000000;
118     nLastTry = 0;
119 }
120
121 CInv::CInv()
122 {
123     type = 0;
124     hash = 0;
125 }
126
127 CInv::CInv(int typeIn, const uint256& hashIn)
128 {
129     type = typeIn;
130     hash = hashIn;
131 }
132
133 CInv::CInv(const std::string& strType, const uint256& hashIn)
134 {
135     unsigned int i;
136     for (i = 1; i < ARRAYLEN(ppszTypeName); i++)
137     {
138         if (strType == ppszTypeName[i])
139         {
140             type = i;
141             break;
142         }
143     }
144     if (i == ARRAYLEN(ppszTypeName))
145         throw std::out_of_range(strprintf("CInv::CInv(string, uint256) : unknown type '%s'", strType.c_str()));
146     hash = hashIn;
147 }
148
149 bool operator<(const CInv& a, const CInv& b)
150 {
151     return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
152 }
153
154 bool CInv::IsKnownType() const
155 {
156     return (type >= 1 && type < (int)ARRAYLEN(ppszTypeName));
157 }
158
159 const char* CInv::GetCommand() const
160 {
161     if (!IsKnownType())
162         throw std::out_of_range(strprintf("CInv::GetCommand() : type=%d unknown type", type));
163     return ppszTypeName[type];
164 }
165
166 std::string CInv::ToString() const
167 {
168     return strprintf("%s %s", GetCommand(), hash.ToString().substr(0,20).c_str());
169 }
170
171 void CInv::print() const
172 {
173     printf("CInv(%s)\n", ToString().c_str());
174 }
175