]> Git Repo - VerusCoin.git/blame - base58.h
more addr message error checking
[VerusCoin.git] / base58.h
CommitLineData
4405b78d 1// Copyright (c) 2009 Satoshi Nakamoto\r
2// Distributed under the MIT/X11 software license, see the accompanying\r
3// file license.txt or http://www.opensource.org/licenses/mit-license.php.\r
4\r
5\r
6//\r
7// Why base-58 instead of standard base-64 encoding?\r
8// - Don't want 0OIl characters that look the same in some fonts and\r
9// could be used to create visually identical looking account numbers.\r
10// - A string with non-alphanumeric characters is not as easily accepted as an account number.\r
11// - E-mail usually won't line-break if there's no punctuation to break at.\r
12// - Doubleclicking selects the whole number as one word if it's all alphanumeric.\r
13//\r
14\r
15\r
16static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";\r
17\r
18\r
19inline string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)\r
20{\r
21 CAutoBN_CTX pctx;\r
22 CBigNum bn58 = 58;\r
23 CBigNum bn0 = 0;\r
24\r
25 // Convert big endian data to little endian\r
26 // Extra zero at the end make sure bignum will interpret as a positive number\r
27 vector<unsigned char> vchTmp(pend-pbegin+1, 0);\r
28 reverse_copy(pbegin, pend, vchTmp.begin());\r
29\r
30 // Convert little endian data to bignum\r
31 CBigNum bn;\r
32 bn.setvch(vchTmp);\r
33\r
34 // Convert bignum to string\r
35 string str;\r
36 str.reserve((pend - pbegin) * 138 / 100 + 1);\r
37 CBigNum dv;\r
38 CBigNum rem;\r
39 while (bn > bn0)\r
40 {\r
41 if (!BN_div(&dv, &rem, &bn, &bn58, pctx))\r
42 throw bignum_error("EncodeBase58 : BN_div failed");\r
43 bn = dv;\r
44 unsigned int c = rem.getulong();\r
45 str += pszBase58[c];\r
46 }\r
47\r
48 // Leading zeroes encoded as base58 zeros\r
49 for (const unsigned char* p = pbegin; p < pend && *p == 0; p++)\r
50 str += pszBase58[0];\r
51\r
52 // Convert little endian string to big endian\r
53 reverse(str.begin(), str.end());\r
54 return str;\r
55}\r
56\r
57inline string EncodeBase58(const vector<unsigned char>& vch)\r
58{\r
59 return EncodeBase58(&vch[0], &vch[0] + vch.size());\r
60}\r
61\r
62inline bool DecodeBase58(const char* psz, vector<unsigned char>& vchRet)\r
63{\r
64 CAutoBN_CTX pctx;\r
65 vchRet.clear();\r
66 CBigNum bn58 = 58;\r
67 CBigNum bn = 0;\r
68 CBigNum bnChar;\r
69 while (isspace(*psz))\r
70 psz++;\r
71\r
72 // Convert big endian string to bignum\r
73 for (const char* p = psz; *p; p++)\r
74 {\r
75 const char* p1 = strchr(pszBase58, *p);\r
76 if (p1 == NULL)\r
77 {\r
78 while (isspace(*p))\r
79 p++;\r
80 if (*p != '\0')\r
81 return false;\r
82 break;\r
83 }\r
84 bnChar.setulong(p1 - pszBase58);\r
85 if (!BN_mul(&bn, &bn, &bn58, pctx))\r
86 throw bignum_error("DecodeBase58 : BN_mul failed");\r
87 bn += bnChar;\r
88 }\r
89\r
90 // Get bignum as little endian data\r
91 vector<unsigned char> vchTmp = bn.getvch();\r
92\r
93 // Trim off sign byte if present\r
94 if (vchTmp.size() >= 2 && vchTmp.end()[-1] == 0 && vchTmp.end()[-2] >= 0x80)\r
95 vchTmp.erase(vchTmp.end()-1);\r
96\r
97 // Restore leading zeros\r
98 int nLeadingZeros = 0;\r
99 for (const char* p = psz; *p == pszBase58[0]; p++)\r
100 nLeadingZeros++;\r
101 vchRet.assign(nLeadingZeros + vchTmp.size(), 0);\r
102\r
103 // Convert little endian data to big endian\r
104 reverse_copy(vchTmp.begin(), vchTmp.end(), vchRet.end() - vchTmp.size());\r
105 return true;\r
106}\r
107\r
108inline bool DecodeBase58(const string& str, vector<unsigned char>& vchRet)\r
109{\r
110 return DecodeBase58(str.c_str(), vchRet);\r
111}\r
112\r
113\r
114\r
115\r
116\r
117inline string EncodeBase58Check(const vector<unsigned char>& vchIn)\r
118{\r
119 // add 4-byte hash check to the end\r
120 vector<unsigned char> vch(vchIn);\r
121 uint256 hash = Hash(vch.begin(), vch.end());\r
122 vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);\r
123 return EncodeBase58(vch);\r
124}\r
125\r
126inline bool DecodeBase58Check(const char* psz, vector<unsigned char>& vchRet)\r
127{\r
128 if (!DecodeBase58(psz, vchRet))\r
129 return false;\r
130 if (vchRet.size() < 4)\r
131 {\r
132 vchRet.clear();\r
133 return false;\r
134 }\r
135 uint256 hash = Hash(vchRet.begin(), vchRet.end()-4);\r
136 if (memcmp(&hash, &vchRet.end()[-4], 4) != 0)\r
137 {\r
138 vchRet.clear();\r
139 return false;\r
140 }\r
141 vchRet.resize(vchRet.size()-4);\r
142 return true;\r
143}\r
144\r
145inline bool DecodeBase58Check(const string& str, vector<unsigned char>& vchRet)\r
146{\r
147 return DecodeBase58Check(str.c_str(), vchRet);\r
148}\r
149\r
150\r
151\r
152\r
153\r
154\r
155static const unsigned char ADDRESSVERSION = 0;\r
156\r
157inline string Hash160ToAddress(uint160 hash160)\r
158{\r
159 // add 1-byte version number to the front\r
160 vector<unsigned char> vch(1, ADDRESSVERSION);\r
161 vch.insert(vch.end(), UBEGIN(hash160), UEND(hash160));\r
162 return EncodeBase58Check(vch);\r
163}\r
164\r
165inline bool AddressToHash160(const char* psz, uint160& hash160Ret)\r
166{\r
167 vector<unsigned char> vch;\r
168 if (!DecodeBase58Check(psz, vch))\r
169 return false;\r
170 if (vch.empty())\r
171 return false;\r
172 unsigned char nVersion = vch[0];\r
173 if (vch.size() != sizeof(hash160Ret) + 1)\r
174 return false;\r
175 memcpy(&hash160Ret, &vch[1], sizeof(hash160Ret));\r
176 return (nVersion <= ADDRESSVERSION);\r
177}\r
178\r
179inline bool AddressToHash160(const string& str, uint160& hash160Ret)\r
180{\r
181 return AddressToHash160(str.c_str(), hash160Ret);\r
182}\r
183\r
184inline bool IsValidBitcoinAddress(const char* psz)\r
185{\r
186 uint160 hash160;\r
187 return AddressToHash160(psz, hash160);\r
188}\r
189\r
190inline bool IsValidBitcoinAddress(const string& str)\r
191{\r
192 return IsValidBitcoinAddress(str.c_str());\r
193}\r
194\r
195\r
196\r
197\r
198inline string PubKeyToAddress(const vector<unsigned char>& vchPubKey)\r
199{\r
200 return Hash160ToAddress(Hash160(vchPubKey));\r
201}\r
This page took 0.044386 seconds and 4 git commands to generate.