├── .gitignore ├── README.md ├── bitcoin.exe ├── libeay32.dll ├── license.txt ├── mingwm10.dll ├── readme.txt └── src ├── base58.h ├── bignum.h ├── db.cpp ├── db.h ├── headers.h ├── irc.cpp ├── irc.h ├── key.h ├── license.txt ├── main.cpp ├── main.h ├── makefile ├── makefile.vc ├── market.cpp ├── market.h ├── net.cpp ├── net.h ├── rc ├── addressbook16.bmp ├── addressbook16mask.bmp ├── addressbook20.bmp ├── addressbook20mask.bmp ├── bitcoin.ico ├── check.ico ├── send16.bmp ├── send16mask.bmp ├── send16masknoshadow.bmp ├── send20.bmp └── send20mask.bmp ├── readme.txt ├── script.cpp ├── script.h ├── serialize.h ├── sha.cpp ├── sha.h ├── ui.cpp ├── ui.h ├── ui.rc ├── uibase.cpp ├── uibase.h ├── uint256.h ├── uiproject.fbp ├── util.cpp └── util.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | 6 | # Compiled Dynamic libraries 7 | *.so 8 | *.dylib 9 | 10 | # Compiled Static libraries 11 | *.lai 12 | *.la 13 | *.a 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | original-bitcoin 2 | ================ 3 | 4 | This is a historical repository of Satoshi Nakamoto's original bitcoin sourcecode -------------------------------------------------------------------------------- /bitcoin.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trottier/original-bitcoin/92ee8d9a994391d148733da77e2bbc2f4acc43cd/bitcoin.exe -------------------------------------------------------------------------------- /libeay32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trottier/original-bitcoin/92ee8d9a994391d148733da77e2bbc2f4acc43cd/libeay32.dll -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 Satoshi Nakamoto 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /mingwm10.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trottier/original-bitcoin/92ee8d9a994391d148733da77e2bbc2f4acc43cd/mingwm10.dll -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | BitCoin v0.1.3 ALPHA 2 | 3 | Copyright (c) 2009 Satoshi Nakamoto 4 | Distributed under the MIT/X11 software license, see the accompanying 5 | file license.txt or http://www.opensource.org/licenses/mit-license.php. 6 | This product includes software developed by the OpenSSL Project for use in 7 | the OpenSSL Toolkit (http://www.openssl.org/). This product includes 8 | cryptographic software written by Eric Young (eay@cryptsoft.com). 9 | 10 | 11 | Intro 12 | ----- 13 | Bitcoin is an electronic cash system that uses a peer-to-peer network to 14 | prevent double-spending. It's completely decentralized with no server or 15 | central authority. 16 | 17 | 18 | Operating Systems 19 | ----------------- 20 | Windows NT/2000/XP (and probably Vista) 21 | 22 | Vista hasn't been tested yet. All the libraries used are cross-platform, so 23 | there's nothing preventing future Linux and Mac builds. 24 | 25 | 26 | Setup 27 | ----- 28 | Unpack the files into a directory and run bitcoin.exe. 29 | 30 | The software automatically finds other nodes to connect to. You should set 31 | your firewall to forward port 8333 to your computer so you can receive incoming 32 | connections, otherwise the nodes you can connect with will be limited. 33 | 34 | To support the network by running a node, select: 35 | 36 | Options->Generate Coins 37 | 38 | and keep the program open or minimized. It runs at idle priority when no other 39 | programs are using the CPU. Your computer will be solving a very difficult 40 | computational problem that is used to lock in blocks of transactions. The time 41 | to generate a block varies each time, but may take days or months, depending 42 | on the speed of your computer and the competition on the network. It's not a 43 | computation that has to start over from the beginning if you stop and restart 44 | it. A solution might be found at any given moment it's running. As a reward 45 | for supporting the network, you receive coins when you successfully generate a 46 | block. 47 | -------------------------------------------------------------------------------- /src/base58.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 Satoshi Nakamoto 2 | // Distributed under the MIT/X11 software license, see the accompanying 3 | // file license.txt or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | 6 | // 7 | // Why base-58 instead of standard base-64 encoding? 8 | // - Don't want 0OIl characters that look the same in some fonts and 9 | // could be used to create visually identical looking account numbers. 10 | // - A string with non-alphanumeric characters is not as easily accepted as an account number. 11 | // - E-mail usually won't line-break if there's no punctuation to break at. 12 | // - Doubleclicking selects the whole number as one word if it's all alphanumeric. 13 | // 14 | 15 | 16 | static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; 17 | 18 | 19 | inline string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend) 20 | { 21 | CAutoBN_CTX pctx; 22 | CBigNum bn58 = 58; 23 | CBigNum bn0 = 0; 24 | 25 | // Convert big endian data to little endian 26 | // Extra zero at the end make sure bignum will interpret as a positive number 27 | vector vchTmp(pend-pbegin+1, 0); 28 | reverse_copy(pbegin, pend, vchTmp.begin()); 29 | 30 | // Convert little endian data to bignum 31 | CBigNum bn; 32 | bn.setvch(vchTmp); 33 | 34 | // Convert bignum to string 35 | string str; 36 | str.reserve((pend - pbegin) * 138 / 100 + 1); 37 | CBigNum dv; 38 | CBigNum rem; 39 | while (bn > bn0) 40 | { 41 | if (!BN_div(&dv, &rem, &bn, &bn58, pctx)) 42 | throw bignum_error("EncodeBase58 : BN_div failed"); 43 | bn = dv; 44 | unsigned int c = rem.getulong(); 45 | str += pszBase58[c]; 46 | } 47 | 48 | // Leading zeroes encoded as base58 zeros 49 | for (const unsigned char* p = pbegin; p < pend && *p == 0; p++) 50 | str += pszBase58[0]; 51 | 52 | // Convert little endian string to big endian 53 | reverse(str.begin(), str.end()); 54 | return str; 55 | } 56 | 57 | inline string EncodeBase58(const vector& vch) 58 | { 59 | return EncodeBase58(&vch[0], &vch[0] + vch.size()); 60 | } 61 | 62 | inline bool DecodeBase58(const char* psz, vector& vchRet) 63 | { 64 | CAutoBN_CTX pctx; 65 | vchRet.clear(); 66 | CBigNum bn58 = 58; 67 | CBigNum bn = 0; 68 | CBigNum bnChar; 69 | while (isspace(*psz)) 70 | psz++; 71 | 72 | // Convert big endian string to bignum 73 | for (const char* p = psz; *p; p++) 74 | { 75 | const char* p1 = strchr(pszBase58, *p); 76 | if (p1 == NULL) 77 | { 78 | while (isspace(*p)) 79 | p++; 80 | if (*p != '\0') 81 | return false; 82 | break; 83 | } 84 | bnChar.setulong(p1 - pszBase58); 85 | if (!BN_mul(&bn, &bn, &bn58, pctx)) 86 | throw bignum_error("DecodeBase58 : BN_mul failed"); 87 | bn += bnChar; 88 | } 89 | 90 | // Get bignum as little endian data 91 | vector vchTmp = bn.getvch(); 92 | 93 | // Trim off sign byte if present 94 | if (vchTmp.size() >= 2 && vchTmp.end()[-1] == 0 && vchTmp.end()[-2] >= 0x80) 95 | vchTmp.erase(vchTmp.end()-1); 96 | 97 | // Restore leading zeros 98 | int nLeadingZeros = 0; 99 | for (const char* p = psz; *p == pszBase58[0]; p++) 100 | nLeadingZeros++; 101 | vchRet.assign(nLeadingZeros + vchTmp.size(), 0); 102 | 103 | // Convert little endian data to big endian 104 | reverse_copy(vchTmp.begin(), vchTmp.end(), vchRet.end() - vchTmp.size()); 105 | return true; 106 | } 107 | 108 | inline bool DecodeBase58(const string& str, vector& vchRet) 109 | { 110 | return DecodeBase58(str.c_str(), vchRet); 111 | } 112 | 113 | 114 | 115 | 116 | 117 | inline string EncodeBase58Check(const vector& vchIn) 118 | { 119 | // add 4-byte hash check to the end 120 | vector vch(vchIn); 121 | uint256 hash = Hash(vch.begin(), vch.end()); 122 | vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4); 123 | return EncodeBase58(vch); 124 | } 125 | 126 | inline bool DecodeBase58Check(const char* psz, vector& vchRet) 127 | { 128 | if (!DecodeBase58(psz, vchRet)) 129 | return false; 130 | if (vchRet.size() < 4) 131 | { 132 | vchRet.clear(); 133 | return false; 134 | } 135 | uint256 hash = Hash(vchRet.begin(), vchRet.end()-4); 136 | if (memcmp(&hash, &vchRet.end()[-4], 4) != 0) 137 | { 138 | vchRet.clear(); 139 | return false; 140 | } 141 | vchRet.resize(vchRet.size()-4); 142 | return true; 143 | } 144 | 145 | inline bool DecodeBase58Check(const string& str, vector& vchRet) 146 | { 147 | return DecodeBase58Check(str.c_str(), vchRet); 148 | } 149 | 150 | 151 | 152 | 153 | 154 | 155 | static const unsigned char ADDRESSVERSION = 0; 156 | 157 | inline string Hash160ToAddress(uint160 hash160) 158 | { 159 | // add 1-byte version number to the front 160 | vector vch(1, ADDRESSVERSION); 161 | vch.insert(vch.end(), UBEGIN(hash160), UEND(hash160)); 162 | return EncodeBase58Check(vch); 163 | } 164 | 165 | inline bool AddressToHash160(const char* psz, uint160& hash160Ret) 166 | { 167 | vector vch; 168 | if (!DecodeBase58Check(psz, vch)) 169 | return false; 170 | if (vch.empty()) 171 | return false; 172 | unsigned char nVersion = vch[0]; 173 | if (vch.size() != sizeof(hash160Ret) + 1) 174 | return false; 175 | memcpy(&hash160Ret, &vch[1], sizeof(hash160Ret)); 176 | return (nVersion <= ADDRESSVERSION); 177 | } 178 | 179 | inline bool AddressToHash160(const string& str, uint160& hash160Ret) 180 | { 181 | return AddressToHash160(str.c_str(), hash160Ret); 182 | } 183 | 184 | inline bool IsValidBitcoinAddress(const char* psz) 185 | { 186 | uint160 hash160; 187 | return AddressToHash160(psz, hash160); 188 | } 189 | 190 | inline bool IsValidBitcoinAddress(const string& str) 191 | { 192 | return IsValidBitcoinAddress(str.c_str()); 193 | } 194 | 195 | 196 | 197 | 198 | inline string PubKeyToAddress(const vector& vchPubKey) 199 | { 200 | return Hash160ToAddress(Hash160(vchPubKey)); 201 | } 202 | -------------------------------------------------------------------------------- /src/bignum.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 Satoshi Nakamoto 2 | // Distributed under the MIT/X11 software license, see the accompanying 3 | // file license.txt or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | 11 | 12 | 13 | class bignum_error : public std::runtime_error 14 | { 15 | public: 16 | explicit bignum_error(const std::string& str) : std::runtime_error(str) {} 17 | }; 18 | 19 | 20 | 21 | class CAutoBN_CTX 22 | { 23 | protected: 24 | BN_CTX* pctx; 25 | BN_CTX* operator=(BN_CTX* pnew) { return pctx = pnew; } 26 | 27 | public: 28 | CAutoBN_CTX() 29 | { 30 | pctx = BN_CTX_new(); 31 | if (pctx == NULL) 32 | throw bignum_error("CAutoBN_CTX : BN_CTX_new() returned NULL"); 33 | } 34 | 35 | ~CAutoBN_CTX() 36 | { 37 | if (pctx != NULL) 38 | BN_CTX_free(pctx); 39 | } 40 | 41 | operator BN_CTX*() { return pctx; } 42 | BN_CTX& operator*() { return *pctx; } 43 | BN_CTX** operator&() { return &pctx; } 44 | bool operator!() { return (pctx == NULL); } 45 | }; 46 | 47 | 48 | 49 | class CBigNum : public BIGNUM 50 | { 51 | public: 52 | CBigNum() 53 | { 54 | BN_init(this); 55 | } 56 | 57 | CBigNum(const CBigNum& b) 58 | { 59 | BN_init(this); 60 | if (!BN_copy(this, &b)) 61 | { 62 | BN_clear_free(this); 63 | throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed"); 64 | } 65 | } 66 | 67 | explicit CBigNum(const std::string& str) 68 | { 69 | BN_init(this); 70 | SetHex(str); 71 | } 72 | 73 | CBigNum& operator=(const CBigNum& b) 74 | { 75 | if (!BN_copy(this, &b)) 76 | throw bignum_error("CBigNum::operator= : BN_copy failed"); 77 | return (*this); 78 | } 79 | 80 | ~CBigNum() 81 | { 82 | BN_clear_free(this); 83 | } 84 | 85 | CBigNum(char n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); } 86 | CBigNum(short n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); } 87 | CBigNum(int n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); } 88 | CBigNum(long n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); } 89 | CBigNum(int64 n) { BN_init(this); setint64(n); } 90 | CBigNum(unsigned char n) { BN_init(this); setulong(n); } 91 | CBigNum(unsigned short n) { BN_init(this); setulong(n); } 92 | CBigNum(unsigned int n) { BN_init(this); setulong(n); } 93 | CBigNum(unsigned long n) { BN_init(this); setulong(n); } 94 | CBigNum(uint64 n) { BN_init(this); setuint64(n); } 95 | explicit CBigNum(uint256 n) { BN_init(this); setuint256(n); } 96 | 97 | explicit CBigNum(const std::vector& vch) 98 | { 99 | BN_init(this); 100 | setvch(vch); 101 | } 102 | 103 | void setulong(unsigned long n) 104 | { 105 | if (!BN_set_word(this, n)) 106 | throw bignum_error("CBigNum conversion from unsigned long : BN_set_word failed"); 107 | } 108 | 109 | unsigned long getulong() const 110 | { 111 | return BN_get_word(this); 112 | } 113 | 114 | unsigned int getuint() const 115 | { 116 | return BN_get_word(this); 117 | } 118 | 119 | int getint() const 120 | { 121 | unsigned long n = BN_get_word(this); 122 | if (!BN_is_negative(this)) 123 | return (n > INT_MAX ? INT_MAX : n); 124 | else 125 | return (n > INT_MAX ? INT_MIN : -(int)n); 126 | } 127 | 128 | void setint64(int64 n) 129 | { 130 | unsigned char pch[sizeof(n) + 6]; 131 | unsigned char* p = pch + 4; 132 | bool fNegative = false; 133 | if (n < (int64)0) 134 | { 135 | n = -n; 136 | fNegative = true; 137 | } 138 | bool fLeadingZeroes = true; 139 | for (int i = 0; i < 8; i++) 140 | { 141 | unsigned char c = (n >> 56) & 0xff; 142 | n <<= 8; 143 | if (fLeadingZeroes) 144 | { 145 | if (c == 0) 146 | continue; 147 | if (c & 0x80) 148 | *p++ = (fNegative ? 0x80 : 0); 149 | else if (fNegative) 150 | c |= 0x80; 151 | fLeadingZeroes = false; 152 | } 153 | *p++ = c; 154 | } 155 | unsigned int nSize = p - (pch + 4); 156 | pch[0] = (nSize >> 24) & 0xff; 157 | pch[1] = (nSize >> 16) & 0xff; 158 | pch[2] = (nSize >> 8) & 0xff; 159 | pch[3] = (nSize) & 0xff; 160 | BN_mpi2bn(pch, p - pch, this); 161 | } 162 | 163 | void setuint64(uint64 n) 164 | { 165 | unsigned char pch[sizeof(n) + 6]; 166 | unsigned char* p = pch + 4; 167 | bool fLeadingZeroes = true; 168 | for (int i = 0; i < 8; i++) 169 | { 170 | unsigned char c = (n >> 56) & 0xff; 171 | n <<= 8; 172 | if (fLeadingZeroes) 173 | { 174 | if (c == 0) 175 | continue; 176 | if (c & 0x80) 177 | *p++ = 0; 178 | fLeadingZeroes = false; 179 | } 180 | *p++ = c; 181 | } 182 | unsigned int nSize = p - (pch + 4); 183 | pch[0] = (nSize >> 24) & 0xff; 184 | pch[1] = (nSize >> 16) & 0xff; 185 | pch[2] = (nSize >> 8) & 0xff; 186 | pch[3] = (nSize) & 0xff; 187 | BN_mpi2bn(pch, p - pch, this); 188 | } 189 | 190 | void setuint256(uint256 n) 191 | { 192 | unsigned char pch[sizeof(n) + 6]; 193 | unsigned char* p = pch + 4; 194 | bool fLeadingZeroes = true; 195 | unsigned char* pbegin = (unsigned char*)&n; 196 | unsigned char* psrc = pbegin + sizeof(n); 197 | while (psrc != pbegin) 198 | { 199 | unsigned char c = *(--psrc); 200 | if (fLeadingZeroes) 201 | { 202 | if (c == 0) 203 | continue; 204 | if (c & 0x80) 205 | *p++ = 0; 206 | fLeadingZeroes = false; 207 | } 208 | *p++ = c; 209 | } 210 | unsigned int nSize = p - (pch + 4); 211 | pch[0] = (nSize >> 24) & 0xff; 212 | pch[1] = (nSize >> 16) & 0xff; 213 | pch[2] = (nSize >> 8) & 0xff; 214 | pch[3] = (nSize >> 0) & 0xff; 215 | BN_mpi2bn(pch, p - pch, this); 216 | } 217 | 218 | uint256 getuint256() 219 | { 220 | unsigned int nSize = BN_bn2mpi(this, NULL); 221 | if (nSize < 4) 222 | return 0; 223 | std::vector vch(nSize); 224 | BN_bn2mpi(this, &vch[0]); 225 | if (vch.size() > 4) 226 | vch[4] &= 0x7f; 227 | uint256 n = 0; 228 | for (int i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--) 229 | ((unsigned char*)&n)[i] = vch[j]; 230 | return n; 231 | } 232 | 233 | void setvch(const std::vector& vch) 234 | { 235 | std::vector vch2(vch.size() + 4); 236 | unsigned int nSize = vch.size(); 237 | vch2[0] = (nSize >> 24) & 0xff; 238 | vch2[1] = (nSize >> 16) & 0xff; 239 | vch2[2] = (nSize >> 8) & 0xff; 240 | vch2[3] = (nSize >> 0) & 0xff; 241 | reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4); 242 | BN_mpi2bn(&vch2[0], vch2.size(), this); 243 | } 244 | 245 | std::vector getvch() const 246 | { 247 | unsigned int nSize = BN_bn2mpi(this, NULL); 248 | if (nSize < 4) 249 | return std::vector(); 250 | std::vector vch(nSize); 251 | BN_bn2mpi(this, &vch[0]); 252 | vch.erase(vch.begin(), vch.begin() + 4); 253 | reverse(vch.begin(), vch.end()); 254 | return vch; 255 | } 256 | 257 | CBigNum& SetCompact(unsigned int nCompact) 258 | { 259 | unsigned int nSize = nCompact >> 24; 260 | std::vector vch(4 + nSize); 261 | vch[3] = nSize; 262 | if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff; 263 | if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff; 264 | if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff; 265 | BN_mpi2bn(&vch[0], vch.size(), this); 266 | return *this; 267 | } 268 | 269 | unsigned int GetCompact() const 270 | { 271 | unsigned int nSize = BN_bn2mpi(this, NULL); 272 | std::vector vch(nSize); 273 | nSize -= 4; 274 | BN_bn2mpi(this, &vch[0]); 275 | unsigned int nCompact = nSize << 24; 276 | if (nSize >= 1) nCompact |= (vch[4] << 16); 277 | if (nSize >= 2) nCompact |= (vch[5] << 8); 278 | if (nSize >= 3) nCompact |= (vch[6] << 0); 279 | return nCompact; 280 | } 281 | 282 | void SetHex(const std::string& str) 283 | { 284 | // skip 0x 285 | const char* psz = str.c_str(); 286 | while (isspace(*psz)) 287 | psz++; 288 | bool fNegative = false; 289 | if (*psz == '-') 290 | { 291 | fNegative = true; 292 | psz++; 293 | } 294 | if (psz[0] == '0' && tolower(psz[1]) == 'x') 295 | psz += 2; 296 | while (isspace(*psz)) 297 | psz++; 298 | 299 | // hex string to bignum 300 | static char phexdigit[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0 }; 301 | *this = 0; 302 | while (isxdigit(*psz)) 303 | { 304 | *this <<= 4; 305 | int n = phexdigit[*psz++]; 306 | *this += n; 307 | } 308 | if (fNegative) 309 | *this = 0 - *this; 310 | } 311 | 312 | unsigned int GetSerializeSize(int nType=0, int nVersion=VERSION) const 313 | { 314 | return ::GetSerializeSize(getvch(), nType, nVersion); 315 | } 316 | 317 | template 318 | void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const 319 | { 320 | ::Serialize(s, getvch(), nType, nVersion); 321 | } 322 | 323 | template 324 | void Unserialize(Stream& s, int nType=0, int nVersion=VERSION) 325 | { 326 | vector vch; 327 | ::Unserialize(s, vch, nType, nVersion); 328 | setvch(vch); 329 | } 330 | 331 | 332 | bool operator!() const 333 | { 334 | return BN_is_zero(this); 335 | } 336 | 337 | CBigNum& operator+=(const CBigNum& b) 338 | { 339 | if (!BN_add(this, this, &b)) 340 | throw bignum_error("CBigNum::operator+= : BN_add failed"); 341 | return *this; 342 | } 343 | 344 | CBigNum& operator-=(const CBigNum& b) 345 | { 346 | *this = *this - b; 347 | return *this; 348 | } 349 | 350 | CBigNum& operator*=(const CBigNum& b) 351 | { 352 | CAutoBN_CTX pctx; 353 | if (!BN_mul(this, this, &b, pctx)) 354 | throw bignum_error("CBigNum::operator*= : BN_mul failed"); 355 | return *this; 356 | } 357 | 358 | CBigNum& operator/=(const CBigNum& b) 359 | { 360 | *this = *this / b; 361 | return *this; 362 | } 363 | 364 | CBigNum& operator%=(const CBigNum& b) 365 | { 366 | *this = *this % b; 367 | return *this; 368 | } 369 | 370 | CBigNum& operator<<=(unsigned int shift) 371 | { 372 | if (!BN_lshift(this, this, shift)) 373 | throw bignum_error("CBigNum:operator<<= : BN_lshift failed"); 374 | return *this; 375 | } 376 | 377 | CBigNum& operator>>=(unsigned int shift) 378 | { 379 | if (!BN_rshift(this, this, shift)) 380 | throw bignum_error("CBigNum:operator>>= : BN_rshift failed"); 381 | return *this; 382 | } 383 | 384 | 385 | CBigNum& operator++() 386 | { 387 | // prefix operator 388 | if (!BN_add(this, this, BN_value_one())) 389 | throw bignum_error("CBigNum::operator++ : BN_add failed"); 390 | return *this; 391 | } 392 | 393 | const CBigNum operator++(int) 394 | { 395 | // postfix operator 396 | const CBigNum ret = *this; 397 | ++(*this); 398 | return ret; 399 | } 400 | 401 | CBigNum& operator--() 402 | { 403 | // prefix operator 404 | CBigNum r; 405 | if (!BN_sub(&r, this, BN_value_one())) 406 | throw bignum_error("CBigNum::operator-- : BN_sub failed"); 407 | *this = r; 408 | return *this; 409 | } 410 | 411 | const CBigNum operator--(int) 412 | { 413 | // postfix operator 414 | const CBigNum ret = *this; 415 | --(*this); 416 | return ret; 417 | } 418 | 419 | 420 | friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b); 421 | friend inline const CBigNum operator/(const CBigNum& a, const CBigNum& b); 422 | friend inline const CBigNum operator%(const CBigNum& a, const CBigNum& b); 423 | }; 424 | 425 | 426 | 427 | inline const CBigNum operator+(const CBigNum& a, const CBigNum& b) 428 | { 429 | CBigNum r; 430 | if (!BN_add(&r, &a, &b)) 431 | throw bignum_error("CBigNum::operator+ : BN_add failed"); 432 | return r; 433 | } 434 | 435 | inline const CBigNum operator-(const CBigNum& a, const CBigNum& b) 436 | { 437 | CBigNum r; 438 | if (!BN_sub(&r, &a, &b)) 439 | throw bignum_error("CBigNum::operator- : BN_sub failed"); 440 | return r; 441 | } 442 | 443 | inline const CBigNum operator-(const CBigNum& a) 444 | { 445 | CBigNum r(a); 446 | BN_set_negative(&r, !BN_is_negative(&r)); 447 | return r; 448 | } 449 | 450 | inline const CBigNum operator*(const CBigNum& a, const CBigNum& b) 451 | { 452 | CAutoBN_CTX pctx; 453 | CBigNum r; 454 | if (!BN_mul(&r, &a, &b, pctx)) 455 | throw bignum_error("CBigNum::operator* : BN_mul failed"); 456 | return r; 457 | } 458 | 459 | inline const CBigNum operator/(const CBigNum& a, const CBigNum& b) 460 | { 461 | CAutoBN_CTX pctx; 462 | CBigNum r; 463 | if (!BN_div(&r, NULL, &a, &b, pctx)) 464 | throw bignum_error("CBigNum::operator/ : BN_div failed"); 465 | return r; 466 | } 467 | 468 | inline const CBigNum operator%(const CBigNum& a, const CBigNum& b) 469 | { 470 | CAutoBN_CTX pctx; 471 | CBigNum r; 472 | if (!BN_mod(&r, &a, &b, pctx)) 473 | throw bignum_error("CBigNum::operator% : BN_div failed"); 474 | return r; 475 | } 476 | 477 | inline const CBigNum operator<<(const CBigNum& a, unsigned int shift) 478 | { 479 | CBigNum r; 480 | if (!BN_lshift(&r, &a, shift)) 481 | throw bignum_error("CBigNum:operator<< : BN_lshift failed"); 482 | return r; 483 | } 484 | 485 | inline const CBigNum operator>>(const CBigNum& a, unsigned int shift) 486 | { 487 | CBigNum r; 488 | if (!BN_rshift(&r, &a, shift)) 489 | throw bignum_error("CBigNum:operator>> : BN_rshift failed"); 490 | return r; 491 | } 492 | 493 | inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) == 0); } 494 | inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) != 0); } 495 | inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) <= 0); } 496 | inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) >= 0); } 497 | inline bool operator<(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) < 0); } 498 | inline bool operator>(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) > 0); } 499 | -------------------------------------------------------------------------------- /src/db.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 Satoshi Nakamoto 2 | // Distributed under the MIT/X11 software license, see the accompanying 3 | // file license.txt or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "headers.h" 6 | 7 | 8 | 9 | 10 | 11 | 12 | // 13 | // CDB 14 | // 15 | 16 | static CCriticalSection cs_db; 17 | static bool fDbEnvInit = false; 18 | DbEnv dbenv(0); 19 | static map mapFileUseCount; 20 | 21 | class CDBInit 22 | { 23 | public: 24 | CDBInit() 25 | { 26 | } 27 | ~CDBInit() 28 | { 29 | if (fDbEnvInit) 30 | { 31 | dbenv.close(0); 32 | fDbEnvInit = false; 33 | } 34 | } 35 | } 36 | instance_of_cdbinit; 37 | 38 | 39 | CDB::CDB(const char* pszFile, const char* pszMode, bool fTxn) : pdb(NULL) 40 | { 41 | int ret; 42 | if (pszFile == NULL) 43 | return; 44 | 45 | bool fCreate = strchr(pszMode, 'c'); 46 | bool fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w')); 47 | unsigned int nFlags = DB_THREAD; 48 | if (fCreate) 49 | nFlags |= DB_CREATE; 50 | else if (fReadOnly) 51 | nFlags |= DB_RDONLY; 52 | if (!fReadOnly || fTxn) 53 | nFlags |= DB_AUTO_COMMIT; 54 | 55 | CRITICAL_BLOCK(cs_db) 56 | { 57 | if (!fDbEnvInit) 58 | { 59 | string strAppDir = GetAppDir(); 60 | string strLogDir = strAppDir + "\\database"; 61 | _mkdir(strLogDir.c_str()); 62 | printf("dbenv.open strAppDir=%s\n", strAppDir.c_str()); 63 | 64 | dbenv.set_lg_dir(strLogDir.c_str()); 65 | dbenv.set_lg_max(10000000); 66 | dbenv.set_lk_max_locks(10000); 67 | dbenv.set_lk_max_objects(10000); 68 | dbenv.set_errfile(fopen("db.log", "a")); /// debug 69 | ///dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1); /// causes corruption 70 | ret = dbenv.open(strAppDir.c_str(), 71 | DB_CREATE | 72 | DB_INIT_LOCK | 73 | DB_INIT_LOG | 74 | DB_INIT_MPOOL | 75 | DB_INIT_TXN | 76 | DB_THREAD | 77 | DB_PRIVATE | 78 | DB_RECOVER, 79 | 0); 80 | if (ret > 0) 81 | throw runtime_error(strprintf("CDB() : error %d opening database environment\n", ret)); 82 | fDbEnvInit = true; 83 | } 84 | 85 | strFile = pszFile; 86 | ++mapFileUseCount[strFile]; 87 | } 88 | 89 | pdb = new Db(&dbenv, 0); 90 | 91 | ret = pdb->open(NULL, // Txn pointer 92 | pszFile, // Filename 93 | "main", // Logical db name 94 | DB_BTREE, // Database type 95 | nFlags, // Flags 96 | 0); 97 | 98 | if (ret > 0) 99 | { 100 | delete pdb; 101 | pdb = NULL; 102 | CRITICAL_BLOCK(cs_db) 103 | --mapFileUseCount[strFile]; 104 | strFile = ""; 105 | throw runtime_error(strprintf("CDB() : can't open database file %s, error %d\n", pszFile, ret)); 106 | } 107 | 108 | if (fCreate && !Exists(string("version"))) 109 | WriteVersion(VERSION); 110 | 111 | RandAddSeed(); 112 | } 113 | 114 | void CDB::Close() 115 | { 116 | if (!pdb) 117 | return; 118 | if (!vTxn.empty()) 119 | vTxn.front()->abort(); 120 | vTxn.clear(); 121 | pdb->close(0); 122 | delete pdb; 123 | pdb = NULL; 124 | dbenv.txn_checkpoint(0, 0, 0); 125 | 126 | CRITICAL_BLOCK(cs_db) 127 | --mapFileUseCount[strFile]; 128 | 129 | RandAddSeed(); 130 | } 131 | 132 | void DBFlush(bool fShutdown) 133 | { 134 | // Flush log data to the actual data file 135 | // on all files that are not in use 136 | printf("DBFlush(%s)\n", fShutdown ? "true" : "false"); 137 | CRITICAL_BLOCK(cs_db) 138 | { 139 | dbenv.txn_checkpoint(0, 0, 0); 140 | map::iterator mi = mapFileUseCount.begin(); 141 | while (mi != mapFileUseCount.end()) 142 | { 143 | string strFile = (*mi).first; 144 | int nRefCount = (*mi).second; 145 | if (nRefCount == 0) 146 | { 147 | dbenv.lsn_reset(strFile.c_str(), 0); 148 | mapFileUseCount.erase(mi++); 149 | } 150 | else 151 | mi++; 152 | } 153 | if (fShutdown) 154 | { 155 | char** listp; 156 | if (mapFileUseCount.empty()) 157 | dbenv.log_archive(&listp, DB_ARCH_REMOVE); 158 | dbenv.close(0); 159 | fDbEnvInit = false; 160 | } 161 | } 162 | } 163 | 164 | 165 | 166 | 167 | 168 | 169 | // 170 | // CTxDB 171 | // 172 | 173 | bool CTxDB::ReadTxIndex(uint256 hash, CTxIndex& txindex) 174 | { 175 | assert(!fClient); 176 | txindex.SetNull(); 177 | return Read(make_pair(string("tx"), hash), txindex); 178 | } 179 | 180 | bool CTxDB::UpdateTxIndex(uint256 hash, const CTxIndex& txindex) 181 | { 182 | assert(!fClient); 183 | return Write(make_pair(string("tx"), hash), txindex); 184 | } 185 | 186 | bool CTxDB::AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight) 187 | { 188 | assert(!fClient); 189 | 190 | // Add to tx index 191 | uint256 hash = tx.GetHash(); 192 | CTxIndex txindex(pos, tx.vout.size()); 193 | return Write(make_pair(string("tx"), hash), txindex); 194 | } 195 | 196 | bool CTxDB::EraseTxIndex(const CTransaction& tx) 197 | { 198 | assert(!fClient); 199 | uint256 hash = tx.GetHash(); 200 | 201 | return Erase(make_pair(string("tx"), hash)); 202 | } 203 | 204 | bool CTxDB::ContainsTx(uint256 hash) 205 | { 206 | assert(!fClient); 207 | return Exists(make_pair(string("tx"), hash)); 208 | } 209 | 210 | bool CTxDB::ReadOwnerTxes(uint160 hash160, int nMinHeight, vector& vtx) 211 | { 212 | assert(!fClient); 213 | vtx.clear(); 214 | 215 | // Get cursor 216 | Dbc* pcursor = GetCursor(); 217 | if (!pcursor) 218 | return false; 219 | 220 | unsigned int fFlags = DB_SET_RANGE; 221 | loop 222 | { 223 | // Read next record 224 | CDataStream ssKey; 225 | if (fFlags == DB_SET_RANGE) 226 | ssKey << string("owner") << hash160 << CDiskTxPos(0, 0, 0); 227 | CDataStream ssValue; 228 | int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags); 229 | fFlags = DB_NEXT; 230 | if (ret == DB_NOTFOUND) 231 | break; 232 | else if (ret != 0) 233 | return false; 234 | 235 | // Unserialize 236 | string strType; 237 | uint160 hashItem; 238 | CDiskTxPos pos; 239 | ssKey >> strType >> hashItem >> pos; 240 | int nItemHeight; 241 | ssValue >> nItemHeight; 242 | 243 | // Read transaction 244 | if (strType != "owner" || hashItem != hash160) 245 | break; 246 | if (nItemHeight >= nMinHeight) 247 | { 248 | vtx.resize(vtx.size()+1); 249 | if (!vtx.back().ReadFromDisk(pos)) 250 | return false; 251 | } 252 | } 253 | return true; 254 | } 255 | 256 | bool CTxDB::ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex) 257 | { 258 | assert(!fClient); 259 | tx.SetNull(); 260 | if (!ReadTxIndex(hash, txindex)) 261 | return false; 262 | return (tx.ReadFromDisk(txindex.pos)); 263 | } 264 | 265 | bool CTxDB::ReadDiskTx(uint256 hash, CTransaction& tx) 266 | { 267 | CTxIndex txindex; 268 | return ReadDiskTx(hash, tx, txindex); 269 | } 270 | 271 | bool CTxDB::ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex) 272 | { 273 | return ReadDiskTx(outpoint.hash, tx, txindex); 274 | } 275 | 276 | bool CTxDB::ReadDiskTx(COutPoint outpoint, CTransaction& tx) 277 | { 278 | CTxIndex txindex; 279 | return ReadDiskTx(outpoint.hash, tx, txindex); 280 | } 281 | 282 | bool CTxDB::WriteBlockIndex(const CDiskBlockIndex& blockindex) 283 | { 284 | return Write(make_pair(string("blockindex"), blockindex.GetBlockHash()), blockindex); 285 | } 286 | 287 | bool CTxDB::EraseBlockIndex(uint256 hash) 288 | { 289 | return Erase(make_pair(string("blockindex"), hash)); 290 | } 291 | 292 | bool CTxDB::ReadHashBestChain(uint256& hashBestChain) 293 | { 294 | return Read(string("hashBestChain"), hashBestChain); 295 | } 296 | 297 | bool CTxDB::WriteHashBestChain(uint256 hashBestChain) 298 | { 299 | return Write(string("hashBestChain"), hashBestChain); 300 | } 301 | 302 | CBlockIndex* InsertBlockIndex(uint256 hash) 303 | { 304 | if (hash == 0) 305 | return NULL; 306 | 307 | // Return existing 308 | map::iterator mi = mapBlockIndex.find(hash); 309 | if (mi != mapBlockIndex.end()) 310 | return (*mi).second; 311 | 312 | // Create new 313 | CBlockIndex* pindexNew = new CBlockIndex(); 314 | if (!pindexNew) 315 | throw runtime_error("LoadBlockIndex() : new CBlockIndex failed"); 316 | mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first; 317 | pindexNew->phashBlock = &((*mi).first); 318 | 319 | return pindexNew; 320 | } 321 | 322 | bool CTxDB::LoadBlockIndex() 323 | { 324 | // Get cursor 325 | Dbc* pcursor = GetCursor(); 326 | if (!pcursor) 327 | return false; 328 | 329 | unsigned int fFlags = DB_SET_RANGE; 330 | loop 331 | { 332 | // Read next record 333 | CDataStream ssKey; 334 | if (fFlags == DB_SET_RANGE) 335 | ssKey << make_pair(string("blockindex"), uint256(0)); 336 | CDataStream ssValue; 337 | int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags); 338 | fFlags = DB_NEXT; 339 | if (ret == DB_NOTFOUND) 340 | break; 341 | else if (ret != 0) 342 | return false; 343 | 344 | // Unserialize 345 | string strType; 346 | ssKey >> strType; 347 | if (strType == "blockindex") 348 | { 349 | CDiskBlockIndex diskindex; 350 | ssValue >> diskindex; 351 | 352 | // Construct block index object 353 | CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash()); 354 | pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev); 355 | pindexNew->pnext = InsertBlockIndex(diskindex.hashNext); 356 | pindexNew->nFile = diskindex.nFile; 357 | pindexNew->nBlockPos = diskindex.nBlockPos; 358 | pindexNew->nHeight = diskindex.nHeight; 359 | pindexNew->nVersion = diskindex.nVersion; 360 | pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot; 361 | pindexNew->nTime = diskindex.nTime; 362 | pindexNew->nBits = diskindex.nBits; 363 | pindexNew->nNonce = diskindex.nNonce; 364 | 365 | // Watch for genesis block and best block 366 | if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == hashGenesisBlock) 367 | pindexGenesisBlock = pindexNew; 368 | } 369 | else 370 | { 371 | break; 372 | } 373 | } 374 | 375 | if (!ReadHashBestChain(hashBestChain)) 376 | { 377 | if (pindexGenesisBlock == NULL) 378 | return true; 379 | return error("CTxDB::LoadBlockIndex() : hashBestChain not found\n"); 380 | } 381 | 382 | if (!mapBlockIndex.count(hashBestChain)) 383 | return error("CTxDB::LoadBlockIndex() : blockindex for hashBestChain not found\n"); 384 | pindexBest = mapBlockIndex[hashBestChain]; 385 | nBestHeight = pindexBest->nHeight; 386 | printf("LoadBlockIndex(): hashBestChain=%s height=%d\n", hashBestChain.ToString().substr(0,14).c_str(), nBestHeight); 387 | 388 | return true; 389 | } 390 | 391 | 392 | 393 | 394 | 395 | // 396 | // CAddrDB 397 | // 398 | 399 | bool CAddrDB::WriteAddress(const CAddress& addr) 400 | { 401 | return Write(make_pair(string("addr"), addr.GetKey()), addr); 402 | } 403 | 404 | bool CAddrDB::LoadAddresses() 405 | { 406 | CRITICAL_BLOCK(cs_mapAddresses) 407 | { 408 | // Load user provided addresses 409 | CAutoFile filein = fopen("addr.txt", "rt"); 410 | if (filein) 411 | { 412 | try 413 | { 414 | char psz[1000]; 415 | while (fgets(psz, sizeof(psz), filein)) 416 | { 417 | CAddress addr(psz, NODE_NETWORK); 418 | if (addr.ip != 0) 419 | AddAddress(*this, addr); 420 | } 421 | } 422 | catch (...) { } 423 | } 424 | 425 | // Get cursor 426 | Dbc* pcursor = GetCursor(); 427 | if (!pcursor) 428 | return false; 429 | 430 | loop 431 | { 432 | // Read next record 433 | CDataStream ssKey; 434 | CDataStream ssValue; 435 | int ret = ReadAtCursor(pcursor, ssKey, ssValue); 436 | if (ret == DB_NOTFOUND) 437 | break; 438 | else if (ret != 0) 439 | return false; 440 | 441 | // Unserialize 442 | string strType; 443 | ssKey >> strType; 444 | if (strType == "addr") 445 | { 446 | CAddress addr; 447 | ssValue >> addr; 448 | mapAddresses.insert(make_pair(addr.GetKey(), addr)); 449 | } 450 | } 451 | 452 | //// debug print 453 | printf("mapAddresses:\n"); 454 | foreach(const PAIRTYPE(vector, CAddress)& item, mapAddresses) 455 | item.second.print(); 456 | printf("-----\n"); 457 | 458 | // Fix for possible GCC bug that manifests in mapAddresses.count in irc.cpp, 459 | // just need to call count here and it doesn't happen there, do not delete this! 460 | mapAddresses.count(vector(18)); 461 | } 462 | 463 | return true; 464 | } 465 | 466 | bool LoadAddresses() 467 | { 468 | return CAddrDB("cr+").LoadAddresses(); 469 | } 470 | 471 | 472 | 473 | 474 | // 475 | // CReviewDB 476 | // 477 | 478 | bool CReviewDB::ReadReviews(uint256 hash, vector& vReviews) 479 | { 480 | vReviews.size(); // msvc workaround, just need to do anything with vReviews 481 | return Read(make_pair(string("reviews"), hash), vReviews); 482 | } 483 | 484 | bool CReviewDB::WriteReviews(uint256 hash, const vector& vReviews) 485 | { 486 | return Write(make_pair(string("reviews"), hash), vReviews); 487 | } 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | // 496 | // CWalletDB 497 | // 498 | 499 | bool CWalletDB::LoadWallet(vector& vchDefaultKeyRet) 500 | { 501 | vchDefaultKeyRet.clear(); 502 | 503 | //// todo: shouldn't we catch exceptions and try to recover and continue? 504 | CRITICAL_BLOCK(cs_mapKeys) 505 | CRITICAL_BLOCK(cs_mapWallet) 506 | { 507 | // Get cursor 508 | Dbc* pcursor = GetCursor(); 509 | if (!pcursor) 510 | return false; 511 | 512 | loop 513 | { 514 | // Read next record 515 | CDataStream ssKey; 516 | CDataStream ssValue; 517 | int ret = ReadAtCursor(pcursor, ssKey, ssValue); 518 | if (ret == DB_NOTFOUND) 519 | break; 520 | else if (ret != 0) 521 | return false; 522 | 523 | // Unserialize 524 | // Taking advantage of the fact that pair serialization 525 | // is just the two items serialized one after the other 526 | string strType; 527 | ssKey >> strType; 528 | if (strType == "name") 529 | { 530 | string strAddress; 531 | ssKey >> strAddress; 532 | ssValue >> mapAddressBook[strAddress]; 533 | } 534 | else if (strType == "tx") 535 | { 536 | uint256 hash; 537 | ssKey >> hash; 538 | CWalletTx& wtx = mapWallet[hash]; 539 | ssValue >> wtx; 540 | 541 | if (wtx.GetHash() != hash) 542 | printf("Error in wallet.dat, hash mismatch\n"); 543 | 544 | //// debug print 545 | //printf("LoadWallet %s\n", wtx.GetHash().ToString().c_str()); 546 | //printf(" %12I64d %s %s %s\n", 547 | // wtx.vout[0].nValue, 548 | // DateTimeStr(wtx.nTime).c_str(), 549 | // wtx.hashBlock.ToString().substr(0,14).c_str(), 550 | // wtx.mapValue["message"].c_str()); 551 | } 552 | else if (strType == "key") 553 | { 554 | vector vchPubKey; 555 | ssKey >> vchPubKey; 556 | CPrivKey vchPrivKey; 557 | ssValue >> vchPrivKey; 558 | 559 | mapKeys[vchPubKey] = vchPrivKey; 560 | mapPubKeys[Hash160(vchPubKey)] = vchPubKey; 561 | } 562 | else if (strType == "defaultkey") 563 | { 564 | ssValue >> vchDefaultKeyRet; 565 | } 566 | else if (strType == "setting") /// or settings or option or options or config? 567 | { 568 | string strKey; 569 | ssKey >> strKey; 570 | if (strKey == "fGenerateBitcoins") ssValue >> fGenerateBitcoins; 571 | if (strKey == "nTransactionFee") ssValue >> nTransactionFee; 572 | if (strKey == "addrIncoming") ssValue >> addrIncoming; 573 | } 574 | } 575 | } 576 | 577 | printf("fGenerateBitcoins = %d\n", fGenerateBitcoins); 578 | printf("nTransactionFee = %I64d\n", nTransactionFee); 579 | printf("addrIncoming = %s\n", addrIncoming.ToString().c_str()); 580 | 581 | return true; 582 | } 583 | 584 | bool LoadWallet() 585 | { 586 | vector vchDefaultKey; 587 | if (!CWalletDB("cr").LoadWallet(vchDefaultKey)) 588 | return false; 589 | 590 | if (mapKeys.count(vchDefaultKey)) 591 | { 592 | // Set keyUser 593 | keyUser.SetPubKey(vchDefaultKey); 594 | keyUser.SetPrivKey(mapKeys[vchDefaultKey]); 595 | } 596 | else 597 | { 598 | // Create new keyUser and set as default key 599 | keyUser.MakeNewKey(); 600 | if (!AddKey(keyUser)) 601 | return false; 602 | if (!SetAddressBookName(PubKeyToAddress(keyUser.GetPubKey()), "Your Address")) 603 | return false; 604 | CWalletDB().WriteDefaultKey(keyUser.GetPubKey()); 605 | } 606 | 607 | return true; 608 | } 609 | -------------------------------------------------------------------------------- /src/db.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 Satoshi Nakamoto 2 | // Distributed under the MIT/X11 software license, see the accompanying 3 | // file license.txt or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include 6 | class CTransaction; 7 | class CTxIndex; 8 | class CDiskBlockIndex; 9 | class CDiskTxPos; 10 | class COutPoint; 11 | class CUser; 12 | class CReview; 13 | class CAddress; 14 | class CWalletTx; 15 | 16 | extern map mapAddressBook; 17 | extern bool fClient; 18 | 19 | 20 | extern DbEnv dbenv; 21 | extern void DBFlush(bool fShutdown); 22 | 23 | 24 | 25 | 26 | class CDB 27 | { 28 | protected: 29 | Db* pdb; 30 | string strFile; 31 | vector vTxn; 32 | 33 | explicit CDB(const char* pszFile, const char* pszMode="r+", bool fTxn=false); 34 | ~CDB() { Close(); } 35 | public: 36 | void Close(); 37 | private: 38 | CDB(const CDB&); 39 | void operator=(const CDB&); 40 | 41 | protected: 42 | template 43 | bool Read(const K& key, T& value) 44 | { 45 | if (!pdb) 46 | return false; 47 | 48 | // Key 49 | CDataStream ssKey(SER_DISK); 50 | ssKey.reserve(1000); 51 | ssKey << key; 52 | Dbt datKey(&ssKey[0], ssKey.size()); 53 | 54 | // Read 55 | Dbt datValue; 56 | datValue.set_flags(DB_DBT_MALLOC); 57 | int ret = pdb->get(GetTxn(), &datKey, &datValue, 0); 58 | memset(datKey.get_data(), 0, datKey.get_size()); 59 | if (datValue.get_data() == NULL) 60 | return false; 61 | 62 | // Unserialize value 63 | CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK); 64 | ssValue >> value; 65 | 66 | // Clear and free memory 67 | memset(datValue.get_data(), 0, datValue.get_size()); 68 | free(datValue.get_data()); 69 | return (ret == 0); 70 | } 71 | 72 | template 73 | bool Write(const K& key, const T& value, bool fOverwrite=true) 74 | { 75 | if (!pdb) 76 | return false; 77 | 78 | // Key 79 | CDataStream ssKey(SER_DISK); 80 | ssKey.reserve(1000); 81 | ssKey << key; 82 | Dbt datKey(&ssKey[0], ssKey.size()); 83 | 84 | // Value 85 | CDataStream ssValue(SER_DISK); 86 | ssValue.reserve(10000); 87 | ssValue << value; 88 | Dbt datValue(&ssValue[0], ssValue.size()); 89 | 90 | // Write 91 | int ret = pdb->put(GetTxn(), &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE)); 92 | 93 | // Clear memory in case it was a private key 94 | memset(datKey.get_data(), 0, datKey.get_size()); 95 | memset(datValue.get_data(), 0, datValue.get_size()); 96 | return (ret == 0); 97 | } 98 | 99 | template 100 | bool Erase(const K& key) 101 | { 102 | if (!pdb) 103 | return false; 104 | 105 | // Key 106 | CDataStream ssKey(SER_DISK); 107 | ssKey.reserve(1000); 108 | ssKey << key; 109 | Dbt datKey(&ssKey[0], ssKey.size()); 110 | 111 | // Erase 112 | int ret = pdb->del(GetTxn(), &datKey, 0); 113 | 114 | // Clear memory 115 | memset(datKey.get_data(), 0, datKey.get_size()); 116 | return (ret == 0 || ret == DB_NOTFOUND); 117 | } 118 | 119 | template 120 | bool Exists(const K& key) 121 | { 122 | if (!pdb) 123 | return false; 124 | 125 | // Key 126 | CDataStream ssKey(SER_DISK); 127 | ssKey.reserve(1000); 128 | ssKey << key; 129 | Dbt datKey(&ssKey[0], ssKey.size()); 130 | 131 | // Exists 132 | int ret = pdb->exists(GetTxn(), &datKey, 0); 133 | 134 | // Clear memory 135 | memset(datKey.get_data(), 0, datKey.get_size()); 136 | return (ret == 0); 137 | } 138 | 139 | Dbc* GetCursor() 140 | { 141 | if (!pdb) 142 | return NULL; 143 | Dbc* pcursor = NULL; 144 | int ret = pdb->cursor(NULL, &pcursor, 0); 145 | if (ret != 0) 146 | return NULL; 147 | return pcursor; 148 | } 149 | 150 | int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, unsigned int fFlags=DB_NEXT) 151 | { 152 | // Read at cursor 153 | Dbt datKey; 154 | if (fFlags == DB_SET || fFlags == DB_SET_RANGE || fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE) 155 | { 156 | datKey.set_data(&ssKey[0]); 157 | datKey.set_size(ssKey.size()); 158 | } 159 | Dbt datValue; 160 | if (fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE) 161 | { 162 | datValue.set_data(&ssValue[0]); 163 | datValue.set_size(ssValue.size()); 164 | } 165 | datKey.set_flags(DB_DBT_MALLOC); 166 | datValue.set_flags(DB_DBT_MALLOC); 167 | int ret = pcursor->get(&datKey, &datValue, fFlags); 168 | if (ret != 0) 169 | return ret; 170 | else if (datKey.get_data() == NULL || datValue.get_data() == NULL) 171 | return 99999; 172 | 173 | // Convert to streams 174 | ssKey.SetType(SER_DISK); 175 | ssKey.clear(); 176 | ssKey.write((char*)datKey.get_data(), datKey.get_size()); 177 | ssValue.SetType(SER_DISK); 178 | ssValue.clear(); 179 | ssValue.write((char*)datValue.get_data(), datValue.get_size()); 180 | 181 | // Clear and free memory 182 | memset(datKey.get_data(), 0, datKey.get_size()); 183 | memset(datValue.get_data(), 0, datValue.get_size()); 184 | free(datKey.get_data()); 185 | free(datValue.get_data()); 186 | return 0; 187 | } 188 | 189 | DbTxn* GetTxn() 190 | { 191 | if (!vTxn.empty()) 192 | return vTxn.back(); 193 | else 194 | return NULL; 195 | } 196 | 197 | public: 198 | bool TxnBegin() 199 | { 200 | if (!pdb) 201 | return false; 202 | DbTxn* ptxn = NULL; 203 | int ret = dbenv.txn_begin(GetTxn(), &ptxn, 0); 204 | if (!ptxn || ret != 0) 205 | return false; 206 | vTxn.push_back(ptxn); 207 | return true; 208 | } 209 | 210 | bool TxnCommit() 211 | { 212 | if (!pdb) 213 | return false; 214 | if (vTxn.empty()) 215 | return false; 216 | int ret = vTxn.back()->commit(0); 217 | vTxn.pop_back(); 218 | return (ret == 0); 219 | } 220 | 221 | bool TxnAbort() 222 | { 223 | if (!pdb) 224 | return false; 225 | if (vTxn.empty()) 226 | return false; 227 | int ret = vTxn.back()->abort(); 228 | vTxn.pop_back(); 229 | return (ret == 0); 230 | } 231 | 232 | bool ReadVersion(int& nVersion) 233 | { 234 | nVersion = 0; 235 | return Read(string("version"), nVersion); 236 | } 237 | 238 | bool WriteVersion(int nVersion) 239 | { 240 | return Write(string("version"), nVersion); 241 | } 242 | }; 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | class CTxDB : public CDB 252 | { 253 | public: 254 | CTxDB(const char* pszMode="r+", bool fTxn=false) : CDB(!fClient ? "blkindex.dat" : NULL, pszMode, fTxn) { } 255 | private: 256 | CTxDB(const CTxDB&); 257 | void operator=(const CTxDB&); 258 | public: 259 | bool ReadTxIndex(uint256 hash, CTxIndex& txindex); 260 | bool UpdateTxIndex(uint256 hash, const CTxIndex& txindex); 261 | bool AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight); 262 | bool EraseTxIndex(const CTransaction& tx); 263 | bool ContainsTx(uint256 hash); 264 | bool ReadOwnerTxes(uint160 hash160, int nHeight, vector& vtx); 265 | bool ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex); 266 | bool ReadDiskTx(uint256 hash, CTransaction& tx); 267 | bool ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex); 268 | bool ReadDiskTx(COutPoint outpoint, CTransaction& tx); 269 | bool WriteBlockIndex(const CDiskBlockIndex& blockindex); 270 | bool EraseBlockIndex(uint256 hash); 271 | bool ReadHashBestChain(uint256& hashBestChain); 272 | bool WriteHashBestChain(uint256 hashBestChain); 273 | bool LoadBlockIndex(); 274 | }; 275 | 276 | 277 | 278 | 279 | 280 | class CReviewDB : public CDB 281 | { 282 | public: 283 | CReviewDB(const char* pszMode="r+", bool fTxn=false) : CDB("reviews.dat", pszMode, fTxn) { } 284 | private: 285 | CReviewDB(const CReviewDB&); 286 | void operator=(const CReviewDB&); 287 | public: 288 | bool ReadUser(uint256 hash, CUser& user) 289 | { 290 | return Read(make_pair(string("user"), hash), user); 291 | } 292 | 293 | bool WriteUser(uint256 hash, const CUser& user) 294 | { 295 | return Write(make_pair(string("user"), hash), user); 296 | } 297 | 298 | bool ReadReviews(uint256 hash, vector& vReviews); 299 | bool WriteReviews(uint256 hash, const vector& vReviews); 300 | }; 301 | 302 | 303 | 304 | 305 | 306 | class CMarketDB : public CDB 307 | { 308 | public: 309 | CMarketDB(const char* pszMode="r+", bool fTxn=false) : CDB("market.dat", pszMode, fTxn) { } 310 | private: 311 | CMarketDB(const CMarketDB&); 312 | void operator=(const CMarketDB&); 313 | }; 314 | 315 | 316 | 317 | 318 | 319 | class CAddrDB : public CDB 320 | { 321 | public: 322 | CAddrDB(const char* pszMode="r+", bool fTxn=false) : CDB("addr.dat", pszMode, fTxn) { } 323 | private: 324 | CAddrDB(const CAddrDB&); 325 | void operator=(const CAddrDB&); 326 | public: 327 | bool WriteAddress(const CAddress& addr); 328 | bool LoadAddresses(); 329 | }; 330 | 331 | bool LoadAddresses(); 332 | 333 | 334 | 335 | 336 | 337 | class CWalletDB : public CDB 338 | { 339 | public: 340 | CWalletDB(const char* pszMode="r+", bool fTxn=false) : CDB("wallet.dat", pszMode, fTxn) { } 341 | private: 342 | CWalletDB(const CWalletDB&); 343 | void operator=(const CWalletDB&); 344 | public: 345 | bool ReadName(const string& strAddress, string& strName) 346 | { 347 | strName = ""; 348 | return Read(make_pair(string("name"), strAddress), strName); 349 | } 350 | 351 | bool WriteName(const string& strAddress, const string& strName) 352 | { 353 | mapAddressBook[strAddress] = strName; 354 | return Write(make_pair(string("name"), strAddress), strName); 355 | } 356 | 357 | bool EraseName(const string& strAddress) 358 | { 359 | mapAddressBook.erase(strAddress); 360 | return Erase(make_pair(string("name"), strAddress)); 361 | } 362 | 363 | bool ReadTx(uint256 hash, CWalletTx& wtx) 364 | { 365 | return Read(make_pair(string("tx"), hash), wtx); 366 | } 367 | 368 | bool WriteTx(uint256 hash, const CWalletTx& wtx) 369 | { 370 | return Write(make_pair(string("tx"), hash), wtx); 371 | } 372 | 373 | bool EraseTx(uint256 hash) 374 | { 375 | return Erase(make_pair(string("tx"), hash)); 376 | } 377 | 378 | bool ReadKey(const vector& vchPubKey, CPrivKey& vchPrivKey) 379 | { 380 | vchPrivKey.clear(); 381 | return Read(make_pair(string("key"), vchPubKey), vchPrivKey); 382 | } 383 | 384 | bool WriteKey(const vector& vchPubKey, const CPrivKey& vchPrivKey) 385 | { 386 | return Write(make_pair(string("key"), vchPubKey), vchPrivKey, false); 387 | } 388 | 389 | bool ReadDefaultKey(vector& vchPubKey) 390 | { 391 | vchPubKey.clear(); 392 | return Read(string("defaultkey"), vchPubKey); 393 | } 394 | 395 | bool WriteDefaultKey(const vector& vchPubKey) 396 | { 397 | return Write(string("defaultkey"), vchPubKey); 398 | } 399 | 400 | template 401 | bool ReadSetting(const string& strKey, T& value) 402 | { 403 | return Read(make_pair(string("setting"), strKey), value); 404 | } 405 | 406 | template 407 | bool WriteSetting(const string& strKey, const T& value) 408 | { 409 | return Write(make_pair(string("setting"), strKey), value); 410 | } 411 | 412 | bool LoadWallet(vector& vchDefaultKeyRet); 413 | }; 414 | 415 | bool LoadWallet(); 416 | 417 | inline bool SetAddressBookName(const string& strAddress, const string& strName) 418 | { 419 | return CWalletDB().WriteName(strAddress, strName); 420 | } 421 | -------------------------------------------------------------------------------- /src/headers.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 Satoshi Nakamoto 2 | // Distributed under the MIT/X11 software license, see the accompanying 3 | // file license.txt or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #ifdef _MSC_VER 6 | #pragma warning(disable:4786) 7 | #pragma warning(disable:4804) 8 | #pragma warning(disable:4717) 9 | #endif 10 | #ifdef _WIN32_WINNT 11 | #undef _WIN32_WINNT 12 | #endif 13 | #define _WIN32_WINNT 0x0400 14 | #define WIN32_LEAN_AND_MEAN 1 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #define BOUNDSCHECK 1 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #pragma hdrstop 53 | using namespace std; 54 | using namespace boost; 55 | 56 | 57 | 58 | #include "serialize.h" 59 | #include "uint256.h" 60 | #include "util.h" 61 | #include "key.h" 62 | #include "bignum.h" 63 | #include "base58.h" 64 | #include "script.h" 65 | #include "db.h" 66 | #include "net.h" 67 | #include "irc.h" 68 | #include "main.h" 69 | #include "market.h" 70 | #include "uibase.h" 71 | #include "ui.h" 72 | -------------------------------------------------------------------------------- /src/irc.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 Satoshi Nakamoto 2 | // Distributed under the MIT/X11 software license, see the accompanying 3 | // file license.txt or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "headers.h" 6 | 7 | 8 | 9 | 10 | #pragma pack(1) 11 | struct ircaddr 12 | { 13 | int ip; 14 | short port; 15 | }; 16 | 17 | string EncodeAddress(const CAddress& addr) 18 | { 19 | struct ircaddr tmp; 20 | tmp.ip = addr.ip; 21 | tmp.port = addr.port; 22 | 23 | vector vch(UBEGIN(tmp), UEND(tmp)); 24 | return string("u") + EncodeBase58Check(vch); 25 | } 26 | 27 | bool DecodeAddress(string str, CAddress& addr) 28 | { 29 | vector vch; 30 | if (!DecodeBase58Check(str.substr(1), vch)) 31 | return false; 32 | 33 | struct ircaddr tmp; 34 | if (vch.size() != sizeof(tmp)) 35 | return false; 36 | memcpy(&tmp, &vch[0], sizeof(tmp)); 37 | 38 | addr = CAddress(tmp.ip, tmp.port); 39 | return true; 40 | } 41 | 42 | 43 | 44 | 45 | 46 | 47 | static bool Send(SOCKET hSocket, const char* pszSend) 48 | { 49 | if (strstr(pszSend, "PONG") != pszSend) 50 | printf("SENDING: %s\n", pszSend); 51 | const char* psz = pszSend; 52 | const char* pszEnd = psz + strlen(psz); 53 | while (psz < pszEnd) 54 | { 55 | int ret = send(hSocket, psz, pszEnd - psz, 0); 56 | if (ret < 0) 57 | return false; 58 | psz += ret; 59 | } 60 | return true; 61 | } 62 | 63 | bool RecvLine(SOCKET hSocket, string& strLine) 64 | { 65 | strLine = ""; 66 | loop 67 | { 68 | char c; 69 | int nBytes = recv(hSocket, &c, 1, 0); 70 | if (nBytes > 0) 71 | { 72 | if (c == '\n') 73 | continue; 74 | if (c == '\r') 75 | return true; 76 | strLine += c; 77 | } 78 | else if (nBytes <= 0) 79 | { 80 | if (!strLine.empty()) 81 | return true; 82 | // socket closed 83 | printf("IRC socket closed\n"); 84 | return false; 85 | } 86 | else 87 | { 88 | // socket error 89 | int nErr = WSAGetLastError(); 90 | if (nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS) 91 | { 92 | printf("IRC recv failed: %d\n", nErr); 93 | return false; 94 | } 95 | } 96 | } 97 | } 98 | 99 | bool RecvLineIRC(SOCKET hSocket, string& strLine) 100 | { 101 | loop 102 | { 103 | bool fRet = RecvLine(hSocket, strLine); 104 | if (fRet) 105 | { 106 | if (fShutdown) 107 | return false; 108 | vector vWords; 109 | ParseString(strLine, ' ', vWords); 110 | if (vWords[0] == "PING") 111 | { 112 | strLine[1] = 'O'; 113 | strLine += '\r'; 114 | Send(hSocket, strLine.c_str()); 115 | continue; 116 | } 117 | } 118 | return fRet; 119 | } 120 | } 121 | 122 | bool RecvUntil(SOCKET hSocket, const char* psz1, const char* psz2=NULL, const char* psz3=NULL) 123 | { 124 | loop 125 | { 126 | string strLine; 127 | if (!RecvLineIRC(hSocket, strLine)) 128 | return false; 129 | printf("IRC %s\n", strLine.c_str()); 130 | if (psz1 && strLine.find(psz1) != -1) 131 | return true; 132 | if (psz2 && strLine.find(psz2) != -1) 133 | return true; 134 | if (psz3 && strLine.find(psz3) != -1) 135 | return true; 136 | } 137 | } 138 | 139 | bool Wait(int nSeconds) 140 | { 141 | if (fShutdown) 142 | return false; 143 | printf("Waiting %d seconds to reconnect to IRC\n", nSeconds); 144 | for (int i = 0; i < nSeconds; i++) 145 | { 146 | if (fShutdown) 147 | return false; 148 | Sleep(1000); 149 | } 150 | return true; 151 | } 152 | 153 | 154 | 155 | void ThreadIRCSeed(void* parg) 156 | { 157 | SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL); 158 | int nErrorWait = 30; 159 | int nRetryWait = 10; 160 | 161 | 162 | while (!fShutdown) 163 | { 164 | struct hostent* phostent = gethostbyname("chat.freenode.net"); 165 | CAddress addrConnect(*(u_long*)phostent->h_addr_list[0], htons(6667)); 166 | 167 | SOCKET hSocket; 168 | if (!ConnectSocket(addrConnect, hSocket)) 169 | { 170 | printf("IRC connect failed\n"); 171 | if (Wait(nErrorWait += 60)) 172 | continue; 173 | else 174 | return; 175 | } 176 | 177 | if (!RecvUntil(hSocket, "Found your hostname", "using your IP address instead", "Couldn't look up your hostname")) 178 | { 179 | closesocket(hSocket); 180 | if (Wait(nErrorWait += 60)) 181 | continue; 182 | else 183 | return; 184 | } 185 | 186 | string strMyName = EncodeAddress(addrLocalHost); 187 | 188 | if (!addrLocalHost.IsRoutable()) 189 | strMyName = strprintf("x%u", GetRand(1000000000)); 190 | 191 | 192 | Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str()); 193 | Send(hSocket, strprintf("USER %s 8 * : %s\r", strMyName.c_str(), strMyName.c_str()).c_str()); 194 | 195 | if (!RecvUntil(hSocket, " 004 ")) 196 | { 197 | closesocket(hSocket); 198 | if (Wait(nErrorWait += 60)) 199 | continue; 200 | else 201 | return; 202 | } 203 | Sleep(500); 204 | 205 | Send(hSocket, "JOIN #bitcoin\r"); 206 | Send(hSocket, "WHO #bitcoin\r"); 207 | 208 | string strLine; 209 | while (!fShutdown && RecvLineIRC(hSocket, strLine)) 210 | { 211 | if (strLine.empty() || strLine.size() > 900 || strLine[0] != ':') 212 | continue; 213 | printf("IRC %s\n", strLine.c_str()); 214 | 215 | vector vWords; 216 | ParseString(strLine, ' ', vWords); 217 | if (vWords.size() < 2) 218 | continue; 219 | 220 | char pszName[10000]; 221 | pszName[0] = '\0'; 222 | 223 | if (vWords[1] == "352" && vWords.size() >= 8) 224 | { 225 | // index 7 is limited to 16 characters 226 | // could get full length name at index 10, but would be different from join messages 227 | strcpy(pszName, vWords[7].c_str()); 228 | printf("GOT WHO: [%s] ", pszName); 229 | } 230 | 231 | if (vWords[1] == "JOIN" && vWords[0].size() > 1) 232 | { 233 | // :username!username@50000007.F000000B.90000002.IP JOIN :#channelname 234 | strcpy(pszName, vWords[0].c_str() + 1); 235 | if (strchr(pszName, '!')) 236 | *strchr(pszName, '!') = '\0'; 237 | printf("GOT JOIN: [%s] ", pszName); 238 | } 239 | 240 | if (pszName[0] == 'u') 241 | { 242 | CAddress addr; 243 | if (DecodeAddress(pszName, addr)) 244 | { 245 | CAddrDB addrdb; 246 | if (AddAddress(addrdb, addr)) 247 | printf("new "); 248 | addr.print(); 249 | } 250 | else 251 | { 252 | printf("decode failed\n"); 253 | } 254 | } 255 | 256 | } 257 | closesocket(hSocket); 258 | 259 | if (!Wait(nRetryWait += 10)) 260 | return; 261 | } 262 | } 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | #ifdef TEST 274 | int main(int argc, char *argv[]) 275 | { 276 | WSADATA wsadata; 277 | if (WSAStartup(MAKEWORD(2,2), &wsadata) != NO_ERROR) 278 | { 279 | printf("Error at WSAStartup()\n"); 280 | return false; 281 | } 282 | 283 | ThreadIRCSeed(NULL); 284 | 285 | WSACleanup(); 286 | return 0; 287 | } 288 | #endif 289 | -------------------------------------------------------------------------------- /src/irc.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 Satoshi Nakamoto 2 | // Distributed under the MIT/X11 software license, see the accompanying 3 | // file license.txt or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | extern bool RecvLine(SOCKET hSocket, string& strLine); 6 | extern void ThreadIRCSeed(void* parg); 7 | extern bool fRestartIRCSeed; 8 | -------------------------------------------------------------------------------- /src/key.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 Satoshi Nakamoto 2 | // Distributed under the MIT/X11 software license, see the accompanying 3 | // file license.txt or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | 6 | // secp160k1 7 | // const unsigned int PRIVATE_KEY_SIZE = 192; 8 | // const unsigned int PUBLIC_KEY_SIZE = 41; 9 | // const unsigned int SIGNATURE_SIZE = 48; 10 | // 11 | // secp192k1 12 | // const unsigned int PRIVATE_KEY_SIZE = 222; 13 | // const unsigned int PUBLIC_KEY_SIZE = 49; 14 | // const unsigned int SIGNATURE_SIZE = 57; 15 | // 16 | // secp224k1 17 | // const unsigned int PRIVATE_KEY_SIZE = 250; 18 | // const unsigned int PUBLIC_KEY_SIZE = 57; 19 | // const unsigned int SIGNATURE_SIZE = 66; 20 | // 21 | // secp256k1: 22 | // const unsigned int PRIVATE_KEY_SIZE = 279; 23 | // const unsigned int PUBLIC_KEY_SIZE = 65; 24 | // const unsigned int SIGNATURE_SIZE = 72; 25 | // 26 | // see www.keylength.com 27 | // script supports up to 75 for single byte push 28 | 29 | 30 | 31 | class key_error : public std::runtime_error 32 | { 33 | public: 34 | explicit key_error(const std::string& str) : std::runtime_error(str) {} 35 | }; 36 | 37 | 38 | // secure_allocator is defined is serialize.h 39 | typedef vector > CPrivKey; 40 | 41 | 42 | 43 | class CKey 44 | { 45 | protected: 46 | EC_KEY* pkey; 47 | 48 | public: 49 | CKey() 50 | { 51 | pkey = EC_KEY_new_by_curve_name(NID_secp256k1); 52 | if (pkey == NULL) 53 | throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed"); 54 | } 55 | 56 | CKey(const CKey& b) 57 | { 58 | pkey = EC_KEY_dup(b.pkey); 59 | if (pkey == NULL) 60 | throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed"); 61 | } 62 | 63 | CKey& operator=(const CKey& b) 64 | { 65 | if (!EC_KEY_copy(pkey, b.pkey)) 66 | throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed"); 67 | return (*this); 68 | } 69 | 70 | ~CKey() 71 | { 72 | EC_KEY_free(pkey); 73 | } 74 | 75 | void MakeNewKey() 76 | { 77 | if (!EC_KEY_generate_key(pkey)) 78 | throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed"); 79 | } 80 | 81 | bool SetPrivKey(const CPrivKey& vchPrivKey) 82 | { 83 | const unsigned char* pbegin = &vchPrivKey[0]; 84 | if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size())) 85 | return false; 86 | return true; 87 | } 88 | 89 | CPrivKey GetPrivKey() const 90 | { 91 | unsigned int nSize = i2d_ECPrivateKey(pkey, NULL); 92 | if (!nSize) 93 | throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed"); 94 | CPrivKey vchPrivKey(nSize, 0); 95 | unsigned char* pbegin = &vchPrivKey[0]; 96 | if (i2d_ECPrivateKey(pkey, &pbegin) != nSize) 97 | throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size"); 98 | return vchPrivKey; 99 | } 100 | 101 | bool SetPubKey(const vector& vchPubKey) 102 | { 103 | const unsigned char* pbegin = &vchPubKey[0]; 104 | if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size())) 105 | return false; 106 | return true; 107 | } 108 | 109 | vector GetPubKey() const 110 | { 111 | unsigned int nSize = i2o_ECPublicKey(pkey, NULL); 112 | if (!nSize) 113 | throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed"); 114 | vector vchPubKey(nSize, 0); 115 | unsigned char* pbegin = &vchPubKey[0]; 116 | if (i2o_ECPublicKey(pkey, &pbegin) != nSize) 117 | throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size"); 118 | return vchPubKey; 119 | } 120 | 121 | bool Sign(uint256 hash, vector& vchSig) 122 | { 123 | vchSig.clear(); 124 | unsigned char pchSig[10000]; 125 | unsigned int nSize = 0; 126 | if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), pchSig, &nSize, pkey)) 127 | return false; 128 | vchSig.resize(nSize); 129 | memcpy(&vchSig[0], pchSig, nSize); 130 | return true; 131 | } 132 | 133 | bool Verify(uint256 hash, const vector& vchSig) 134 | { 135 | // -1 = error, 0 = bad sig, 1 = good 136 | if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1) 137 | return false; 138 | return true; 139 | } 140 | 141 | static bool Sign(const CPrivKey& vchPrivKey, uint256 hash, vector& vchSig) 142 | { 143 | CKey key; 144 | if (!key.SetPrivKey(vchPrivKey)) 145 | return false; 146 | return key.Sign(hash, vchSig); 147 | } 148 | 149 | static bool Verify(const vector& vchPubKey, uint256 hash, const vector& vchSig) 150 | { 151 | CKey key; 152 | if (!key.SetPubKey(vchPubKey)) 153 | return false; 154 | return key.Verify(hash, vchSig); 155 | } 156 | }; 157 | -------------------------------------------------------------------------------- /src/license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 Satoshi Nakamoto 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /src/makefile: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2009 Satoshi Nakamoto 2 | # Distributed under the MIT/X11 software license, see the accompanying 3 | # file license.txt or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | 6 | ifneq "$(BUILD)" "debug" 7 | ifneq "$(BUILD)" "release" 8 | BUILD=debug 9 | endif 10 | endif 11 | ifeq "$(BUILD)" "debug" 12 | D=d 13 | # note: gcc 3.x profile doesn't work 14 | #DEBUGFLAGS=-O0 -g -pg -D__WXDEBUG__ 15 | DEBUGFLAGS=-g -D__WXDEBUG__ 16 | endif 17 | 18 | 19 | 20 | INCLUDEPATHS=-I"/boost" -I"/DB/build_unix" -I"/OpenSSL/include" -I"/wxWidgets/lib/vc_lib/mswd" -I"/wxWidgets/include" 21 | LIBPATHS=-L"/DB/build_unix" -L"/OpenSSL/out" -L"/wxWidgets/lib/gcc_lib" 22 | LIBS= \ 23 | -l db_cxx \ 24 | -l eay32 \ 25 | -l wxmsw28$(D)_richtext -l wxmsw28$(D)_html -l wxmsw28$(D)_core -l wxbase28$(D) -l wxtiff$(D) -l wxjpeg$(D) -l wxpng$(D) -l wxzlib$(D) -l wxregex$(D) -l wxexpat$(D) \ 26 | -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 27 | WXDEFS=-DWIN32 -D__WXMSW__ -D_WINDOWS -DNOPCH 28 | CFLAGS=-mthreads -O0 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS) 29 | HEADERS=headers.h util.h main.h serialize.h uint256.h key.h bignum.h script.h db.h base58.h 30 | 31 | 32 | 33 | all: bitcoin.exe 34 | 35 | 36 | headers.h.gch: headers.h $(HEADERS) net.h irc.h market.h uibase.h ui.h 37 | g++ -c $(CFLAGS) -o $@ $< 38 | 39 | obj/util.o: util.cpp $(HEADERS) 40 | g++ -c $(CFLAGS) -o $@ $< 41 | 42 | obj/script.o: script.cpp $(HEADERS) 43 | g++ -c $(CFLAGS) -o $@ $< 44 | 45 | obj/db.o: db.cpp $(HEADERS) market.h 46 | g++ -c $(CFLAGS) -o $@ $< 47 | 48 | obj/net.o: net.cpp $(HEADERS) net.h 49 | g++ -c $(CFLAGS) -o $@ $< 50 | 51 | obj/main.o: main.cpp $(HEADERS) net.h market.h sha.h 52 | g++ -c $(CFLAGS) -o $@ $< 53 | 54 | obj/market.o: market.cpp $(HEADERS) market.h 55 | g++ -c $(CFLAGS) -o $@ $< 56 | 57 | obj/ui.o: ui.cpp $(HEADERS) net.h uibase.h ui.h market.h 58 | g++ -c $(CFLAGS) -o $@ $< 59 | 60 | obj/uibase.o: uibase.cpp uibase.h 61 | g++ -c $(CFLAGS) -o $@ $< 62 | 63 | obj/sha.o: sha.cpp sha.h 64 | g++ -c $(CFLAGS) -O3 -o $@ $< 65 | 66 | obj/irc.o: irc.cpp $(HEADERS) 67 | g++ -c $(CFLAGS) -o $@ $< 68 | 69 | obj/ui_res.o: ui.rc rc/bitcoin.ico rc/check.ico rc/send16.bmp rc/send16mask.bmp rc/send16masknoshadow.bmp rc/send20.bmp rc/send20mask.bmp rc/addressbook16.bmp rc/addressbook16mask.bmp rc/addressbook20.bmp rc/addressbook20mask.bmp 70 | windres $(WXDEFS) $(INCLUDEPATHS) -o $@ -i $< 71 | 72 | 73 | 74 | OBJS=obj/util.o obj/script.o obj/db.o obj/net.o obj/main.o obj/market.o \ 75 | obj/ui.o obj/uibase.o obj/sha.o obj/irc.o obj/ui_res.o 76 | 77 | bitcoin.exe: headers.h.gch $(OBJS) 78 | -kill /f bitcoin.exe 79 | g++ $(CFLAGS) -mwindows -Wl,--subsystem,windows -o $@ $(LIBPATHS) $(OBJS) $(LIBS) 80 | 81 | clean: 82 | -del /Q obj\* 83 | -del /Q headers.h.gch 84 | -------------------------------------------------------------------------------- /src/makefile.vc: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2009 Satoshi Nakamoto 2 | # Distributed under the MIT/X11 software license, see the accompanying 3 | # file license.txt or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | 6 | !IF "$(BUILD)" != "debug" && "$(BUILD)" != "release" 7 | BUILD=debug 8 | !ENDIF 9 | !IF "$(BUILD)" == "debug" 10 | D=d 11 | DEBUGFLAGS=/Zi /Od /D__WXDEBUG__ 12 | !ENDIF 13 | 14 | 15 | 16 | INCLUDEPATHS=/I"/boost" /I"/DB/build_windows" /I"/OpenSSL/include" /I"/wxWidgets/lib/vc_lib/mswd" /I"/wxWidgets/include" 17 | LIBPATHS=/LIBPATH:"/DB/build_windows/$(BUILD)" /LIBPATH:"/OpenSSL/out" /LIBPATH:"/wxWidgets/lib/vc_lib" 18 | LIBS= \ 19 | libdb47s$(D).lib \ 20 | libeay32.lib \ 21 | wxmsw28$(D)_richtext.lib wxmsw28$(D)_html.lib wxmsw28$(D)_core.lib wxbase28$(D).lib wxtiff$(D).lib wxjpeg$(D).lib wxpng$(D).lib wxzlib$(D).lib wxregex$(D).lib wxexpat$(D).lib \ 22 | kernel32.lib user32.lib gdi32.lib comdlg32.lib winspool.lib winmm.lib shell32.lib comctl32.lib ole32.lib oleaut32.lib uuid.lib rpcrt4.lib advapi32.lib ws2_32.lib 23 | WXDEFS=/DWIN32 /D__WXMSW__ /D_WINDOWS /DNOPCH 24 | CFLAGS=/c /nologo /Ob0 /MD$(D) /EHsc /GR /Zm300 /YX /Fpobj/headers.pch $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS) 25 | HEADERS=headers.h util.h main.h serialize.h uint256.h key.h bignum.h script.h db.h base58.h 26 | 27 | 28 | 29 | all: bitcoin.exe 30 | 31 | 32 | obj\util.obj: util.cpp $(HEADERS) 33 | cl $(CFLAGS) /Fo$@ %s 34 | 35 | obj\script.obj: script.cpp $(HEADERS) 36 | cl $(CFLAGS) /Fo$@ %s 37 | 38 | obj\db.obj: db.cpp $(HEADERS) market.h 39 | cl $(CFLAGS) /Fo$@ %s 40 | 41 | obj\net.obj: net.cpp $(HEADERS) net.h 42 | cl $(CFLAGS) /Fo$@ %s 43 | 44 | obj\main.obj: main.cpp $(HEADERS) net.h market.h 45 | cl $(CFLAGS) /Fo$@ %s 46 | 47 | obj\market.obj: market.cpp $(HEADERS) market.h 48 | cl $(CFLAGS) /Fo$@ %s 49 | 50 | obj\ui.obj: ui.cpp $(HEADERS) net.h uibase.h ui.h market.h 51 | cl $(CFLAGS) /Fo$@ %s 52 | 53 | obj\uibase.obj: uibase.cpp uibase.h 54 | cl $(CFLAGS) /Fo$@ %s 55 | 56 | obj\sha.obj: sha.cpp sha.h 57 | cl $(CFLAGS) /O2 /Fo$@ %s 58 | 59 | obj\irc.obj: irc.cpp $(HEADERS) 60 | cl $(CFLAGS) /Fo$@ %s 61 | 62 | obj\ui.res: ui.rc rc/bitcoin.ico rc/check.ico rc/send16.bmp rc/send16mask.bmp rc/send16masknoshadow.bmp rc/send20.bmp rc/send20mask.bmp rc/addressbook16.bmp rc/addressbook16mask.bmp rc/addressbook20.bmp rc/addressbook20mask.bmp 63 | rc $(INCLUDEPATHS) $(WXDEFS) /Fo$@ %s 64 | 65 | 66 | 67 | OBJS=obj\util.obj obj\script.obj obj\db.obj obj\net.obj obj\main.obj obj\market.obj \ 68 | obj\ui.obj obj\uibase.obj obj\sha.obj obj\irc.obj obj\ui.res 69 | 70 | bitcoin.exe: $(OBJS) 71 | -kill /f bitcoin.exe & sleep 1 72 | link /nologo /DEBUG /SUBSYSTEM:WINDOWS /OUT:$@ $(LIBPATHS) $** $(LIBS) 73 | 74 | clean: 75 | -del /Q obj\* 76 | -del *.ilk 77 | -del *.pdb 78 | -------------------------------------------------------------------------------- /src/market.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 Satoshi Nakamoto 2 | // Distributed under the MIT/X11 software license, see the accompanying 3 | // file license.txt or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "headers.h" 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | // 17 | // Global state variables 18 | // 19 | 20 | //// later figure out how these are persisted 21 | map mapMyProducts; 22 | 23 | 24 | 25 | 26 | map mapProducts; 27 | CCriticalSection cs_mapProducts; 28 | 29 | bool AdvertInsert(const CProduct& product) 30 | { 31 | uint256 hash = product.GetHash(); 32 | bool fNew = false; 33 | bool fUpdated = false; 34 | 35 | CRITICAL_BLOCK(cs_mapProducts) 36 | { 37 | // Insert or find existing product 38 | pair::iterator, bool> item = mapProducts.insert(make_pair(hash, product)); 39 | CProduct* pproduct = &(*(item.first)).second; 40 | fNew = item.second; 41 | 42 | // Update if newer 43 | if (product.nSequence > pproduct->nSequence) 44 | { 45 | *pproduct = product; 46 | fUpdated = true; 47 | } 48 | } 49 | 50 | //if (fNew) 51 | // NotifyProductAdded(hash); 52 | //else if (fUpdated) 53 | // NotifyProductUpdated(hash); 54 | 55 | return (fNew || fUpdated); 56 | } 57 | 58 | void AdvertErase(const CProduct& product) 59 | { 60 | uint256 hash = product.GetHash(); 61 | CRITICAL_BLOCK(cs_mapProducts) 62 | mapProducts.erase(hash); 63 | //NotifyProductDeleted(hash); 64 | } 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | template 85 | unsigned int Union(T& v1, T& v2) 86 | { 87 | // v1 = v1 union v2 88 | // v1 and v2 must be sorted 89 | // returns the number of elements added to v1 90 | 91 | ///// need to check that this is equivalent, then delete this comment 92 | //vector vUnion(v1.size() + v2.size()); 93 | //vUnion.erase(set_union(v1.begin(), v1.end(), 94 | // v2.begin(), v2.end(), 95 | // vUnion.begin()), 96 | // vUnion.end()); 97 | 98 | T vUnion; 99 | vUnion.reserve(v1.size() + v2.size()); 100 | set_union(v1.begin(), v1.end(), 101 | v2.begin(), v2.end(), 102 | back_inserter(vUnion)); 103 | unsigned int nAdded = vUnion.size() - v1.size(); 104 | if (nAdded > 0) 105 | v1 = vUnion; 106 | return nAdded; 107 | } 108 | 109 | void CUser::AddAtom(unsigned short nAtom, bool fOrigin) 110 | { 111 | // Ignore duplicates 112 | if (binary_search(vAtomsIn.begin(), vAtomsIn.end(), nAtom) || 113 | find(vAtomsNew.begin(), vAtomsNew.end(), nAtom) != vAtomsNew.end()) 114 | return; 115 | 116 | //// instead of zero atom, should change to free atom that propagates, 117 | //// limited to lower than a certain value like 5 so conflicts quickly 118 | // The zero atom never propagates, 119 | // new atoms always propagate through the user that created them 120 | if (nAtom == 0 || fOrigin) 121 | { 122 | vector vTmp(1, nAtom); 123 | Union(vAtomsIn, vTmp); 124 | if (fOrigin) 125 | vAtomsOut.push_back(nAtom); 126 | return; 127 | } 128 | 129 | vAtomsNew.push_back(nAtom); 130 | 131 | if (vAtomsNew.size() >= nFlowthroughRate || vAtomsOut.empty()) 132 | { 133 | // Select atom to flow through to vAtomsOut 134 | vAtomsOut.push_back(vAtomsNew[GetRand(vAtomsNew.size())]); 135 | 136 | // Merge vAtomsNew into vAtomsIn 137 | sort(vAtomsNew.begin(), vAtomsNew.end()); 138 | Union(vAtomsIn, vAtomsNew); 139 | vAtomsNew.clear(); 140 | } 141 | } 142 | 143 | bool AddAtomsAndPropagate(uint256 hashUserStart, const vector& vAtoms, bool fOrigin) 144 | { 145 | CReviewDB reviewdb; 146 | map > pmapPropagate[2]; 147 | pmapPropagate[0][hashUserStart] = vAtoms; 148 | 149 | for (int side = 0; !pmapPropagate[side].empty(); side = 1 - side) 150 | { 151 | map >& mapFrom = pmapPropagate[side]; 152 | map >& mapTo = pmapPropagate[1 - side]; 153 | 154 | for (map >::iterator mi = mapFrom.begin(); mi != mapFrom.end(); ++mi) 155 | { 156 | const uint256& hashUser = (*mi).first; 157 | const vector& vReceived = (*mi).second; 158 | 159 | ///// this would be a lot easier on the database if it put the new atom at the beginning of the list, 160 | ///// so the change would be right next to the vector size. 161 | 162 | // Read user 163 | CUser user; 164 | reviewdb.ReadUser(hashUser, user); 165 | unsigned int nIn = user.vAtomsIn.size(); 166 | unsigned int nNew = user.vAtomsNew.size(); 167 | unsigned int nOut = user.vAtomsOut.size(); 168 | 169 | // Add atoms received 170 | foreach(unsigned short nAtom, vReceived) 171 | user.AddAtom(nAtom, fOrigin); 172 | fOrigin = false; 173 | 174 | // Don't bother writing to disk if no changes 175 | if (user.vAtomsIn.size() == nIn && user.vAtomsNew.size() == nNew) 176 | continue; 177 | 178 | // Propagate 179 | if (user.vAtomsOut.size() > nOut) 180 | foreach(const uint256& hash, user.vLinksOut) 181 | mapTo[hash].insert(mapTo[hash].end(), user.vAtomsOut.begin() + nOut, user.vAtomsOut.end()); 182 | 183 | // Write back 184 | if (!reviewdb.WriteUser(hashUser, user)) 185 | return false; 186 | } 187 | mapFrom.clear(); 188 | } 189 | return true; 190 | } 191 | 192 | 193 | 194 | 195 | 196 | 197 | bool CReview::AcceptReview() 198 | { 199 | // Timestamp 200 | nTime = GetTime(); 201 | 202 | // Check signature 203 | if (!CKey::Verify(vchPubKeyFrom, GetSigHash(), vchSig)) 204 | return false; 205 | 206 | CReviewDB reviewdb; 207 | 208 | // Add review text to recipient 209 | vector vReviews; 210 | reviewdb.ReadReviews(hashTo, vReviews); 211 | vReviews.push_back(*this); 212 | if (!reviewdb.WriteReviews(hashTo, vReviews)) 213 | return false; 214 | 215 | // Add link from sender 216 | CUser user; 217 | uint256 hashFrom = Hash(vchPubKeyFrom.begin(), vchPubKeyFrom.end()); 218 | reviewdb.ReadUser(hashFrom, user); 219 | user.vLinksOut.push_back(hashTo); 220 | if (!reviewdb.WriteUser(hashFrom, user)) 221 | return false; 222 | 223 | reviewdb.Close(); 224 | 225 | // Propagate atoms to recipient 226 | vector vZeroAtom(1, 0); 227 | if (!AddAtomsAndPropagate(hashTo, user.vAtomsOut.size() ? user.vAtomsOut : vZeroAtom, false)) 228 | return false; 229 | 230 | return true; 231 | } 232 | 233 | 234 | 235 | 236 | 237 | bool CProduct::CheckSignature() 238 | { 239 | return (CKey::Verify(vchPubKeyFrom, GetSigHash(), vchSig)); 240 | } 241 | 242 | bool CProduct::CheckProduct() 243 | { 244 | if (!CheckSignature()) 245 | return false; 246 | 247 | // Make sure it's a summary product 248 | if (!mapDetails.empty() || !vOrderForm.empty()) 249 | return false; 250 | 251 | // Look up seller's atom count 252 | CReviewDB reviewdb("r"); 253 | CUser user; 254 | reviewdb.ReadUser(GetUserHash(), user); 255 | nAtoms = user.GetAtomCount(); 256 | reviewdb.Close(); 257 | 258 | ////// delme, this is now done by AdvertInsert 259 | //// Store to memory 260 | //CRITICAL_BLOCK(cs_mapProducts) 261 | // mapProducts[GetHash()] = *this; 262 | 263 | return true; 264 | } 265 | -------------------------------------------------------------------------------- /src/market.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 Satoshi Nakamoto 2 | // Distributed under the MIT/X11 software license, see the accompanying 3 | // file license.txt or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | class CUser; 6 | class CReview; 7 | class CProduct; 8 | 9 | static const unsigned int nFlowthroughRate = 2; 10 | 11 | 12 | 13 | 14 | bool AdvertInsert(const CProduct& product); 15 | void AdvertErase(const CProduct& product); 16 | bool AddAtomsAndPropagate(uint256 hashUserStart, const vector& vAtoms, bool fOrigin); 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | class CUser 26 | { 27 | public: 28 | vector vAtomsIn; 29 | vector vAtomsNew; 30 | vector vAtomsOut; 31 | vector vLinksOut; 32 | 33 | CUser() 34 | { 35 | } 36 | 37 | IMPLEMENT_SERIALIZE 38 | ( 39 | if (!(nType & SER_GETHASH)) 40 | READWRITE(nVersion); 41 | READWRITE(vAtomsIn); 42 | READWRITE(vAtomsNew); 43 | READWRITE(vAtomsOut); 44 | READWRITE(vLinksOut); 45 | ) 46 | 47 | void SetNull() 48 | { 49 | vAtomsIn.clear(); 50 | vAtomsNew.clear(); 51 | vAtomsOut.clear(); 52 | vLinksOut.clear(); 53 | } 54 | 55 | uint256 GetHash() const { return SerializeHash(*this); } 56 | 57 | 58 | int GetAtomCount() const 59 | { 60 | return (vAtomsIn.size() + vAtomsNew.size()); 61 | } 62 | 63 | void AddAtom(unsigned short nAtom, bool fOrigin); 64 | }; 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | class CReview 73 | { 74 | public: 75 | int nVersion; 76 | uint256 hashTo; 77 | map mapValue; 78 | vector vchPubKeyFrom; 79 | vector vchSig; 80 | 81 | // memory only 82 | unsigned int nTime; 83 | int nAtoms; 84 | 85 | 86 | CReview() 87 | { 88 | nVersion = 1; 89 | hashTo = 0; 90 | nTime = 0; 91 | nAtoms = 0; 92 | } 93 | 94 | IMPLEMENT_SERIALIZE 95 | ( 96 | READWRITE(this->nVersion); 97 | nVersion = this->nVersion; 98 | if (!(nType & SER_DISK)) 99 | READWRITE(hashTo); 100 | READWRITE(mapValue); 101 | READWRITE(vchPubKeyFrom); 102 | if (!(nType & SER_GETHASH)) 103 | READWRITE(vchSig); 104 | ) 105 | 106 | uint256 GetHash() const { return SerializeHash(*this); } 107 | uint256 GetSigHash() const { return SerializeHash(*this, SER_GETHASH|SER_SKIPSIG); } 108 | uint256 GetUserHash() const { return Hash(vchPubKeyFrom.begin(), vchPubKeyFrom.end()); } 109 | 110 | 111 | bool AcceptReview(); 112 | }; 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | class CProduct 121 | { 122 | public: 123 | int nVersion; 124 | CAddress addr; 125 | map mapValue; 126 | map mapDetails; 127 | vector > vOrderForm; 128 | unsigned int nSequence; 129 | vector vchPubKeyFrom; 130 | vector vchSig; 131 | 132 | // disk only 133 | int nAtoms; 134 | 135 | // memory only 136 | set setSources; 137 | 138 | CProduct() 139 | { 140 | nVersion = 1; 141 | nAtoms = 0; 142 | nSequence = 0; 143 | } 144 | 145 | IMPLEMENT_SERIALIZE 146 | ( 147 | READWRITE(this->nVersion); 148 | nVersion = this->nVersion; 149 | READWRITE(addr); 150 | READWRITE(mapValue); 151 | if (!(nType & SER_GETHASH)) 152 | { 153 | READWRITE(mapDetails); 154 | READWRITE(vOrderForm); 155 | READWRITE(nSequence); 156 | } 157 | READWRITE(vchPubKeyFrom); 158 | if (!(nType & SER_GETHASH)) 159 | READWRITE(vchSig); 160 | if (nType & SER_DISK) 161 | READWRITE(nAtoms); 162 | ) 163 | 164 | uint256 GetHash() const { return SerializeHash(*this); } 165 | uint256 GetSigHash() const { return SerializeHash(*this, SER_GETHASH|SER_SKIPSIG); } 166 | uint256 GetUserHash() const { return Hash(vchPubKeyFrom.begin(), vchPubKeyFrom.end()); } 167 | 168 | 169 | bool CheckSignature(); 170 | bool CheckProduct(); 171 | }; 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | extern map mapProducts; 181 | extern CCriticalSection cs_mapProducts; 182 | extern map mapMyProducts; 183 | -------------------------------------------------------------------------------- /src/net.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 Satoshi Nakamoto 2 | // Distributed under the MIT/X11 software license, see the accompanying 3 | // file license.txt or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | class CMessageHeader; 6 | class CAddress; 7 | class CInv; 8 | class CRequestTracker; 9 | class CNode; 10 | 11 | 12 | 13 | static const unsigned short DEFAULT_PORT = htons(8333); 14 | static const unsigned int PUBLISH_HOPS = 5; 15 | enum 16 | { 17 | NODE_NETWORK = (1 << 0), 18 | }; 19 | 20 | 21 | 22 | 23 | 24 | 25 | bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet); 26 | bool GetMyExternalIP(unsigned int& ipRet); 27 | bool AddAddress(CAddrDB& addrdb, const CAddress& addr); 28 | CNode* FindNode(unsigned int ip); 29 | CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0); 30 | void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1); 31 | bool AnySubscribed(unsigned int nChannel); 32 | void ThreadBitcoinMiner(void* parg); 33 | bool StartNode(string& strError=REF(string())); 34 | bool StopNode(); 35 | void CheckForShutdown(int n); 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | // 46 | // Message header 47 | // (4) message start 48 | // (12) command 49 | // (4) size 50 | 51 | // The message start string is designed to be unlikely to occur in normal data. 52 | // The characters are rarely used upper ascii, not valid as UTF-8, and produce 53 | // a large 4-byte int at any alignment. 54 | static const char pchMessageStart[4] = { 0xf9, 0xbe, 0xb4, 0xd9 }; 55 | 56 | class CMessageHeader 57 | { 58 | public: 59 | enum { COMMAND_SIZE=12 }; 60 | char pchMessageStart[sizeof(::pchMessageStart)]; 61 | char pchCommand[COMMAND_SIZE]; 62 | unsigned int nMessageSize; 63 | 64 | CMessageHeader() 65 | { 66 | memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart)); 67 | memset(pchCommand, 0, sizeof(pchCommand)); 68 | pchCommand[1] = 1; 69 | nMessageSize = -1; 70 | } 71 | 72 | CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn) 73 | { 74 | memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart)); 75 | strncpy(pchCommand, pszCommand, COMMAND_SIZE); 76 | nMessageSize = nMessageSizeIn; 77 | } 78 | 79 | IMPLEMENT_SERIALIZE 80 | ( 81 | READWRITE(FLATDATA(pchMessageStart)); 82 | READWRITE(FLATDATA(pchCommand)); 83 | READWRITE(nMessageSize); 84 | ) 85 | 86 | string GetCommand() 87 | { 88 | if (pchCommand[COMMAND_SIZE-1] == 0) 89 | return string(pchCommand, pchCommand + strlen(pchCommand)); 90 | else 91 | return string(pchCommand, pchCommand + COMMAND_SIZE); 92 | } 93 | 94 | bool IsValid() 95 | { 96 | // Check start string 97 | if (memcmp(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart)) != 0) 98 | return false; 99 | 100 | // Check the command string for errors 101 | for (char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; p1++) 102 | { 103 | if (*p1 == 0) 104 | { 105 | // Must be all zeros after the first zero 106 | for (; p1 < pchCommand + COMMAND_SIZE; p1++) 107 | if (*p1 != 0) 108 | return false; 109 | } 110 | else if (*p1 < ' ' || *p1 > 0x7E) 111 | return false; 112 | } 113 | 114 | // Message size 115 | if (nMessageSize > 0x10000000) 116 | { 117 | printf("CMessageHeader::IsValid() : nMessageSize too large %u\n", nMessageSize); 118 | return false; 119 | } 120 | 121 | return true; 122 | } 123 | }; 124 | 125 | 126 | 127 | 128 | 129 | 130 | static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff }; 131 | 132 | class CAddress 133 | { 134 | public: 135 | uint64 nServices; 136 | unsigned char pchReserved[12]; 137 | unsigned int ip; 138 | unsigned short port; 139 | 140 | // disk only 141 | unsigned int nTime; 142 | 143 | // memory only 144 | unsigned int nLastFailed; 145 | 146 | CAddress() 147 | { 148 | nServices = 0; 149 | memcpy(pchReserved, pchIPv4, sizeof(pchReserved)); 150 | ip = 0; 151 | port = DEFAULT_PORT; 152 | nTime = GetAdjustedTime(); 153 | nLastFailed = 0; 154 | } 155 | 156 | CAddress(unsigned int ipIn, unsigned short portIn=DEFAULT_PORT, uint64 nServicesIn=0) 157 | { 158 | nServices = nServicesIn; 159 | memcpy(pchReserved, pchIPv4, sizeof(pchReserved)); 160 | ip = ipIn; 161 | port = portIn; 162 | nTime = GetAdjustedTime(); 163 | nLastFailed = 0; 164 | } 165 | 166 | explicit CAddress(const struct sockaddr_in& sockaddr, uint64 nServicesIn=0) 167 | { 168 | nServices = nServicesIn; 169 | memcpy(pchReserved, pchIPv4, sizeof(pchReserved)); 170 | ip = sockaddr.sin_addr.s_addr; 171 | port = sockaddr.sin_port; 172 | nTime = GetAdjustedTime(); 173 | nLastFailed = 0; 174 | } 175 | 176 | explicit CAddress(const char* pszIn, uint64 nServicesIn=0) 177 | { 178 | nServices = nServicesIn; 179 | memcpy(pchReserved, pchIPv4, sizeof(pchReserved)); 180 | ip = 0; 181 | port = DEFAULT_PORT; 182 | nTime = GetAdjustedTime(); 183 | nLastFailed = 0; 184 | 185 | char psz[100]; 186 | if (strlen(pszIn) > ARRAYLEN(psz)-1) 187 | return; 188 | strcpy(psz, pszIn); 189 | unsigned int a, b, c, d, e; 190 | if (sscanf(psz, "%u.%u.%u.%u:%u", &a, &b, &c, &d, &e) < 4) 191 | return; 192 | char* pszPort = strchr(psz, ':'); 193 | if (pszPort) 194 | { 195 | *pszPort++ = '\0'; 196 | port = htons(atoi(pszPort)); 197 | } 198 | ip = inet_addr(psz); 199 | } 200 | 201 | IMPLEMENT_SERIALIZE 202 | ( 203 | if (nType & SER_DISK) 204 | { 205 | READWRITE(nVersion); 206 | READWRITE(nTime); 207 | } 208 | READWRITE(nServices); 209 | READWRITE(FLATDATA(pchReserved)); 210 | READWRITE(ip); 211 | READWRITE(port); 212 | ) 213 | 214 | friend inline bool operator==(const CAddress& a, const CAddress& b) 215 | { 216 | return (memcmp(a.pchReserved, b.pchReserved, sizeof(a.pchReserved)) == 0 && 217 | a.ip == b.ip && 218 | a.port == b.port); 219 | } 220 | 221 | friend inline bool operator<(const CAddress& a, const CAddress& b) 222 | { 223 | int ret = memcmp(a.pchReserved, b.pchReserved, sizeof(a.pchReserved)); 224 | if (ret < 0) 225 | return true; 226 | else if (ret == 0) 227 | { 228 | if (ntohl(a.ip) < ntohl(b.ip)) 229 | return true; 230 | else if (a.ip == b.ip) 231 | return ntohs(a.port) < ntohs(b.port); 232 | } 233 | return false; 234 | } 235 | 236 | vector GetKey() const 237 | { 238 | CDataStream ss; 239 | ss.reserve(18); 240 | ss << FLATDATA(pchReserved) << ip << port; 241 | 242 | #if defined(_MSC_VER) && _MSC_VER < 1300 243 | return vector((unsigned char*)&ss.begin()[0], (unsigned char*)&ss.end()[0]); 244 | #else 245 | return vector(ss.begin(), ss.end()); 246 | #endif 247 | } 248 | 249 | struct sockaddr_in GetSockAddr() const 250 | { 251 | struct sockaddr_in sockaddr; 252 | sockaddr.sin_family = AF_INET; 253 | sockaddr.sin_addr.s_addr = ip; 254 | sockaddr.sin_port = port; 255 | return sockaddr; 256 | } 257 | 258 | bool IsIPv4() const 259 | { 260 | return (memcmp(pchReserved, pchIPv4, sizeof(pchIPv4)) == 0); 261 | } 262 | 263 | bool IsRoutable() const 264 | { 265 | return !(GetByte(3) == 10 || (GetByte(3) == 192 && GetByte(2) == 168) || GetByte(3) == 127 || GetByte(3) == 0); 266 | } 267 | 268 | unsigned char GetByte(int n) const 269 | { 270 | return ((unsigned char*)&ip)[3-n]; 271 | } 272 | 273 | string ToStringIPPort() const 274 | { 275 | return strprintf("%u.%u.%u.%u:%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0), ntohs(port)); 276 | } 277 | 278 | string ToStringIP() const 279 | { 280 | return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0)); 281 | } 282 | 283 | string ToString() const 284 | { 285 | return strprintf("%u.%u.%u.%u:%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0), ntohs(port)); 286 | //return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0)); 287 | } 288 | 289 | void print() const 290 | { 291 | printf("CAddress(%s)\n", ToString().c_str()); 292 | } 293 | }; 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | enum 302 | { 303 | MSG_TX = 1, 304 | MSG_BLOCK, 305 | MSG_REVIEW, 306 | MSG_PRODUCT, 307 | MSG_TABLE, 308 | }; 309 | 310 | static const char* ppszTypeName[] = 311 | { 312 | "ERROR", 313 | "tx", 314 | "block", 315 | "review", 316 | "product", 317 | "table", 318 | }; 319 | 320 | class CInv 321 | { 322 | public: 323 | int type; 324 | uint256 hash; 325 | 326 | CInv() 327 | { 328 | type = 0; 329 | hash = 0; 330 | } 331 | 332 | CInv(int typeIn, const uint256& hashIn) 333 | { 334 | type = typeIn; 335 | hash = hashIn; 336 | } 337 | 338 | CInv(const string& strType, const uint256& hashIn) 339 | { 340 | int i; 341 | for (i = 1; i < ARRAYLEN(ppszTypeName); i++) 342 | { 343 | if (strType == ppszTypeName[i]) 344 | { 345 | type = i; 346 | break; 347 | } 348 | } 349 | if (i == ARRAYLEN(ppszTypeName)) 350 | throw std::out_of_range(strprintf("CInv::CInv(string, uint256) : unknown type '%s'", strType.c_str())); 351 | hash = hashIn; 352 | } 353 | 354 | IMPLEMENT_SERIALIZE 355 | ( 356 | READWRITE(type); 357 | READWRITE(hash); 358 | ) 359 | 360 | friend inline bool operator<(const CInv& a, const CInv& b) 361 | { 362 | return (a.type < b.type || (a.type == b.type && a.hash < b.hash)); 363 | } 364 | 365 | bool IsKnownType() const 366 | { 367 | return (type >= 1 && type < ARRAYLEN(ppszTypeName)); 368 | } 369 | 370 | const char* GetCommand() const 371 | { 372 | if (!IsKnownType()) 373 | throw std::out_of_range(strprintf("CInv::GetCommand() : type=% unknown type", type)); 374 | return ppszTypeName[type]; 375 | } 376 | 377 | string ToString() const 378 | { 379 | return strprintf("%s %s", GetCommand(), hash.ToString().substr(0,14).c_str()); 380 | } 381 | 382 | void print() const 383 | { 384 | printf("CInv(%s)\n", ToString().c_str()); 385 | } 386 | }; 387 | 388 | 389 | 390 | 391 | 392 | class CRequestTracker 393 | { 394 | public: 395 | void (*fn)(void*, CDataStream&); 396 | void* param1; 397 | 398 | explicit CRequestTracker(void (*fnIn)(void*, CDataStream&)=NULL, void* param1In=NULL) 399 | { 400 | fn = fnIn; 401 | param1 = param1In; 402 | } 403 | 404 | bool IsNull() 405 | { 406 | return fn == NULL; 407 | } 408 | }; 409 | 410 | 411 | 412 | 413 | 414 | extern bool fClient; 415 | extern uint64 nLocalServices; 416 | extern CAddress addrLocalHost; 417 | extern CNode* pnodeLocalHost; 418 | extern bool fShutdown; 419 | extern array vfThreadRunning; 420 | extern vector vNodes; 421 | extern CCriticalSection cs_vNodes; 422 | extern map, CAddress> mapAddresses; 423 | extern CCriticalSection cs_mapAddresses; 424 | extern map mapRelay; 425 | extern deque > vRelayExpiration; 426 | extern CCriticalSection cs_mapRelay; 427 | extern map mapAlreadyAskedFor; 428 | extern CAddress addrProxy; 429 | 430 | 431 | 432 | 433 | 434 | class CNode 435 | { 436 | public: 437 | // socket 438 | uint64 nServices; 439 | SOCKET hSocket; 440 | CDataStream vSend; 441 | CDataStream vRecv; 442 | CCriticalSection cs_vSend; 443 | CCriticalSection cs_vRecv; 444 | unsigned int nPushPos; 445 | CAddress addr; 446 | int nVersion; 447 | bool fClient; 448 | bool fInbound; 449 | bool fNetworkNode; 450 | bool fDisconnect; 451 | protected: 452 | int nRefCount; 453 | public: 454 | int64 nReleaseTime; 455 | map mapRequests; 456 | CCriticalSection cs_mapRequests; 457 | 458 | // flood 459 | vector vAddrToSend; 460 | set setAddrKnown; 461 | 462 | // inventory based relay 463 | set setInventoryKnown; 464 | set setInventoryKnown2; 465 | vector vInventoryToSend; 466 | CCriticalSection cs_inventory; 467 | multimap mapAskFor; 468 | 469 | // publish and subscription 470 | vector vfSubscribe; 471 | 472 | 473 | CNode(SOCKET hSocketIn, CAddress addrIn, bool fInboundIn=false) 474 | { 475 | nServices = 0; 476 | hSocket = hSocketIn; 477 | vSend.SetType(SER_NETWORK); 478 | vRecv.SetType(SER_NETWORK); 479 | nPushPos = -1; 480 | addr = addrIn; 481 | nVersion = 0; 482 | fClient = false; // set by version message 483 | fInbound = fInboundIn; 484 | fNetworkNode = false; 485 | fDisconnect = false; 486 | nRefCount = 0; 487 | nReleaseTime = 0; 488 | vfSubscribe.assign(256, false); 489 | 490 | // Push a version message 491 | /// when NTP implemented, change to just nTime = GetAdjustedTime() 492 | int64 nTime = (fInbound ? GetAdjustedTime() : GetTime()); 493 | PushMessage("version", VERSION, nLocalServices, nTime, addr); 494 | } 495 | 496 | ~CNode() 497 | { 498 | if (hSocket != INVALID_SOCKET) 499 | closesocket(hSocket); 500 | } 501 | 502 | private: 503 | CNode(const CNode&); 504 | void operator=(const CNode&); 505 | public: 506 | 507 | 508 | bool ReadyToDisconnect() 509 | { 510 | return fDisconnect || GetRefCount() <= 0; 511 | } 512 | 513 | int GetRefCount() 514 | { 515 | return max(nRefCount, 0) + (GetTime() < nReleaseTime ? 1 : 0); 516 | } 517 | 518 | void AddRef(int64 nTimeout=0) 519 | { 520 | if (nTimeout != 0) 521 | nReleaseTime = max(nReleaseTime, GetTime() + nTimeout); 522 | else 523 | nRefCount++; 524 | } 525 | 526 | void Release() 527 | { 528 | nRefCount--; 529 | } 530 | 531 | 532 | 533 | void AddInventoryKnown(const CInv& inv) 534 | { 535 | CRITICAL_BLOCK(cs_inventory) 536 | setInventoryKnown.insert(inv); 537 | } 538 | 539 | void PushInventory(const CInv& inv) 540 | { 541 | CRITICAL_BLOCK(cs_inventory) 542 | if (!setInventoryKnown.count(inv)) 543 | vInventoryToSend.push_back(inv); 544 | } 545 | 546 | void AskFor(const CInv& inv) 547 | { 548 | // We're using mapAskFor as a priority queue, 549 | // the key is the earliest time the request can be sent 550 | int64& nRequestTime = mapAlreadyAskedFor[inv]; 551 | printf("askfor %s %I64d\n", inv.ToString().c_str(), nRequestTime); 552 | 553 | // Make sure not to reuse time indexes to keep things in the same order 554 | int64 nNow = (GetTime() - 1) * 1000000; 555 | static int64 nLastTime; 556 | nLastTime = nNow = max(nNow, ++nLastTime); 557 | 558 | // Each retry is 2 minutes after the last 559 | nRequestTime = max(nRequestTime + 2 * 60 * 1000000, nNow); 560 | mapAskFor.insert(make_pair(nRequestTime, inv)); 561 | } 562 | 563 | 564 | 565 | void BeginMessage(const char* pszCommand) 566 | { 567 | EnterCriticalSection(&cs_vSend); 568 | if (nPushPos != -1) 569 | AbortMessage(); 570 | nPushPos = vSend.size(); 571 | vSend << CMessageHeader(pszCommand, 0); 572 | printf("sending: %-12s ", pszCommand); 573 | } 574 | 575 | void AbortMessage() 576 | { 577 | if (nPushPos == -1) 578 | return; 579 | vSend.resize(nPushPos); 580 | nPushPos = -1; 581 | LeaveCriticalSection(&cs_vSend); 582 | printf("(aborted)\n"); 583 | } 584 | 585 | void EndMessage() 586 | { 587 | extern int nDropMessagesTest; 588 | if (nDropMessagesTest > 0 && GetRand(nDropMessagesTest) == 0) 589 | { 590 | printf("dropmessages DROPPING SEND MESSAGE\n"); 591 | AbortMessage(); 592 | return; 593 | } 594 | 595 | if (nPushPos == -1) 596 | return; 597 | 598 | // Patch in the size 599 | unsigned int nSize = vSend.size() - nPushPos - sizeof(CMessageHeader); 600 | memcpy((char*)&vSend[nPushPos] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize)); 601 | 602 | printf("(%d bytes) ", nSize); 603 | //for (int i = nPushPos+sizeof(CMessageHeader); i < min(vSend.size(), nPushPos+sizeof(CMessageHeader)+20U); i++) 604 | // printf("%02x ", vSend[i] & 0xff); 605 | printf("\n"); 606 | 607 | nPushPos = -1; 608 | LeaveCriticalSection(&cs_vSend); 609 | } 610 | 611 | void EndMessageAbortIfEmpty() 612 | { 613 | if (nPushPos == -1) 614 | return; 615 | int nSize = vSend.size() - nPushPos - sizeof(CMessageHeader); 616 | if (nSize > 0) 617 | EndMessage(); 618 | else 619 | AbortMessage(); 620 | } 621 | 622 | const char* GetMessageCommand() const 623 | { 624 | if (nPushPos == -1) 625 | return ""; 626 | return &vSend[nPushPos] + offsetof(CMessageHeader, pchCommand); 627 | } 628 | 629 | 630 | 631 | 632 | void PushMessage(const char* pszCommand) 633 | { 634 | try 635 | { 636 | BeginMessage(pszCommand); 637 | EndMessage(); 638 | } 639 | catch (...) 640 | { 641 | AbortMessage(); 642 | throw; 643 | } 644 | } 645 | 646 | template 647 | void PushMessage(const char* pszCommand, const T1& a1) 648 | { 649 | try 650 | { 651 | BeginMessage(pszCommand); 652 | vSend << a1; 653 | EndMessage(); 654 | } 655 | catch (...) 656 | { 657 | AbortMessage(); 658 | throw; 659 | } 660 | } 661 | 662 | template 663 | void PushMessage(const char* pszCommand, const T1& a1, const T2& a2) 664 | { 665 | try 666 | { 667 | BeginMessage(pszCommand); 668 | vSend << a1 << a2; 669 | EndMessage(); 670 | } 671 | catch (...) 672 | { 673 | AbortMessage(); 674 | throw; 675 | } 676 | } 677 | 678 | template 679 | void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3) 680 | { 681 | try 682 | { 683 | BeginMessage(pszCommand); 684 | vSend << a1 << a2 << a3; 685 | EndMessage(); 686 | } 687 | catch (...) 688 | { 689 | AbortMessage(); 690 | throw; 691 | } 692 | } 693 | 694 | template 695 | void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4) 696 | { 697 | try 698 | { 699 | BeginMessage(pszCommand); 700 | vSend << a1 << a2 << a3 << a4; 701 | EndMessage(); 702 | } 703 | catch (...) 704 | { 705 | AbortMessage(); 706 | throw; 707 | } 708 | } 709 | 710 | 711 | void PushRequest(const char* pszCommand, 712 | void (*fn)(void*, CDataStream&), void* param1) 713 | { 714 | uint256 hashReply; 715 | RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply)); 716 | 717 | CRITICAL_BLOCK(cs_mapRequests) 718 | mapRequests[hashReply] = CRequestTracker(fn, param1); 719 | 720 | PushMessage(pszCommand, hashReply); 721 | } 722 | 723 | template 724 | void PushRequest(const char* pszCommand, const T1& a1, 725 | void (*fn)(void*, CDataStream&), void* param1) 726 | { 727 | uint256 hashReply; 728 | RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply)); 729 | 730 | CRITICAL_BLOCK(cs_mapRequests) 731 | mapRequests[hashReply] = CRequestTracker(fn, param1); 732 | 733 | PushMessage(pszCommand, hashReply, a1); 734 | } 735 | 736 | template 737 | void PushRequest(const char* pszCommand, const T1& a1, const T2& a2, 738 | void (*fn)(void*, CDataStream&), void* param1) 739 | { 740 | uint256 hashReply; 741 | RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply)); 742 | 743 | CRITICAL_BLOCK(cs_mapRequests) 744 | mapRequests[hashReply] = CRequestTracker(fn, param1); 745 | 746 | PushMessage(pszCommand, hashReply, a1, a2); 747 | } 748 | 749 | 750 | 751 | bool IsSubscribed(unsigned int nChannel); 752 | void Subscribe(unsigned int nChannel, unsigned int nHops=0); 753 | void CancelSubscribe(unsigned int nChannel); 754 | void Disconnect(); 755 | }; 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | inline void RelayInventory(const CInv& inv) 767 | { 768 | // Put on lists to offer to the other nodes 769 | CRITICAL_BLOCK(cs_vNodes) 770 | foreach(CNode* pnode, vNodes) 771 | pnode->PushInventory(inv); 772 | } 773 | 774 | template 775 | void RelayMessage(const CInv& inv, const T& a) 776 | { 777 | CDataStream ss(SER_NETWORK); 778 | ss.reserve(10000); 779 | ss << a; 780 | RelayMessage(inv, ss); 781 | } 782 | 783 | template<> 784 | inline void RelayMessage<>(const CInv& inv, const CDataStream& ss) 785 | { 786 | CRITICAL_BLOCK(cs_mapRelay) 787 | { 788 | // Expire old relay messages 789 | while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime()) 790 | { 791 | mapRelay.erase(vRelayExpiration.front().second); 792 | vRelayExpiration.pop_front(); 793 | } 794 | 795 | // Save original serialized message so newer versions are preserved 796 | mapRelay[inv] = ss; 797 | vRelayExpiration.push_back(make_pair(GetTime() + 15 * 60, inv)); 798 | } 799 | 800 | RelayInventory(inv); 801 | } 802 | 803 | 804 | 805 | 806 | 807 | 808 | 809 | 810 | // 811 | // Templates for the publish and subscription system. 812 | // The object being published as T& obj needs to have: 813 | // a set setSources member 814 | // specializations of AdvertInsert and AdvertErase 815 | // Currently implemented for CTable and CProduct. 816 | // 817 | 818 | template 819 | void AdvertStartPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj) 820 | { 821 | // Add to sources 822 | obj.setSources.insert(pfrom->addr.ip); 823 | 824 | if (!AdvertInsert(obj)) 825 | return; 826 | 827 | // Relay 828 | CRITICAL_BLOCK(cs_vNodes) 829 | foreach(CNode* pnode, vNodes) 830 | if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel))) 831 | pnode->PushMessage("publish", nChannel, nHops, obj); 832 | } 833 | 834 | template 835 | void AdvertStopPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj) 836 | { 837 | uint256 hash = obj.GetHash(); 838 | 839 | CRITICAL_BLOCK(cs_vNodes) 840 | foreach(CNode* pnode, vNodes) 841 | if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel))) 842 | pnode->PushMessage("pub-cancel", nChannel, nHops, hash); 843 | 844 | AdvertErase(obj); 845 | } 846 | 847 | template 848 | void AdvertRemoveSource(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj) 849 | { 850 | // Remove a source 851 | obj.setSources.erase(pfrom->addr.ip); 852 | 853 | // If no longer supported by any sources, cancel it 854 | if (obj.setSources.empty()) 855 | AdvertStopPublish(pfrom, nChannel, nHops, obj); 856 | } 857 | -------------------------------------------------------------------------------- /src/rc/addressbook16.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trottier/original-bitcoin/92ee8d9a994391d148733da77e2bbc2f4acc43cd/src/rc/addressbook16.bmp -------------------------------------------------------------------------------- /src/rc/addressbook16mask.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trottier/original-bitcoin/92ee8d9a994391d148733da77e2bbc2f4acc43cd/src/rc/addressbook16mask.bmp -------------------------------------------------------------------------------- /src/rc/addressbook20.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trottier/original-bitcoin/92ee8d9a994391d148733da77e2bbc2f4acc43cd/src/rc/addressbook20.bmp -------------------------------------------------------------------------------- /src/rc/addressbook20mask.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trottier/original-bitcoin/92ee8d9a994391d148733da77e2bbc2f4acc43cd/src/rc/addressbook20mask.bmp -------------------------------------------------------------------------------- /src/rc/bitcoin.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trottier/original-bitcoin/92ee8d9a994391d148733da77e2bbc2f4acc43cd/src/rc/bitcoin.ico -------------------------------------------------------------------------------- /src/rc/check.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trottier/original-bitcoin/92ee8d9a994391d148733da77e2bbc2f4acc43cd/src/rc/check.ico -------------------------------------------------------------------------------- /src/rc/send16.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trottier/original-bitcoin/92ee8d9a994391d148733da77e2bbc2f4acc43cd/src/rc/send16.bmp -------------------------------------------------------------------------------- /src/rc/send16mask.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trottier/original-bitcoin/92ee8d9a994391d148733da77e2bbc2f4acc43cd/src/rc/send16mask.bmp -------------------------------------------------------------------------------- /src/rc/send16masknoshadow.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trottier/original-bitcoin/92ee8d9a994391d148733da77e2bbc2f4acc43cd/src/rc/send16masknoshadow.bmp -------------------------------------------------------------------------------- /src/rc/send20.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trottier/original-bitcoin/92ee8d9a994391d148733da77e2bbc2f4acc43cd/src/rc/send20.bmp -------------------------------------------------------------------------------- /src/rc/send20mask.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trottier/original-bitcoin/92ee8d9a994391d148733da77e2bbc2f4acc43cd/src/rc/send20mask.bmp -------------------------------------------------------------------------------- /src/readme.txt: -------------------------------------------------------------------------------- 1 | BitCoin v0.1.3 ALPHA 2 | 3 | Copyright (c) 2009 Satoshi Nakamoto 4 | Distributed under the MIT/X11 software license, see the accompanying 5 | file license.txt or http://www.opensource.org/licenses/mit-license.php. 6 | This product includes software developed by the OpenSSL Project for use in 7 | the OpenSSL Toolkit (http://www.openssl.org/). This product includes 8 | cryptographic software written by Eric Young (eay@cryptsoft.com). 9 | 10 | 11 | Compilers Supported 12 | ------------------- 13 | MinGW GCC (v3.4.5) 14 | Microsoft Visual C++ 6.0 SP6 15 | 16 | 17 | Dependencies 18 | ------------ 19 | Libraries you need to obtain separately to build: 20 | 21 | default path download 22 | wxWidgets \wxWidgets http://www.wxwidgets.org/downloads/ 23 | OpenSSL \OpenSSL http://www.openssl.org/source/ 24 | Berkeley DB \DB http://www.oracle.com/technology/software/products/berkeley-db/index.html 25 | Boost \Boost http://www.boost.org/users/download/ 26 | 27 | Their licenses: 28 | wxWidgets LGPL 2.1 with very liberal exceptions 29 | OpenSSL Old BSD license with the problematic advertising requirement 30 | Berkeley DB New BSD license with additional requirement that linked software must be free open source 31 | Boost MIT-like license 32 | 33 | 34 | OpenSSL 35 | ------- 36 | Bitcoin does not use any encryption. If you want to do a no-everything 37 | build of OpenSSL to exclude encryption routines, a few patches are required. 38 | (OpenSSL v0.9.8h) 39 | 40 | Edit engines\e_gmp.c and put this #ifndef around #include 41 | #ifndef OPENSSL_NO_RSA 42 | #include 43 | #endif 44 | 45 | Add this to crypto\err\err_all.c before the ERR_load_crypto_strings line: 46 | void ERR_load_RSA_strings(void) { } 47 | 48 | Edit ms\mingw32.bat and replace the Configure line's parameters with this 49 | no-everything list. You have to put this in the batch file because batch 50 | files can't handle more than 9 parameters. 51 | perl Configure mingw threads no-rc2 no-rc4 no-rc5 no-idea no-des no-bf no-cast no-aes no-camellia no-seed no-rsa no-dh 52 | 53 | Also REM out the following line in ms\mingw32.bat. The build fails after it's 54 | already finished building libeay32, which is all we care about, but the 55 | failure aborts the script before it runs dllwrap to generate libeay32.dll. 56 | REM if errorlevel 1 goto end 57 | 58 | Build 59 | ms\mingw32.bat 60 | 61 | If you want to use it with MSVC, generate the .lib file 62 | lib /machine:i386 /def:ms\libeay32.def /out:out\libeay32.lib 63 | 64 | 65 | Berkeley DB 66 | ----------- 67 | MinGW with MSYS: 68 | cd \DB\build_unix 69 | sh ../dist/configure --enable-mingw --enable-cxx 70 | make 71 | 72 | 73 | Boost 74 | ----- 75 | You may need Boost version 1.35 to build with MSVC 6.0. I couldn't get 76 | version 1.37 to compile with MSVC 6.0. 77 | -------------------------------------------------------------------------------- /src/script.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 Satoshi Nakamoto 2 | // Distributed under the MIT/X11 software license, see the accompanying 3 | // file license.txt or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | class CTransaction; 6 | 7 | enum 8 | { 9 | SIGHASH_ALL = 1, 10 | SIGHASH_NONE = 2, 11 | SIGHASH_SINGLE = 3, 12 | SIGHASH_ANYONECANPAY = 0x80, 13 | }; 14 | 15 | 16 | 17 | enum opcodetype 18 | { 19 | // push value 20 | OP_0=0, 21 | OP_FALSE=OP_0, 22 | OP_PUSHDATA1=76, 23 | OP_PUSHDATA2, 24 | OP_PUSHDATA4, 25 | OP_1NEGATE, 26 | OP_RESERVED, 27 | OP_1, 28 | OP_TRUE=OP_1, 29 | OP_2, 30 | OP_3, 31 | OP_4, 32 | OP_5, 33 | OP_6, 34 | OP_7, 35 | OP_8, 36 | OP_9, 37 | OP_10, 38 | OP_11, 39 | OP_12, 40 | OP_13, 41 | OP_14, 42 | OP_15, 43 | OP_16, 44 | 45 | // control 46 | OP_NOP, 47 | OP_VER, 48 | OP_IF, 49 | OP_NOTIF, 50 | OP_VERIF, 51 | OP_VERNOTIF, 52 | OP_ELSE, 53 | OP_ENDIF, 54 | OP_VERIFY, 55 | OP_RETURN, 56 | 57 | // stack ops 58 | OP_TOALTSTACK, 59 | OP_FROMALTSTACK, 60 | OP_2DROP, 61 | OP_2DUP, 62 | OP_3DUP, 63 | OP_2OVER, 64 | OP_2ROT, 65 | OP_2SWAP, 66 | OP_IFDUP, 67 | OP_DEPTH, 68 | OP_DROP, 69 | OP_DUP, 70 | OP_NIP, 71 | OP_OVER, 72 | OP_PICK, 73 | OP_ROLL, 74 | OP_ROT, 75 | OP_SWAP, 76 | OP_TUCK, 77 | 78 | // splice ops 79 | OP_CAT, 80 | OP_SUBSTR, 81 | OP_LEFT, 82 | OP_RIGHT, 83 | OP_SIZE, 84 | 85 | // bit logic 86 | OP_INVERT, 87 | OP_AND, 88 | OP_OR, 89 | OP_XOR, 90 | OP_EQUAL, 91 | OP_EQUALVERIFY, 92 | OP_RESERVED1, 93 | OP_RESERVED2, 94 | 95 | // numeric 96 | OP_1ADD, 97 | OP_1SUB, 98 | OP_2MUL, 99 | OP_2DIV, 100 | OP_NEGATE, 101 | OP_ABS, 102 | OP_NOT, 103 | OP_0NOTEQUAL, 104 | 105 | OP_ADD, 106 | OP_SUB, 107 | OP_MUL, 108 | OP_DIV, 109 | OP_MOD, 110 | OP_LSHIFT, 111 | OP_RSHIFT, 112 | 113 | OP_BOOLAND, 114 | OP_BOOLOR, 115 | OP_NUMEQUAL, 116 | OP_NUMEQUALVERIFY, 117 | OP_NUMNOTEQUAL, 118 | OP_LESSTHAN, 119 | OP_GREATERTHAN, 120 | OP_LESSTHANOREQUAL, 121 | OP_GREATERTHANOREQUAL, 122 | OP_MIN, 123 | OP_MAX, 124 | 125 | OP_WITHIN, 126 | 127 | // crypto 128 | OP_RIPEMD160, 129 | OP_SHA1, 130 | OP_SHA256, 131 | OP_HASH160, 132 | OP_HASH256, 133 | OP_CODESEPARATOR, 134 | OP_CHECKSIG, 135 | OP_CHECKSIGVERIFY, 136 | OP_CHECKMULTISIG, 137 | OP_CHECKMULTISIGVERIFY, 138 | 139 | 140 | // multi-byte opcodes 141 | OP_SINGLEBYTE_END = 0xF0, 142 | OP_DOUBLEBYTE_BEGIN = 0xF000, 143 | 144 | // template matching params 145 | OP_PUBKEY, 146 | OP_PUBKEYHASH, 147 | 148 | 149 | 150 | OP_INVALIDOPCODE = 0xFFFF, 151 | }; 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | inline const char* GetOpName(opcodetype opcode) 161 | { 162 | switch (opcode) 163 | { 164 | // push value 165 | case OP_0 : return "0"; 166 | case OP_PUSHDATA1 : return "OP_PUSHDATA1"; 167 | case OP_PUSHDATA2 : return "OP_PUSHDATA2"; 168 | case OP_PUSHDATA4 : return "OP_PUSHDATA4"; 169 | case OP_1NEGATE : return "-1"; 170 | case OP_RESERVED : return "OP_RESERVED"; 171 | case OP_1 : return "1"; 172 | case OP_2 : return "2"; 173 | case OP_3 : return "3"; 174 | case OP_4 : return "4"; 175 | case OP_5 : return "5"; 176 | case OP_6 : return "6"; 177 | case OP_7 : return "7"; 178 | case OP_8 : return "8"; 179 | case OP_9 : return "9"; 180 | case OP_10 : return "10"; 181 | case OP_11 : return "11"; 182 | case OP_12 : return "12"; 183 | case OP_13 : return "13"; 184 | case OP_14 : return "14"; 185 | case OP_15 : return "15"; 186 | case OP_16 : return "16"; 187 | 188 | // control 189 | case OP_NOP : return "OP_NOP"; 190 | case OP_VER : return "OP_VER"; 191 | case OP_IF : return "OP_IF"; 192 | case OP_NOTIF : return "OP_NOTIF"; 193 | case OP_VERIF : return "OP_VERIF"; 194 | case OP_VERNOTIF : return "OP_VERNOTIF"; 195 | case OP_ELSE : return "OP_ELSE"; 196 | case OP_ENDIF : return "OP_ENDIF"; 197 | case OP_VERIFY : return "OP_VERIFY"; 198 | case OP_RETURN : return "OP_RETURN"; 199 | 200 | // stack ops 201 | case OP_TOALTSTACK : return "OP_TOALTSTACK"; 202 | case OP_FROMALTSTACK : return "OP_FROMALTSTACK"; 203 | case OP_2DROP : return "OP_2DROP"; 204 | case OP_2DUP : return "OP_2DUP"; 205 | case OP_3DUP : return "OP_3DUP"; 206 | case OP_2OVER : return "OP_2OVER"; 207 | case OP_2ROT : return "OP_2ROT"; 208 | case OP_2SWAP : return "OP_2SWAP"; 209 | case OP_IFDUP : return "OP_IFDUP"; 210 | case OP_DEPTH : return "OP_DEPTH"; 211 | case OP_DROP : return "OP_DROP"; 212 | case OP_DUP : return "OP_DUP"; 213 | case OP_NIP : return "OP_NIP"; 214 | case OP_OVER : return "OP_OVER"; 215 | case OP_PICK : return "OP_PICK"; 216 | case OP_ROLL : return "OP_ROLL"; 217 | case OP_ROT : return "OP_ROT"; 218 | case OP_SWAP : return "OP_SWAP"; 219 | case OP_TUCK : return "OP_TUCK"; 220 | 221 | // splice ops 222 | case OP_CAT : return "OP_CAT"; 223 | case OP_SUBSTR : return "OP_SUBSTR"; 224 | case OP_LEFT : return "OP_LEFT"; 225 | case OP_RIGHT : return "OP_RIGHT"; 226 | case OP_SIZE : return "OP_SIZE"; 227 | 228 | // bit logic 229 | case OP_INVERT : return "OP_INVERT"; 230 | case OP_AND : return "OP_AND"; 231 | case OP_OR : return "OP_OR"; 232 | case OP_XOR : return "OP_XOR"; 233 | case OP_EQUAL : return "OP_EQUAL"; 234 | case OP_EQUALVERIFY : return "OP_EQUALVERIFY"; 235 | case OP_RESERVED1 : return "OP_RESERVED1"; 236 | case OP_RESERVED2 : return "OP_RESERVED2"; 237 | 238 | // numeric 239 | case OP_1ADD : return "OP_1ADD"; 240 | case OP_1SUB : return "OP_1SUB"; 241 | case OP_2MUL : return "OP_2MUL"; 242 | case OP_2DIV : return "OP_2DIV"; 243 | case OP_NEGATE : return "OP_NEGATE"; 244 | case OP_ABS : return "OP_ABS"; 245 | case OP_NOT : return "OP_NOT"; 246 | case OP_0NOTEQUAL : return "OP_0NOTEQUAL"; 247 | case OP_ADD : return "OP_ADD"; 248 | case OP_SUB : return "OP_SUB"; 249 | case OP_MUL : return "OP_MUL"; 250 | case OP_DIV : return "OP_DIV"; 251 | case OP_MOD : return "OP_MOD"; 252 | case OP_LSHIFT : return "OP_LSHIFT"; 253 | case OP_RSHIFT : return "OP_RSHIFT"; 254 | case OP_BOOLAND : return "OP_BOOLAND"; 255 | case OP_BOOLOR : return "OP_BOOLOR"; 256 | case OP_NUMEQUAL : return "OP_NUMEQUAL"; 257 | case OP_NUMEQUALVERIFY : return "OP_NUMEQUALVERIFY"; 258 | case OP_NUMNOTEQUAL : return "OP_NUMNOTEQUAL"; 259 | case OP_LESSTHAN : return "OP_LESSTHAN"; 260 | case OP_GREATERTHAN : return "OP_GREATERTHAN"; 261 | case OP_LESSTHANOREQUAL : return "OP_LESSTHANOREQUAL"; 262 | case OP_GREATERTHANOREQUAL : return "OP_GREATERTHANOREQUAL"; 263 | case OP_MIN : return "OP_MIN"; 264 | case OP_MAX : return "OP_MAX"; 265 | case OP_WITHIN : return "OP_WITHIN"; 266 | 267 | // crypto 268 | case OP_RIPEMD160 : return "OP_RIPEMD160"; 269 | case OP_SHA1 : return "OP_SHA1"; 270 | case OP_SHA256 : return "OP_SHA256"; 271 | case OP_HASH160 : return "OP_HASH160"; 272 | case OP_HASH256 : return "OP_HASH256"; 273 | case OP_CODESEPARATOR : return "OP_CODESEPARATOR"; 274 | case OP_CHECKSIG : return "OP_CHECKSIG"; 275 | case OP_CHECKSIGVERIFY : return "OP_CHECKSIGVERIFY"; 276 | case OP_CHECKMULTISIG : return "OP_CHECKMULTISIG"; 277 | case OP_CHECKMULTISIGVERIFY : return "OP_CHECKMULTISIGVERIFY"; 278 | 279 | 280 | 281 | // multi-byte opcodes 282 | case OP_SINGLEBYTE_END : return "OP_SINGLEBYTE_END"; 283 | case OP_DOUBLEBYTE_BEGIN : return "OP_DOUBLEBYTE_BEGIN"; 284 | case OP_PUBKEY : return "OP_PUBKEY"; 285 | case OP_PUBKEYHASH : return "OP_PUBKEYHASH"; 286 | 287 | 288 | 289 | case OP_INVALIDOPCODE : return "OP_INVALIDOPCODE"; 290 | default: 291 | return "UNKNOWN_OPCODE"; 292 | } 293 | }; 294 | 295 | 296 | 297 | 298 | inline string ValueString(const vector& vch) 299 | { 300 | if (vch.size() <= 4) 301 | return strprintf("%d", CBigNum(vch).getint()); 302 | else 303 | return HexNumStr(vch.begin(), vch.end()); 304 | //return string("(") + HexStr(vch.begin(), vch.end()) + string(")"); 305 | } 306 | 307 | inline string StackString(const vector >& vStack) 308 | { 309 | string str; 310 | foreach(const vector& vch, vStack) 311 | { 312 | if (!str.empty()) 313 | str += " "; 314 | str += ValueString(vch); 315 | } 316 | return str; 317 | } 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | class CScript : public vector 328 | { 329 | protected: 330 | CScript& push_int64(int64 n) 331 | { 332 | if (n == -1 || (n >= 1 && n <= 16)) 333 | { 334 | push_back(n + (OP_1 - 1)); 335 | } 336 | else 337 | { 338 | CBigNum bn(n); 339 | *this << bn.getvch(); 340 | } 341 | return (*this); 342 | } 343 | 344 | CScript& push_uint64(uint64 n) 345 | { 346 | if (n == -1 || (n >= 1 && n <= 16)) 347 | { 348 | push_back(n + (OP_1 - 1)); 349 | } 350 | else 351 | { 352 | CBigNum bn(n); 353 | *this << bn.getvch(); 354 | } 355 | return (*this); 356 | } 357 | 358 | public: 359 | CScript() { } 360 | CScript(const CScript& b) : vector(b.begin(), b.end()) { } 361 | CScript(const_iterator pbegin, const_iterator pend) : vector(pbegin, pend) { } 362 | #ifndef _MSC_VER 363 | CScript(const unsigned char* pbegin, const unsigned char* pend) : vector(pbegin, pend) { } 364 | #endif 365 | 366 | CScript& operator+=(const CScript& b) 367 | { 368 | insert(end(), b.begin(), b.end()); 369 | return *this; 370 | } 371 | 372 | friend CScript operator+(const CScript& a, const CScript& b) 373 | { 374 | CScript ret = a; 375 | ret += b; 376 | return (ret); 377 | } 378 | 379 | 380 | explicit CScript(char b) { operator<<(b); } 381 | explicit CScript(short b) { operator<<(b); } 382 | explicit CScript(int b) { operator<<(b); } 383 | explicit CScript(long b) { operator<<(b); } 384 | explicit CScript(int64 b) { operator<<(b); } 385 | explicit CScript(unsigned char b) { operator<<(b); } 386 | explicit CScript(unsigned int b) { operator<<(b); } 387 | explicit CScript(unsigned short b) { operator<<(b); } 388 | explicit CScript(unsigned long b) { operator<<(b); } 389 | explicit CScript(uint64 b) { operator<<(b); } 390 | 391 | explicit CScript(opcodetype b) { operator<<(b); } 392 | explicit CScript(const uint256& b) { operator<<(b); } 393 | explicit CScript(const CBigNum& b) { operator<<(b); } 394 | explicit CScript(const vector& b) { operator<<(b); } 395 | 396 | 397 | CScript& operator<<(char b) { return (push_int64(b)); } 398 | CScript& operator<<(short b) { return (push_int64(b)); } 399 | CScript& operator<<(int b) { return (push_int64(b)); } 400 | CScript& operator<<(long b) { return (push_int64(b)); } 401 | CScript& operator<<(int64 b) { return (push_int64(b)); } 402 | CScript& operator<<(unsigned char b) { return (push_uint64(b)); } 403 | CScript& operator<<(unsigned int b) { return (push_uint64(b)); } 404 | CScript& operator<<(unsigned short b) { return (push_uint64(b)); } 405 | CScript& operator<<(unsigned long b) { return (push_uint64(b)); } 406 | CScript& operator<<(uint64 b) { return (push_uint64(b)); } 407 | 408 | CScript& operator<<(opcodetype opcode) 409 | { 410 | if (opcode <= OP_SINGLEBYTE_END) 411 | { 412 | insert(end(), (unsigned char)opcode); 413 | } 414 | else 415 | { 416 | assert(opcode >= OP_DOUBLEBYTE_BEGIN); 417 | insert(end(), (unsigned char)(opcode >> 8)); 418 | insert(end(), (unsigned char)(opcode & 0xFF)); 419 | } 420 | return (*this); 421 | } 422 | 423 | CScript& operator<<(const uint160& b) 424 | { 425 | insert(end(), sizeof(b)); 426 | insert(end(), (unsigned char*)&b, (unsigned char*)&b + sizeof(b)); 427 | return (*this); 428 | } 429 | 430 | CScript& operator<<(const uint256& b) 431 | { 432 | insert(end(), sizeof(b)); 433 | insert(end(), (unsigned char*)&b, (unsigned char*)&b + sizeof(b)); 434 | return (*this); 435 | } 436 | 437 | CScript& operator<<(const CBigNum& b) 438 | { 439 | *this << b.getvch(); 440 | return (*this); 441 | } 442 | 443 | CScript& operator<<(const vector& b) 444 | { 445 | if (b.size() < OP_PUSHDATA1) 446 | { 447 | insert(end(), (unsigned char)b.size()); 448 | } 449 | else if (b.size() <= 0xff) 450 | { 451 | insert(end(), OP_PUSHDATA1); 452 | insert(end(), (unsigned char)b.size()); 453 | } 454 | else 455 | { 456 | insert(end(), OP_PUSHDATA2); 457 | unsigned short nSize = b.size(); 458 | insert(end(), (unsigned char*)&nSize, (unsigned char*)&nSize + sizeof(nSize)); 459 | } 460 | insert(end(), b.begin(), b.end()); 461 | return (*this); 462 | } 463 | 464 | CScript& operator<<(const CScript& b) 465 | { 466 | // I'm not sure if this should push the script or concatenate scripts. 467 | // If there's ever a use for pushing a script onto a script, delete this member fn 468 | assert(("warning: pushing a CScript onto a CScript with << is probably not intended, use + to concatenate", false)); 469 | return (*this); 470 | } 471 | 472 | 473 | bool GetOp(iterator& pc, opcodetype& opcodeRet, vector& vchRet) 474 | { 475 | // This is why people hate C++ 476 | const_iterator pc2 = pc; 477 | bool fRet = GetOp(pc2, opcodeRet, vchRet); 478 | pc = begin() + (pc2 - begin()); 479 | return fRet; 480 | } 481 | 482 | bool GetOp(const_iterator& pc, opcodetype& opcodeRet, vector& vchRet) const 483 | { 484 | opcodeRet = OP_INVALIDOPCODE; 485 | vchRet.clear(); 486 | if (pc >= end()) 487 | return false; 488 | 489 | // Read instruction 490 | unsigned int opcode = *pc++; 491 | if (opcode >= OP_SINGLEBYTE_END) 492 | { 493 | if (pc + 1 > end()) 494 | return false; 495 | opcode <<= 8; 496 | opcode |= *pc++; 497 | } 498 | 499 | // Immediate operand 500 | if (opcode <= OP_PUSHDATA4) 501 | { 502 | unsigned int nSize = opcode; 503 | if (opcode == OP_PUSHDATA1) 504 | { 505 | if (pc + 1 > end()) 506 | return false; 507 | nSize = *pc++; 508 | } 509 | else if (opcode == OP_PUSHDATA2) 510 | { 511 | if (pc + 2 > end()) 512 | return false; 513 | nSize = 0; 514 | memcpy(&nSize, &pc[0], 2); 515 | pc += 2; 516 | } 517 | else if (opcode == OP_PUSHDATA4) 518 | { 519 | if (pc + 4 > end()) 520 | return false; 521 | memcpy(&nSize, &pc[0], 4); 522 | pc += 4; 523 | } 524 | if (pc + nSize > end()) 525 | return false; 526 | vchRet.assign(pc, pc + nSize); 527 | pc += nSize; 528 | } 529 | 530 | opcodeRet = (opcodetype)opcode; 531 | return true; 532 | } 533 | 534 | 535 | void FindAndDelete(const CScript& b) 536 | { 537 | iterator pc = begin(); 538 | opcodetype opcode; 539 | vector vchPushValue; 540 | int count = 0; 541 | do 542 | { 543 | while (end() - pc >= b.size() && memcmp(&pc[0], &b[0], b.size()) == 0) 544 | { 545 | erase(pc, pc + b.size()); 546 | count++; 547 | } 548 | } 549 | while (GetOp(pc, opcode, vchPushValue)); 550 | //printf("FindAndDeleted deleted %d items\n", count); /// debug 551 | } 552 | 553 | 554 | void PrintHex() const 555 | { 556 | printf("CScript(%s)\n", HexStr(begin(), end()).c_str()); 557 | } 558 | 559 | string ToString() const 560 | { 561 | string str; 562 | opcodetype opcode; 563 | vector vch; 564 | const_iterator it = begin(); 565 | while (GetOp(it, opcode, vch)) 566 | { 567 | if (!str.empty()) 568 | str += " "; 569 | if (opcode <= OP_PUSHDATA4) 570 | str += ValueString(vch); 571 | else 572 | str += GetOpName(opcode); 573 | } 574 | return str; 575 | } 576 | 577 | void print() const 578 | { 579 | printf("%s\n", ToString().c_str()); 580 | } 581 | }; 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType=0, 591 | vector >* pvStackRet=NULL); 592 | uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); 593 | bool IsMine(const CScript& scriptPubKey); 594 | bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector& vchPubKeyRet); 595 | bool ExtractHash160(const CScript& scriptPubKey, uint160& hash160Ret); 596 | bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL, CScript scriptPrereq=CScript()); 597 | bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, int nHashType=0); 598 | -------------------------------------------------------------------------------- /src/sha.cpp: -------------------------------------------------------------------------------- 1 | // This file is public domain 2 | // SHA routines extracted as a standalone file from: 3 | // Crypto++: a C++ Class Library of Cryptographic Schemes 4 | // Version 5.5.2 (9/24/2007) 5 | // http://www.cryptopp.com 6 | 7 | // sha.cpp - modified by Wei Dai from Steve Reid's public domain sha1.c 8 | 9 | // Steve Reid implemented SHA-1. Wei Dai implemented SHA-2. 10 | // Both are in the public domain. 11 | 12 | #include 13 | #include 14 | #include "sha.h" 15 | 16 | namespace CryptoPP 17 | { 18 | 19 | // start of Steve Reid's code 20 | 21 | #define blk0(i) (W[i] = data[i]) 22 | #define blk1(i) (W[i&15] = rotlFixed(W[(i+13)&15]^W[(i+8)&15]^W[(i+2)&15]^W[i&15],1)) 23 | 24 | void SHA1::InitState(HashWordType *state) 25 | { 26 | state[0] = 0x67452301L; 27 | state[1] = 0xEFCDAB89L; 28 | state[2] = 0x98BADCFEL; 29 | state[3] = 0x10325476L; 30 | state[4] = 0xC3D2E1F0L; 31 | } 32 | 33 | #define f1(x,y,z) (z^(x&(y^z))) 34 | #define f2(x,y,z) (x^y^z) 35 | #define f3(x,y,z) ((x&y)|(z&(x|y))) 36 | #define f4(x,y,z) (x^y^z) 37 | 38 | /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ 39 | #define R0(v,w,x,y,z,i) z+=f1(w,x,y)+blk0(i)+0x5A827999+rotlFixed(v,5);w=rotlFixed(w,30); 40 | #define R1(v,w,x,y,z,i) z+=f1(w,x,y)+blk1(i)+0x5A827999+rotlFixed(v,5);w=rotlFixed(w,30); 41 | #define R2(v,w,x,y,z,i) z+=f2(w,x,y)+blk1(i)+0x6ED9EBA1+rotlFixed(v,5);w=rotlFixed(w,30); 42 | #define R3(v,w,x,y,z,i) z+=f3(w,x,y)+blk1(i)+0x8F1BBCDC+rotlFixed(v,5);w=rotlFixed(w,30); 43 | #define R4(v,w,x,y,z,i) z+=f4(w,x,y)+blk1(i)+0xCA62C1D6+rotlFixed(v,5);w=rotlFixed(w,30); 44 | 45 | void SHA1::Transform(word32 *state, const word32 *data) 46 | { 47 | word32 W[16]; 48 | /* Copy context->state[] to working vars */ 49 | word32 a = state[0]; 50 | word32 b = state[1]; 51 | word32 c = state[2]; 52 | word32 d = state[3]; 53 | word32 e = state[4]; 54 | /* 4 rounds of 20 operations each. Loop unrolled. */ 55 | R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); 56 | R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); 57 | R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); 58 | R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); 59 | R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); 60 | R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); 61 | R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); 62 | R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); 63 | R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); 64 | R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); 65 | R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); 66 | R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); 67 | R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); 68 | R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); 69 | R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); 70 | R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); 71 | R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); 72 | R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); 73 | R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); 74 | R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); 75 | /* Add the working vars back into context.state[] */ 76 | state[0] += a; 77 | state[1] += b; 78 | state[2] += c; 79 | state[3] += d; 80 | state[4] += e; 81 | } 82 | 83 | // end of Steve Reid's code 84 | 85 | // ************************************************************* 86 | 87 | void SHA224::InitState(HashWordType *state) 88 | { 89 | static const word32 s[8] = {0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4}; 90 | memcpy(state, s, sizeof(s)); 91 | } 92 | 93 | void SHA256::InitState(HashWordType *state) 94 | { 95 | static const word32 s[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; 96 | memcpy(state, s, sizeof(s)); 97 | } 98 | 99 | static const word32 SHA256_K[64] = { 100 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 101 | 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 102 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 103 | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 104 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 105 | 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 106 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 107 | 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 108 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 109 | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 110 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 111 | 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 112 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 113 | 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 114 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 115 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 116 | }; 117 | 118 | #define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15])) 119 | 120 | #define Ch(x,y,z) (z^(x&(y^z))) 121 | #define Maj(x,y,z) ((x&y)|(z&(x|y))) 122 | 123 | #define a(i) T[(0-i)&7] 124 | #define b(i) T[(1-i)&7] 125 | #define c(i) T[(2-i)&7] 126 | #define d(i) T[(3-i)&7] 127 | #define e(i) T[(4-i)&7] 128 | #define f(i) T[(5-i)&7] 129 | #define g(i) T[(6-i)&7] 130 | #define h(i) T[(7-i)&7] 131 | 132 | #define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA256_K[i+j]+(j?blk2(i):blk0(i));\ 133 | d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i)) 134 | 135 | // for SHA256 136 | #define S0(x) (rotrFixed(x,2)^rotrFixed(x,13)^rotrFixed(x,22)) 137 | #define S1(x) (rotrFixed(x,6)^rotrFixed(x,11)^rotrFixed(x,25)) 138 | #define s0(x) (rotrFixed(x,7)^rotrFixed(x,18)^(x>>3)) 139 | #define s1(x) (rotrFixed(x,17)^rotrFixed(x,19)^(x>>10)) 140 | 141 | void SHA256::Transform(word32 *state, const word32 *data) 142 | { 143 | word32 W[16]; 144 | word32 T[8]; 145 | /* Copy context->state[] to working vars */ 146 | memcpy(T, state, sizeof(T)); 147 | /* 64 operations, partially loop unrolled */ 148 | for (unsigned int j=0; j<64; j+=16) 149 | { 150 | R( 0); R( 1); R( 2); R( 3); 151 | R( 4); R( 5); R( 6); R( 7); 152 | R( 8); R( 9); R(10); R(11); 153 | R(12); R(13); R(14); R(15); 154 | } 155 | /* Add the working vars back into context.state[] */ 156 | state[0] += a(0); 157 | state[1] += b(0); 158 | state[2] += c(0); 159 | state[3] += d(0); 160 | state[4] += e(0); 161 | state[5] += f(0); 162 | state[6] += g(0); 163 | state[7] += h(0); 164 | } 165 | 166 | /* 167 | // smaller but slower 168 | void SHA256_Transform(word32 *state, const word32 *data) 169 | { 170 | word32 T[20]; 171 | word32 W[32]; 172 | unsigned int i = 0, j = 0; 173 | word32 *t = T+8; 174 | 175 | memcpy(t, state, 8*4); 176 | word32 e = t[4], a = t[0]; 177 | 178 | do 179 | { 180 | word32 w = data[j]; 181 | W[j] = w; 182 | w += K[j]; 183 | w += t[7]; 184 | w += S1(e); 185 | w += Ch(e, t[5], t[6]); 186 | e = t[3] + w; 187 | t[3] = t[3+8] = e; 188 | w += S0(t[0]); 189 | a = w + Maj(a, t[1], t[2]); 190 | t[-1] = t[7] = a; 191 | --t; 192 | ++j; 193 | if (j%8 == 0) 194 | t += 8; 195 | } while (j<16); 196 | 197 | do 198 | { 199 | i = j&0xf; 200 | word32 w = s1(W[i+16-2]) + s0(W[i+16-15]) + W[i] + W[i+16-7]; 201 | W[i+16] = W[i] = w; 202 | w += K[j]; 203 | w += t[7]; 204 | w += S1(e); 205 | w += Ch(e, t[5], t[6]); 206 | e = t[3] + w; 207 | t[3] = t[3+8] = e; 208 | w += S0(t[0]); 209 | a = w + Maj(a, t[1], t[2]); 210 | t[-1] = t[7] = a; 211 | 212 | w = s1(W[(i+1)+16-2]) + s0(W[(i+1)+16-15]) + W[(i+1)] + W[(i+1)+16-7]; 213 | W[(i+1)+16] = W[(i+1)] = w; 214 | w += K[j+1]; 215 | w += (t-1)[7]; 216 | w += S1(e); 217 | w += Ch(e, (t-1)[5], (t-1)[6]); 218 | e = (t-1)[3] + w; 219 | (t-1)[3] = (t-1)[3+8] = e; 220 | w += S0((t-1)[0]); 221 | a = w + Maj(a, (t-1)[1], (t-1)[2]); 222 | (t-1)[-1] = (t-1)[7] = a; 223 | 224 | t-=2; 225 | j+=2; 226 | if (j%8 == 0) 227 | t += 8; 228 | } while (j<64); 229 | 230 | state[0] += a; 231 | state[1] += t[1]; 232 | state[2] += t[2]; 233 | state[3] += t[3]; 234 | state[4] += e; 235 | state[5] += t[5]; 236 | state[6] += t[6]; 237 | state[7] += t[7]; 238 | } 239 | */ 240 | 241 | #undef S0 242 | #undef S1 243 | #undef s0 244 | #undef s1 245 | #undef R 246 | 247 | // ************************************************************* 248 | 249 | #ifdef WORD64_AVAILABLE 250 | 251 | void SHA384::InitState(HashWordType *state) 252 | { 253 | static const word64 s[8] = { 254 | W64LIT(0xcbbb9d5dc1059ed8), W64LIT(0x629a292a367cd507), 255 | W64LIT(0x9159015a3070dd17), W64LIT(0x152fecd8f70e5939), 256 | W64LIT(0x67332667ffc00b31), W64LIT(0x8eb44a8768581511), 257 | W64LIT(0xdb0c2e0d64f98fa7), W64LIT(0x47b5481dbefa4fa4)}; 258 | memcpy(state, s, sizeof(s)); 259 | } 260 | 261 | void SHA512::InitState(HashWordType *state) 262 | { 263 | static const word64 s[8] = { 264 | W64LIT(0x6a09e667f3bcc908), W64LIT(0xbb67ae8584caa73b), 265 | W64LIT(0x3c6ef372fe94f82b), W64LIT(0xa54ff53a5f1d36f1), 266 | W64LIT(0x510e527fade682d1), W64LIT(0x9b05688c2b3e6c1f), 267 | W64LIT(0x1f83d9abfb41bd6b), W64LIT(0x5be0cd19137e2179)}; 268 | memcpy(state, s, sizeof(s)); 269 | } 270 | 271 | CRYPTOPP_ALIGN_DATA(16) static const word64 SHA512_K[80] CRYPTOPP_SECTION_ALIGN16 = { 272 | W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd), 273 | W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc), 274 | W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019), 275 | W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118), 276 | W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe), 277 | W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2), 278 | W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1), 279 | W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694), 280 | W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3), 281 | W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65), 282 | W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483), 283 | W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5), 284 | W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210), 285 | W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4), 286 | W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725), 287 | W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70), 288 | W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926), 289 | W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df), 290 | W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8), 291 | W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b), 292 | W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001), 293 | W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30), 294 | W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910), 295 | W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8), 296 | W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53), 297 | W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8), 298 | W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb), 299 | W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3), 300 | W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60), 301 | W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec), 302 | W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9), 303 | W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b), 304 | W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207), 305 | W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178), 306 | W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6), 307 | W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b), 308 | W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493), 309 | W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c), 310 | W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a), 311 | W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817) 312 | }; 313 | 314 | #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86 315 | // put assembly version in separate function, otherwise MSVC 2005 SP1 doesn't generate correct code for the non-assembly version 316 | CRYPTOPP_NAKED static void CRYPTOPP_FASTCALL SHA512_SSE2_Transform(word64 *state, const word64 *data) 317 | { 318 | #ifdef __GNUC__ 319 | __asm__ __volatile__ 320 | ( 321 | ".intel_syntax noprefix;" 322 | AS1( push ebx) 323 | AS2( mov ebx, eax) 324 | #else 325 | AS1( push ebx) 326 | AS1( push esi) 327 | AS1( push edi) 328 | AS2( lea ebx, SHA512_K) 329 | #endif 330 | 331 | AS2( mov eax, esp) 332 | AS2( and esp, 0xfffffff0) 333 | AS2( sub esp, 27*16) // 17*16 for expanded data, 20*8 for state 334 | AS1( push eax) 335 | AS2( xor eax, eax) 336 | AS2( lea edi, [esp+4+8*8]) // start at middle of state buffer. will decrement pointer each round to avoid copying 337 | AS2( lea esi, [esp+4+20*8+8]) // 16-byte alignment, then add 8 338 | 339 | AS2( movq mm4, [ecx+0*8]) 340 | AS2( movq [edi+0*8], mm4) 341 | AS2( movq mm0, [ecx+1*8]) 342 | AS2( movq [edi+1*8], mm0) 343 | AS2( movq mm0, [ecx+2*8]) 344 | AS2( movq [edi+2*8], mm0) 345 | AS2( movq mm0, [ecx+3*8]) 346 | AS2( movq [edi+3*8], mm0) 347 | AS2( movq mm5, [ecx+4*8]) 348 | AS2( movq [edi+4*8], mm5) 349 | AS2( movq mm0, [ecx+5*8]) 350 | AS2( movq [edi+5*8], mm0) 351 | AS2( movq mm0, [ecx+6*8]) 352 | AS2( movq [edi+6*8], mm0) 353 | AS2( movq mm0, [ecx+7*8]) 354 | AS2( movq [edi+7*8], mm0) 355 | ASJ( jmp, 0, f) 356 | 357 | #define SSE2_S0_S1(r, a, b, c) \ 358 | AS2( movq mm6, r)\ 359 | AS2( psrlq r, a)\ 360 | AS2( movq mm7, r)\ 361 | AS2( psllq mm6, 64-c)\ 362 | AS2( pxor mm7, mm6)\ 363 | AS2( psrlq r, b-a)\ 364 | AS2( pxor mm7, r)\ 365 | AS2( psllq mm6, c-b)\ 366 | AS2( pxor mm7, mm6)\ 367 | AS2( psrlq r, c-b)\ 368 | AS2( pxor r, mm7)\ 369 | AS2( psllq mm6, b-a)\ 370 | AS2( pxor r, mm6) 371 | 372 | #define SSE2_s0(r, a, b, c) \ 373 | AS2( movdqa xmm6, r)\ 374 | AS2( psrlq r, a)\ 375 | AS2( movdqa xmm7, r)\ 376 | AS2( psllq xmm6, 64-c)\ 377 | AS2( pxor xmm7, xmm6)\ 378 | AS2( psrlq r, b-a)\ 379 | AS2( pxor xmm7, r)\ 380 | AS2( psrlq r, c-b)\ 381 | AS2( pxor r, xmm7)\ 382 | AS2( psllq xmm6, c-a)\ 383 | AS2( pxor r, xmm6) 384 | 385 | #define SSE2_s1(r, a, b, c) \ 386 | AS2( movdqa xmm6, r)\ 387 | AS2( psrlq r, a)\ 388 | AS2( movdqa xmm7, r)\ 389 | AS2( psllq xmm6, 64-c)\ 390 | AS2( pxor xmm7, xmm6)\ 391 | AS2( psrlq r, b-a)\ 392 | AS2( pxor xmm7, r)\ 393 | AS2( psllq xmm6, c-b)\ 394 | AS2( pxor xmm7, xmm6)\ 395 | AS2( psrlq r, c-b)\ 396 | AS2( pxor r, xmm7) 397 | 398 | ASL(SHA512_Round) 399 | // k + w is in mm0, a is in mm4, e is in mm5 400 | AS2( paddq mm0, [edi+7*8]) // h 401 | AS2( movq mm2, [edi+5*8]) // f 402 | AS2( movq mm3, [edi+6*8]) // g 403 | AS2( pxor mm2, mm3) 404 | AS2( pand mm2, mm5) 405 | SSE2_S0_S1(mm5,14,18,41) 406 | AS2( pxor mm2, mm3) 407 | AS2( paddq mm0, mm2) // h += Ch(e,f,g) 408 | AS2( paddq mm5, mm0) // h += S1(e) 409 | AS2( movq mm2, [edi+1*8]) // b 410 | AS2( movq mm1, mm2) 411 | AS2( por mm2, mm4) 412 | AS2( pand mm2, [edi+2*8]) // c 413 | AS2( pand mm1, mm4) 414 | AS2( por mm1, mm2) 415 | AS2( paddq mm1, mm5) // temp = h + Maj(a,b,c) 416 | AS2( paddq mm5, [edi+3*8]) // e = d + h 417 | AS2( movq [edi+3*8], mm5) 418 | AS2( movq [edi+11*8], mm5) 419 | SSE2_S0_S1(mm4,28,34,39) // S0(a) 420 | AS2( paddq mm4, mm1) // a = temp + S0(a) 421 | AS2( movq [edi-8], mm4) 422 | AS2( movq [edi+7*8], mm4) 423 | AS1( ret) 424 | 425 | // first 16 rounds 426 | ASL(0) 427 | AS2( movq mm0, [edx+eax*8]) 428 | AS2( movq [esi+eax*8], mm0) 429 | AS2( movq [esi+eax*8+16*8], mm0) 430 | AS2( paddq mm0, [ebx+eax*8]) 431 | ASC( call, SHA512_Round) 432 | AS1( inc eax) 433 | AS2( sub edi, 8) 434 | AS2( test eax, 7) 435 | ASJ( jnz, 0, b) 436 | AS2( add edi, 8*8) 437 | AS2( cmp eax, 16) 438 | ASJ( jne, 0, b) 439 | 440 | // rest of the rounds 441 | AS2( movdqu xmm0, [esi+(16-2)*8]) 442 | ASL(1) 443 | // data expansion, W[i-2] already in xmm0 444 | AS2( movdqu xmm3, [esi]) 445 | AS2( paddq xmm3, [esi+(16-7)*8]) 446 | AS2( movdqa xmm2, [esi+(16-15)*8]) 447 | SSE2_s1(xmm0, 6, 19, 61) 448 | AS2( paddq xmm0, xmm3) 449 | SSE2_s0(xmm2, 1, 7, 8) 450 | AS2( paddq xmm0, xmm2) 451 | AS2( movdq2q mm0, xmm0) 452 | AS2( movhlps xmm1, xmm0) 453 | AS2( paddq mm0, [ebx+eax*8]) 454 | AS2( movlps [esi], xmm0) 455 | AS2( movlps [esi+8], xmm1) 456 | AS2( movlps [esi+8*16], xmm0) 457 | AS2( movlps [esi+8*17], xmm1) 458 | // 2 rounds 459 | ASC( call, SHA512_Round) 460 | AS2( sub edi, 8) 461 | AS2( movdq2q mm0, xmm1) 462 | AS2( paddq mm0, [ebx+eax*8+8]) 463 | ASC( call, SHA512_Round) 464 | // update indices and loop 465 | AS2( add esi, 16) 466 | AS2( add eax, 2) 467 | AS2( sub edi, 8) 468 | AS2( test eax, 7) 469 | ASJ( jnz, 1, b) 470 | // do housekeeping every 8 rounds 471 | AS2( mov esi, 0xf) 472 | AS2( and esi, eax) 473 | AS2( lea esi, [esp+4+20*8+8+esi*8]) 474 | AS2( add edi, 8*8) 475 | AS2( cmp eax, 80) 476 | ASJ( jne, 1, b) 477 | 478 | #define SSE2_CombineState(i) \ 479 | AS2( movq mm0, [edi+i*8])\ 480 | AS2( paddq mm0, [ecx+i*8])\ 481 | AS2( movq [ecx+i*8], mm0) 482 | 483 | SSE2_CombineState(0) 484 | SSE2_CombineState(1) 485 | SSE2_CombineState(2) 486 | SSE2_CombineState(3) 487 | SSE2_CombineState(4) 488 | SSE2_CombineState(5) 489 | SSE2_CombineState(6) 490 | SSE2_CombineState(7) 491 | 492 | AS1( pop esp) 493 | AS1( emms) 494 | 495 | #if defined(__GNUC__) 496 | AS1( pop ebx) 497 | ".att_syntax prefix;" 498 | : 499 | : "a" (SHA512_K), "c" (state), "d" (data) 500 | : "%esi", "%edi", "memory", "cc" 501 | ); 502 | #else 503 | AS1( pop edi) 504 | AS1( pop esi) 505 | AS1( pop ebx) 506 | AS1( ret) 507 | #endif 508 | } 509 | #endif // #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 510 | 511 | void SHA512::Transform(word64 *state, const word64 *data) 512 | { 513 | #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86 514 | if (HasSSE2()) 515 | { 516 | SHA512_SSE2_Transform(state, data); 517 | return; 518 | } 519 | #endif 520 | 521 | #define S0(x) (rotrFixed(x,28)^rotrFixed(x,34)^rotrFixed(x,39)) 522 | #define S1(x) (rotrFixed(x,14)^rotrFixed(x,18)^rotrFixed(x,41)) 523 | #define s0(x) (rotrFixed(x,1)^rotrFixed(x,8)^(x>>7)) 524 | #define s1(x) (rotrFixed(x,19)^rotrFixed(x,61)^(x>>6)) 525 | 526 | #define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA512_K[i+j]+(j?blk2(i):blk0(i));\ 527 | d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i)) 528 | 529 | word64 W[16]; 530 | word64 T[8]; 531 | /* Copy context->state[] to working vars */ 532 | memcpy(T, state, sizeof(T)); 533 | /* 80 operations, partially loop unrolled */ 534 | for (unsigned int j=0; j<80; j+=16) 535 | { 536 | R( 0); R( 1); R( 2); R( 3); 537 | R( 4); R( 5); R( 6); R( 7); 538 | R( 8); R( 9); R(10); R(11); 539 | R(12); R(13); R(14); R(15); 540 | } 541 | /* Add the working vars back into context.state[] */ 542 | state[0] += a(0); 543 | state[1] += b(0); 544 | state[2] += c(0); 545 | state[3] += d(0); 546 | state[4] += e(0); 547 | state[5] += f(0); 548 | state[6] += g(0); 549 | state[7] += h(0); 550 | } 551 | 552 | #endif 553 | 554 | } 555 | -------------------------------------------------------------------------------- /src/sha.h: -------------------------------------------------------------------------------- 1 | // This file is public domain 2 | // SHA routines extracted as a standalone file from: 3 | // Crypto++: a C++ Class Library of Cryptographic Schemes 4 | // Version 5.5.2 (9/24/2007) 5 | // http://www.cryptopp.com 6 | #ifndef CRYPTOPP_SHA_H 7 | #define CRYPTOPP_SHA_H 8 | #include 9 | 10 | namespace CryptoPP 11 | { 12 | 13 | // 14 | // Dependencies 15 | // 16 | 17 | typedef unsigned char byte; 18 | typedef unsigned short word16; 19 | typedef unsigned int word32; 20 | #if defined(_MSC_VER) || defined(__BORLANDC__) 21 | typedef unsigned __int64 word64; 22 | #else 23 | typedef unsigned long long word64; 24 | #endif 25 | 26 | template inline T rotlFixed(T x, unsigned int y) 27 | { 28 | assert(y < sizeof(T)*8); 29 | return T((x<>(sizeof(T)*8-y))); 30 | } 31 | 32 | template inline T rotrFixed(T x, unsigned int y) 33 | { 34 | assert(y < sizeof(T)*8); 35 | return T((x>>y) | (x<<(sizeof(T)*8-y))); 36 | } 37 | 38 | // ************** endian reversal *************** 39 | 40 | #ifdef _MSC_VER 41 | #if _MSC_VER >= 1400 42 | #define CRYPTOPP_FAST_ROTATE(x) 1 43 | #elif _MSC_VER >= 1300 44 | #define CRYPTOPP_FAST_ROTATE(x) ((x) == 32 | (x) == 64) 45 | #else 46 | #define CRYPTOPP_FAST_ROTATE(x) ((x) == 32) 47 | #endif 48 | #elif (defined(__MWERKS__) && TARGET_CPU_PPC) || \ 49 | (defined(__GNUC__) && (defined(_ARCH_PWR2) || defined(_ARCH_PWR) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || defined(_ARCH_COM))) 50 | #define CRYPTOPP_FAST_ROTATE(x) ((x) == 32) 51 | #elif defined(__GNUC__) && (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86) // depend on GCC's peephole optimization to generate rotate instructions 52 | #define CRYPTOPP_FAST_ROTATE(x) 1 53 | #else 54 | #define CRYPTOPP_FAST_ROTATE(x) 0 55 | #endif 56 | 57 | inline byte ByteReverse(byte value) 58 | { 59 | return value; 60 | } 61 | 62 | inline word16 ByteReverse(word16 value) 63 | { 64 | #ifdef CRYPTOPP_BYTESWAP_AVAILABLE 65 | return bswap_16(value); 66 | #elif defined(_MSC_VER) && _MSC_VER >= 1300 67 | return _byteswap_ushort(value); 68 | #else 69 | return rotlFixed(value, 8U); 70 | #endif 71 | } 72 | 73 | inline word32 ByteReverse(word32 value) 74 | { 75 | #if defined(__GNUC__) 76 | __asm__ ("bswap %0" : "=r" (value) : "0" (value)); 77 | return value; 78 | #elif defined(CRYPTOPP_BYTESWAP_AVAILABLE) 79 | return bswap_32(value); 80 | #elif defined(__MWERKS__) && TARGET_CPU_PPC 81 | return (word32)__lwbrx(&value,0); 82 | #elif _MSC_VER >= 1400 || (_MSC_VER >= 1300 && !defined(_DLL)) 83 | return _byteswap_ulong(value); 84 | #elif CRYPTOPP_FAST_ROTATE(32) 85 | // 5 instructions with rotate instruction, 9 without 86 | return (rotrFixed(value, 8U) & 0xff00ff00) | (rotlFixed(value, 8U) & 0x00ff00ff); 87 | #else 88 | // 6 instructions with rotate instruction, 8 without 89 | value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8); 90 | return rotlFixed(value, 16U); 91 | #endif 92 | } 93 | 94 | #ifdef WORD64_AVAILABLE 95 | inline word64 ByteReverse(word64 value) 96 | { 97 | #if defined(__GNUC__) && defined(__x86_64__) 98 | __asm__ ("bswap %0" : "=r" (value) : "0" (value)); 99 | return value; 100 | #elif defined(CRYPTOPP_BYTESWAP_AVAILABLE) 101 | return bswap_64(value); 102 | #elif defined(_MSC_VER) && _MSC_VER >= 1300 103 | return _byteswap_uint64(value); 104 | #elif defined(CRYPTOPP_SLOW_WORD64) 105 | return (word64(ByteReverse(word32(value))) << 32) | ByteReverse(word32(value>>32)); 106 | #else 107 | value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) | ((value & W64LIT(0x00FF00FF00FF00FF)) << 8); 108 | value = ((value & W64LIT(0xFFFF0000FFFF0000)) >> 16) | ((value & W64LIT(0x0000FFFF0000FFFF)) << 16); 109 | return rotlFixed(value, 32U); 110 | #endif 111 | } 112 | #endif 113 | 114 | 115 | // 116 | // SHA 117 | // 118 | 119 | // http://www.weidai.com/scan-mirror/md.html#SHA-1 120 | class SHA1 121 | { 122 | public: 123 | typedef word32 HashWordType; 124 | static void InitState(word32 *state); 125 | static void Transform(word32 *digest, const word32 *data); 126 | static const char * StaticAlgorithmName() {return "SHA-1";} 127 | }; 128 | 129 | typedef SHA1 SHA; // for backwards compatibility 130 | 131 | // implements the SHA-256 standard 132 | class SHA256 133 | { 134 | public: 135 | typedef word32 HashWordType; 136 | static void InitState(word32 *state); 137 | static void Transform(word32 *digest, const word32 *data); 138 | static const char * StaticAlgorithmName() {return "SHA-256";} 139 | }; 140 | 141 | // implements the SHA-224 standard 142 | class SHA224 143 | { 144 | public: 145 | typedef word32 HashWordType; 146 | static void InitState(word32 *state); 147 | static void Transform(word32 *digest, const word32 *data) {SHA256::Transform(digest, data);} 148 | static const char * StaticAlgorithmName() {return "SHA-224";} 149 | }; 150 | 151 | #ifdef WORD64_AVAILABLE 152 | 153 | // implements the SHA-512 standard 154 | class SHA512 155 | { 156 | public: 157 | typedef word64 HashWordType; 158 | static void InitState(word64 *state); 159 | static void Transform(word64 *digest, const word64 *data); 160 | static const char * StaticAlgorithmName() {return "SHA-512";} 161 | }; 162 | 163 | // implements the SHA-384 standard 164 | class SHA384 165 | { 166 | public: 167 | typedef word64 HashWordType; 168 | static void InitState(word64 *state); 169 | static void Transform(word64 *digest, const word64 *data) {SHA512::Transform(digest, data);} 170 | static const char * StaticAlgorithmName() {return "SHA-384";} 171 | }; 172 | 173 | #endif 174 | 175 | } 176 | 177 | #endif 178 | -------------------------------------------------------------------------------- /src/ui.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trottier/original-bitcoin/92ee8d9a994391d148733da77e2bbc2f4acc43cd/src/ui.cpp -------------------------------------------------------------------------------- /src/ui.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 Satoshi Nakamoto 2 | // Distributed under the MIT/X11 software license, see the accompanying 3 | // file license.txt or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | 6 | 7 | 8 | DECLARE_EVENT_TYPE(wxEVT_CROSSTHREADCALL, -1) 9 | DECLARE_EVENT_TYPE(wxEVT_REPLY1, -1) 10 | DECLARE_EVENT_TYPE(wxEVT_REPLY2, -1) 11 | DECLARE_EVENT_TYPE(wxEVT_REPLY3, -1) 12 | DECLARE_EVENT_TYPE(wxEVT_TABLEADDED, -1) 13 | DECLARE_EVENT_TYPE(wxEVT_TABLEUPDATED, -1) 14 | DECLARE_EVENT_TYPE(wxEVT_TABLEDELETED, -1) 15 | 16 | enum 17 | { 18 | UICALL_ADDORDER = 1, 19 | UICALL_UPDATEORDER, 20 | }; 21 | 22 | 23 | 24 | extern void HandleCtrlA(wxKeyEvent& event); 25 | extern string DateTimeStr(int64 nTime); 26 | extern string FormatTxStatus(const CWalletTx& wtx); 27 | extern void CrossThreadCall(int nID, void* pdata); 28 | extern void MainFrameRepaint(); 29 | extern void Shutdown(void* parg); 30 | 31 | 32 | 33 | 34 | 35 | 36 | class CMainFrame : public CMainFrameBase 37 | { 38 | protected: 39 | // Event handlers 40 | void OnClose(wxCloseEvent& event); 41 | void OnMouseEvents(wxMouseEvent& event); 42 | void OnKeyDown(wxKeyEvent& event) { HandleCtrlA(event); } 43 | void OnIdle(wxIdleEvent& event); 44 | void OnPaint(wxPaintEvent& event); 45 | void OnPaintListCtrl(wxPaintEvent& event); 46 | void OnMenuFileExit(wxCommandEvent& event); 47 | void OnMenuOptionsGenerate(wxCommandEvent& event); 48 | void OnMenuOptionsOptions(wxCommandEvent& event); 49 | void OnMenuHelpAbout(wxCommandEvent& event); 50 | void OnButtonSend(wxCommandEvent& event); 51 | void OnButtonAddressBook(wxCommandEvent& event); 52 | void OnSetFocusAddress(wxFocusEvent& event); 53 | void OnMouseEventsAddress(wxMouseEvent& event); 54 | void OnButtonCopy(wxCommandEvent& event); 55 | void OnButtonChange(wxCommandEvent& event); 56 | void OnListColBeginDrag(wxListEvent& event); 57 | void OnListItemActivatedAllTransactions(wxListEvent& event); 58 | void OnListItemActivatedProductsSent(wxListEvent& event); 59 | void OnListItemActivatedOrdersSent(wxListEvent& event); 60 | void OnListItemActivatedOrdersReceived(wxListEvent& event); 61 | 62 | public: 63 | /** Constructor */ 64 | CMainFrame(wxWindow* parent); 65 | ~CMainFrame(); 66 | 67 | // Custom 68 | bool fRefreshListCtrl; 69 | bool fRefreshListCtrlRunning; 70 | bool fOnSetFocusAddress; 71 | CBlockIndex* pindexBestLast; 72 | set setUnmaturedDisplayed; 73 | 74 | void OnCrossThreadCall(wxCommandEvent& event); 75 | void InsertLine(bool fNew, int nIndex, uint256 hashKey, string strSort, const wxString& str1, const wxString& str2, const wxString& str3, const wxString& str4, const wxString& str5); 76 | void InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex=-1); 77 | void RefreshListCtrl(); 78 | void RefreshStatus(); 79 | }; 80 | 81 | 82 | 83 | 84 | class CTxDetailsDialog : public CTxDetailsDialogBase 85 | { 86 | protected: 87 | // Event handlers 88 | void OnButtonOK(wxCommandEvent& event); 89 | 90 | public: 91 | /** Constructor */ 92 | CTxDetailsDialog(wxWindow* parent, CWalletTx wtx); 93 | 94 | // State 95 | CWalletTx wtx; 96 | }; 97 | 98 | 99 | 100 | class COptionsDialog : public COptionsDialogBase 101 | { 102 | protected: 103 | // Event handlers 104 | void OnKillFocusTransactionFee(wxFocusEvent& event); 105 | void OnButtonOK(wxCommandEvent& event); 106 | void OnButtonCancel(wxCommandEvent& event); 107 | 108 | public: 109 | /** Constructor */ 110 | COptionsDialog(wxWindow* parent); 111 | }; 112 | 113 | 114 | 115 | class CAboutDialog : public CAboutDialogBase 116 | { 117 | protected: 118 | // Event handlers 119 | void OnButtonOK(wxCommandEvent& event); 120 | 121 | public: 122 | /** Constructor */ 123 | CAboutDialog(wxWindow* parent); 124 | }; 125 | 126 | 127 | 128 | class CSendDialog : public CSendDialogBase 129 | { 130 | protected: 131 | // Event handlers 132 | void OnKeyDown(wxKeyEvent& event) { HandleCtrlA(event); } 133 | void OnTextAddress(wxCommandEvent& event); 134 | void OnKillFocusAmount(wxFocusEvent& event); 135 | void OnButtonAddressBook(wxCommandEvent& event); 136 | void OnButtonPaste(wxCommandEvent& event); 137 | void OnButtonSend(wxCommandEvent& event); 138 | void OnButtonCancel(wxCommandEvent& event); 139 | 140 | public: 141 | /** Constructor */ 142 | CSendDialog(wxWindow* parent, const wxString& strAddress=""); 143 | }; 144 | 145 | 146 | 147 | class CSendingDialog : public CSendingDialogBase 148 | { 149 | public: 150 | // Event handlers 151 | void OnClose(wxCloseEvent& event); 152 | void OnButtonOK(wxCommandEvent& event); 153 | void OnButtonCancel(wxCommandEvent& event); 154 | void OnPaint(wxPaintEvent& event); 155 | 156 | public: 157 | /** Constructor */ 158 | CSendingDialog(wxWindow* parent, const CAddress& addrIn, int64 nPriceIn, const CWalletTx& wtxIn); 159 | ~CSendingDialog(); 160 | 161 | // State 162 | CAddress addr; 163 | int64 nPrice; 164 | CWalletTx wtx; 165 | wxDateTime start; 166 | string strStatus; 167 | bool fCanCancel; 168 | bool fAbort; 169 | bool fSuccess; 170 | bool fUIDone; 171 | bool fWorkDone; 172 | 173 | void Close(); 174 | void Repaint(); 175 | bool Status(); 176 | bool Status(const string& str); 177 | bool Error(const string& str); 178 | void StartTransfer(); 179 | void OnReply2(CDataStream& vRecv); 180 | void OnReply3(CDataStream& vRecv); 181 | }; 182 | 183 | void SendingDialogStartTransfer(void* parg); 184 | void SendingDialogOnReply2(void* parg, CDataStream& vRecv); 185 | void SendingDialogOnReply3(void* parg, CDataStream& vRecv); 186 | 187 | 188 | 189 | class CYourAddressDialog : public CYourAddressDialogBase 190 | { 191 | protected: 192 | // Event handlers 193 | void OnListEndLabelEdit(wxListEvent& event); 194 | void OnListItemSelected(wxListEvent& event); 195 | void OnListItemActivated(wxListEvent& event); 196 | void OnButtonRename(wxCommandEvent& event); 197 | void OnButtonNew(wxCommandEvent& event); 198 | void OnButtonCopy(wxCommandEvent& event); 199 | void OnButtonOK(wxCommandEvent& event); 200 | void OnButtonCancel(wxCommandEvent& event); 201 | void OnClose(wxCloseEvent& event); 202 | 203 | public: 204 | /** Constructor */ 205 | CYourAddressDialog(wxWindow* parent); 206 | CYourAddressDialog(wxWindow* parent, const string& strInitSelected); 207 | 208 | // Custom 209 | wxString GetAddress(); 210 | }; 211 | 212 | 213 | 214 | class CAddressBookDialog : public CAddressBookDialogBase 215 | { 216 | protected: 217 | // Event handlers 218 | void OnListEndLabelEdit(wxListEvent& event); 219 | void OnListItemSelected(wxListEvent& event); 220 | void OnListItemActivated(wxListEvent& event); 221 | void OnButtonEdit(wxCommandEvent& event); 222 | void OnButtonDelete(wxCommandEvent& event); 223 | void OnButtonNew(wxCommandEvent& event); 224 | void OnButtonCopy(wxCommandEvent& event); 225 | void OnButtonOK(wxCommandEvent& event); 226 | void OnButtonCancel(wxCommandEvent& event); 227 | void OnClose(wxCloseEvent& event); 228 | 229 | public: 230 | /** Constructor */ 231 | CAddressBookDialog(wxWindow* parent, const wxString& strInitSelected, bool fSendingIn); 232 | 233 | // Custom 234 | bool fSending; 235 | wxString GetAddress(); 236 | }; 237 | 238 | 239 | 240 | class CProductsDialog : public CProductsDialogBase 241 | { 242 | protected: 243 | // Event handlers 244 | void OnKeyDown(wxKeyEvent& event) { HandleCtrlA(event); } 245 | void OnCombobox(wxCommandEvent& event); 246 | void OnButtonSearch(wxCommandEvent& event); 247 | void OnListItemActivated(wxListEvent& event); 248 | 249 | public: 250 | /** Constructor */ 251 | CProductsDialog(wxWindow* parent); 252 | 253 | // Custom 254 | vector m_vProduct; 255 | }; 256 | 257 | 258 | 259 | class CEditProductDialog : public CEditProductDialogBase 260 | { 261 | protected: 262 | // Event handlers 263 | void OnKeyDown(wxKeyEvent& event) { HandleCtrlA(event); } 264 | void OnButtonDel0(wxCommandEvent& event); 265 | void OnButtonDel1(wxCommandEvent& event); 266 | void OnButtonDel2(wxCommandEvent& event); 267 | void OnButtonDel3(wxCommandEvent& event); 268 | void OnButtonDel4(wxCommandEvent& event); 269 | void OnButtonDel5(wxCommandEvent& event); 270 | void OnButtonDel6(wxCommandEvent& event); 271 | void OnButtonDel7(wxCommandEvent& event); 272 | void OnButtonDel8(wxCommandEvent& event); 273 | void OnButtonDel9(wxCommandEvent& event); 274 | void OnButtonDel10(wxCommandEvent& event); 275 | void OnButtonDel11(wxCommandEvent& event); 276 | void OnButtonDel12(wxCommandEvent& event); 277 | void OnButtonDel13(wxCommandEvent& event); 278 | void OnButtonDel14(wxCommandEvent& event); 279 | void OnButtonDel15(wxCommandEvent& event); 280 | void OnButtonDel16(wxCommandEvent& event); 281 | void OnButtonDel17(wxCommandEvent& event); 282 | void OnButtonDel18(wxCommandEvent& event); 283 | void OnButtonDel19(wxCommandEvent& event); 284 | void OnButtonAddField(wxCommandEvent& event); 285 | void OnButtonSend(wxCommandEvent& event); 286 | void OnButtonPreview(wxCommandEvent& event); 287 | void OnButtonCancel(wxCommandEvent& event); 288 | 289 | public: 290 | /** Constructor */ 291 | CEditProductDialog(wxWindow* parent); 292 | 293 | // Custom 294 | enum { FIELDS_MAX = 20 }; 295 | wxTextCtrl* m_textCtrlLabel[FIELDS_MAX]; 296 | wxTextCtrl* m_textCtrlField[FIELDS_MAX]; 297 | wxButton* m_buttonDel[FIELDS_MAX]; 298 | 299 | void LayoutAll(); 300 | void ShowLine(int i, bool fShow=true); 301 | void OnButtonDel(wxCommandEvent& event, int n); 302 | void SetProduct(const CProduct& productIn); 303 | void GetProduct(CProduct& product); 304 | 305 | }; 306 | 307 | 308 | 309 | class CViewProductDialog : public CViewProductDialogBase 310 | { 311 | protected: 312 | // Event handlers 313 | void OnButtonSubmitForm(wxCommandEvent& event); 314 | void OnButtonCancelForm(wxCommandEvent& event); 315 | void OnButtonBack(wxCommandEvent& event); 316 | void OnButtonNext(wxCommandEvent& event); 317 | void OnButtonCancel(wxCommandEvent& event); 318 | 319 | public: 320 | /** Constructor */ 321 | CViewProductDialog(wxWindow* parent, const CProduct& productIn); 322 | ~CViewProductDialog(); 323 | 324 | // Custom 325 | CProduct product; 326 | enum { FIELDS_MAX = 20 }; 327 | wxStaticText* m_staticTextLabel[FIELDS_MAX]; 328 | wxTextCtrl* m_textCtrlField[FIELDS_MAX]; 329 | wxChoice* m_choiceField[FIELDS_MAX]; 330 | 331 | void GetOrder(CWalletTx& order); 332 | void UpdateProductDisplay(bool fDetails); 333 | void OnReply1(wxCommandEvent& event); 334 | }; 335 | 336 | 337 | 338 | class CViewOrderDialog : public CViewOrderDialogBase 339 | { 340 | protected: 341 | // Event handlers 342 | void OnButtonOK(wxCommandEvent& event); 343 | 344 | public: 345 | /** Constructor */ 346 | CViewOrderDialog(wxWindow* parent, CWalletTx order, bool fReceived); 347 | 348 | // Custom 349 | bool fReceived; 350 | }; 351 | 352 | 353 | 354 | class CEditReviewDialog : public CEditReviewDialogBase 355 | { 356 | protected: 357 | // Event handlers 358 | void OnKeyDown(wxKeyEvent& event) { HandleCtrlA(event); } 359 | void OnButtonSubmit(wxCommandEvent& event); 360 | void OnButtonCancel(wxCommandEvent& event); 361 | 362 | public: 363 | /** Constructor */ 364 | CEditReviewDialog(wxWindow* parent); 365 | 366 | // Custom 367 | void GetReview(CReview& review); 368 | }; 369 | 370 | 371 | 372 | class CGetTextFromUserDialog : public CGetTextFromUserDialogBase 373 | { 374 | protected: 375 | // Event handlers 376 | void OnButtonOK(wxCommandEvent& event) { EndModal(true); } 377 | void OnButtonCancel(wxCommandEvent& event) { EndModal(false); } 378 | void OnClose(wxCloseEvent& event) { EndModal(false); } 379 | 380 | void OnKeyDown(wxKeyEvent& event) 381 | { 382 | if (event.GetKeyCode() == '\r' || event.GetKeyCode() == WXK_NUMPAD_ENTER) 383 | EndModal(true); 384 | else 385 | HandleCtrlA(event); 386 | } 387 | 388 | public: 389 | /** Constructor */ 390 | CGetTextFromUserDialog(wxWindow* parent, 391 | const string& strCaption, 392 | const string& strMessage1, 393 | const string& strValue1="", 394 | const string& strMessage2="", 395 | const string& strValue2="") : CGetTextFromUserDialogBase(parent, wxID_ANY, strCaption) 396 | { 397 | m_staticTextMessage1->SetLabel(strMessage1); 398 | m_textCtrl1->SetValue(strValue1); 399 | if (!strMessage2.empty()) 400 | { 401 | m_staticTextMessage2->Show(true); 402 | m_staticTextMessage2->SetLabel(strMessage2); 403 | m_textCtrl2->Show(true); 404 | m_textCtrl2->SetValue(strValue2); 405 | SetSize(wxDefaultCoord, 180); 406 | } 407 | } 408 | 409 | // Custom 410 | string GetValue() { return (string)m_textCtrl1->GetValue(); } 411 | string GetValue1() { return (string)m_textCtrl1->GetValue(); } 412 | string GetValue2() { return (string)m_textCtrl2->GetValue(); } 413 | }; 414 | 415 | 416 | 417 | 418 | 419 | -------------------------------------------------------------------------------- /src/ui.rc: -------------------------------------------------------------------------------- 1 | bitcoin ICON "rc/bitcoin.ico" 2 | 3 | #include "wx/msw/wx.rc" 4 | 5 | check ICON "rc/check.ico" 6 | send16 BITMAP "rc/send16.bmp" 7 | send16mask BITMAP "rc/send16mask.bmp" 8 | send16masknoshadow BITMAP "rc/send16masknoshadow.bmp" 9 | send20 BITMAP "rc/send20.bmp" 10 | send20mask BITMAP "rc/send20mask.bmp" 11 | addressbook16 BITMAP "rc/addressbook16.bmp" 12 | addressbook16mask BITMAP "rc/addressbook16mask.bmp" 13 | addressbook20 BITMAP "rc/addressbook20.bmp" 14 | addressbook20mask BITMAP "rc/addressbook20mask.bmp" 15 | -------------------------------------------------------------------------------- /src/util.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 Satoshi Nakamoto 2 | // Distributed under the MIT/X11 software license, see the accompanying 3 | // file license.txt or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "headers.h" 6 | 7 | 8 | 9 | bool fDebug = false; 10 | 11 | 12 | 13 | 14 | // Init openssl library multithreading support 15 | static HANDLE* lock_cs; 16 | 17 | void win32_locking_callback(int mode, int type, const char* file, int line) 18 | { 19 | if (mode & CRYPTO_LOCK) 20 | WaitForSingleObject(lock_cs[type], INFINITE); 21 | else 22 | ReleaseMutex(lock_cs[type]); 23 | } 24 | 25 | // Init 26 | class CInit 27 | { 28 | public: 29 | CInit() 30 | { 31 | // Init openssl library multithreading support 32 | lock_cs = (HANDLE*)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(HANDLE)); 33 | for (int i = 0; i < CRYPTO_num_locks(); i++) 34 | lock_cs[i] = CreateMutex(NULL,FALSE,NULL); 35 | CRYPTO_set_locking_callback(win32_locking_callback); 36 | 37 | // Seed random number generator with screen scrape and other hardware sources 38 | RAND_screen(); 39 | 40 | // Seed random number generator with perfmon data 41 | RandAddSeed(true); 42 | } 43 | ~CInit() 44 | { 45 | // Shutdown openssl library multithreading support 46 | CRYPTO_set_locking_callback(NULL); 47 | for (int i =0 ; i < CRYPTO_num_locks(); i++) 48 | CloseHandle(lock_cs[i]); 49 | OPENSSL_free(lock_cs); 50 | } 51 | } 52 | instance_of_cinit; 53 | 54 | 55 | 56 | 57 | void RandAddSeed(bool fPerfmon) 58 | { 59 | // Seed with CPU performance counter 60 | LARGE_INTEGER PerformanceCount; 61 | QueryPerformanceCounter(&PerformanceCount); 62 | RAND_add(&PerformanceCount, sizeof(PerformanceCount), 1.5); 63 | memset(&PerformanceCount, 0, sizeof(PerformanceCount)); 64 | 65 | static int64 nLastPerfmon; 66 | if (fPerfmon || GetTime() > nLastPerfmon + 5 * 60) 67 | { 68 | nLastPerfmon = GetTime(); 69 | 70 | // Seed with the entire set of perfmon data 71 | unsigned char pdata[250000]; 72 | memset(pdata, 0, sizeof(pdata)); 73 | unsigned long nSize = sizeof(pdata); 74 | long ret = RegQueryValueEx(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize); 75 | RegCloseKey(HKEY_PERFORMANCE_DATA); 76 | if (ret == ERROR_SUCCESS) 77 | { 78 | uint256 hash; 79 | SHA256(pdata, nSize, (unsigned char*)&hash); 80 | RAND_add(&hash, sizeof(hash), min(nSize/500.0, (double)sizeof(hash))); 81 | hash = 0; 82 | memset(pdata, 0, nSize); 83 | 84 | time_t nTime; 85 | time(&nTime); 86 | struct tm* ptmTime = gmtime(&nTime); 87 | char pszTime[200]; 88 | strftime(pszTime, sizeof(pszTime), "%x %H:%M:%S", ptmTime); 89 | printf("%s RandAddSeed() got %d bytes of performance data\n", pszTime, nSize); 90 | } 91 | } 92 | } 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | // Safer snprintf 104 | // - prints up to limit-1 characters 105 | // - output string is always null terminated even if limit reached 106 | // - return value is the number of characters actually printed 107 | int my_snprintf(char* buffer, size_t limit, const char* format, ...) 108 | { 109 | if (limit == 0) 110 | return 0; 111 | va_list arg_ptr; 112 | va_start(arg_ptr, format); 113 | int ret = _vsnprintf(buffer, limit, format, arg_ptr); 114 | va_end(arg_ptr); 115 | if (ret < 0 || ret >= limit) 116 | { 117 | ret = limit - 1; 118 | buffer[limit-1] = 0; 119 | } 120 | return ret; 121 | } 122 | 123 | 124 | string strprintf(const char* format, ...) 125 | { 126 | char buffer[50000]; 127 | char* p = buffer; 128 | int limit = sizeof(buffer); 129 | int ret; 130 | loop 131 | { 132 | va_list arg_ptr; 133 | va_start(arg_ptr, format); 134 | ret = _vsnprintf(p, limit, format, arg_ptr); 135 | va_end(arg_ptr); 136 | if (ret >= 0 && ret < limit) 137 | break; 138 | if (p != buffer) 139 | delete p; 140 | limit *= 2; 141 | p = new char[limit]; 142 | if (p == NULL) 143 | throw std::bad_alloc(); 144 | } 145 | #ifdef _MSC_VER 146 | // msvc optimisation 147 | if (p == buffer) 148 | return string(p, p+ret); 149 | #endif 150 | string str(p, p+ret); 151 | if (p != buffer) 152 | delete p; 153 | return str; 154 | } 155 | 156 | 157 | bool error(const char* format, ...) 158 | { 159 | char buffer[50000]; 160 | int limit = sizeof(buffer); 161 | va_list arg_ptr; 162 | va_start(arg_ptr, format); 163 | int ret = _vsnprintf(buffer, limit, format, arg_ptr); 164 | va_end(arg_ptr); 165 | if (ret < 0 || ret >= limit) 166 | { 167 | ret = limit - 1; 168 | buffer[limit-1] = 0; 169 | } 170 | printf("ERROR: %s\n", buffer); 171 | return false; 172 | } 173 | 174 | 175 | void PrintException(std::exception* pex, const char* pszThread) 176 | { 177 | char pszModule[260]; 178 | pszModule[0] = '\0'; 179 | GetModuleFileName(NULL, pszModule, sizeof(pszModule)); 180 | _strlwr(pszModule); 181 | char pszMessage[1000]; 182 | if (pex) 183 | snprintf(pszMessage, sizeof(pszMessage), 184 | "EXCEPTION: %s \n%s \n%s in %s \n", typeid(*pex).name(), pex->what(), pszModule, pszThread); 185 | else 186 | snprintf(pszMessage, sizeof(pszMessage), 187 | "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread); 188 | printf("\n\n************************\n%s", pszMessage); 189 | if (wxTheApp) 190 | wxMessageBox(pszMessage, "Error", wxOK | wxICON_ERROR); 191 | throw; 192 | //DebugBreak(); 193 | } 194 | 195 | 196 | void ParseString(const string& str, char c, vector& v) 197 | { 198 | unsigned int i1 = 0; 199 | unsigned int i2; 200 | do 201 | { 202 | i2 = str.find(c, i1); 203 | v.push_back(str.substr(i1, i2-i1)); 204 | i1 = i2+1; 205 | } 206 | while (i2 != str.npos); 207 | } 208 | 209 | 210 | string FormatMoney(int64 n, bool fPlus) 211 | { 212 | n /= CENT; 213 | string str = strprintf("%I64d.%02I64d", (n > 0 ? n : -n)/100, (n > 0 ? n : -n)%100); 214 | for (int i = 6; i < str.size(); i += 4) 215 | if (isdigit(str[str.size() - i - 1])) 216 | str.insert(str.size() - i, 1, ','); 217 | if (n < 0) 218 | str.insert((unsigned int)0, 1, '-'); 219 | else if (fPlus && n > 0) 220 | str.insert((unsigned int)0, 1, '+'); 221 | return str; 222 | } 223 | 224 | bool ParseMoney(const char* pszIn, int64& nRet) 225 | { 226 | string strWhole; 227 | int64 nCents = 0; 228 | const char* p = pszIn; 229 | while (isspace(*p)) 230 | p++; 231 | for (; *p; p++) 232 | { 233 | if (*p == ',' && p > pszIn && isdigit(p[-1]) && isdigit(p[1]) && isdigit(p[2]) && isdigit(p[3]) && !isdigit(p[4])) 234 | continue; 235 | if (*p == '.') 236 | { 237 | p++; 238 | if (!isdigit(p[0]) || !isdigit(p[1])) 239 | return false; 240 | nCents = atoi64(p); 241 | if (nCents < 0 || nCents > 99) 242 | return false; 243 | p += 2; 244 | break; 245 | } 246 | if (isspace(*p)) 247 | break; 248 | if (!isdigit(*p)) 249 | return false; 250 | strWhole.insert(strWhole.end(), *p); 251 | } 252 | for (; *p; p++) 253 | if (!isspace(*p)) 254 | return false; 255 | if (strWhole.size() > 17) 256 | return false; 257 | int64 nWhole = atoi64(strWhole); 258 | int64 nValue = nWhole * 100 + nCents; 259 | if (nValue / 100 != nWhole) 260 | return false; 261 | nValue *= CENT; 262 | nRet = nValue; 263 | return true; 264 | } 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | bool FileExists(const char* psz) 276 | { 277 | #ifdef WIN32 278 | return GetFileAttributes(psz) != -1; 279 | #else 280 | return access(psz, 0) != -1; 281 | #endif 282 | } 283 | 284 | int GetFilesize(FILE* file) 285 | { 286 | int nSavePos = ftell(file); 287 | int nFilesize = -1; 288 | if (fseek(file, 0, SEEK_END) == 0) 289 | nFilesize = ftell(file); 290 | fseek(file, nSavePos, SEEK_SET); 291 | return nFilesize; 292 | } 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | uint64 GetRand(uint64 nMax) 302 | { 303 | if (nMax == 0) 304 | return 0; 305 | 306 | // The range of the random source must be a multiple of the modulus 307 | // to give every possible output value an equal possibility 308 | uint64 nRange = (_UI64_MAX / nMax) * nMax; 309 | uint64 nRand = 0; 310 | do 311 | RAND_bytes((unsigned char*)&nRand, sizeof(nRand)); 312 | while (nRand >= nRange); 313 | return (nRand % nMax); 314 | } 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | // 326 | // "Never go to sea with two chronometers; take one or three." 327 | // Our three chronometers are: 328 | // - System clock 329 | // - Median of other server's clocks 330 | // - NTP servers 331 | // 332 | // note: NTP isn't implemented yet, so until then we just use the median 333 | // of other nodes clocks to correct ours. 334 | // 335 | 336 | int64 GetTime() 337 | { 338 | return time(NULL); 339 | } 340 | 341 | static int64 nTimeOffset = 0; 342 | 343 | int64 GetAdjustedTime() 344 | { 345 | return GetTime() + nTimeOffset; 346 | } 347 | 348 | void AddTimeData(unsigned int ip, int64 nTime) 349 | { 350 | int64 nOffsetSample = nTime - GetTime(); 351 | 352 | // Ignore duplicates 353 | static set setKnown; 354 | if (!setKnown.insert(ip).second) 355 | return; 356 | 357 | // Add data 358 | static vector vTimeOffsets; 359 | if (vTimeOffsets.empty()) 360 | vTimeOffsets.push_back(0); 361 | vTimeOffsets.push_back(nOffsetSample); 362 | printf("Added time data, samples %d, ip %08x, offset %+I64d (%+I64d minutes)\n", vTimeOffsets.size(), ip, vTimeOffsets.back(), vTimeOffsets.back()/60); 363 | if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1) 364 | { 365 | sort(vTimeOffsets.begin(), vTimeOffsets.end()); 366 | int64 nMedian = vTimeOffsets[vTimeOffsets.size()/2]; 367 | nTimeOffset = nMedian; 368 | if ((nMedian > 0 ? nMedian : -nMedian) > 5 * 60) 369 | { 370 | // Only let other nodes change our clock so far before we 371 | // go to the NTP servers 372 | /// todo: Get time from NTP servers, then set a flag 373 | /// to make sure it doesn't get changed again 374 | } 375 | foreach(int64 n, vTimeOffsets) 376 | printf("%+I64d ", n); 377 | printf("| nTimeOffset = %+I64d (%+I64d minutes)\n", nTimeOffset, nTimeOffset/60); 378 | } 379 | } 380 | -------------------------------------------------------------------------------- /src/util.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 Satoshi Nakamoto 2 | // Distributed under the MIT/X11 software license, see the accompanying 3 | // file license.txt or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | 6 | #if defined(_MSC_VER) || defined(__BORLANDC__) 7 | typedef __int64 int64; 8 | typedef unsigned __int64 uint64; 9 | #else 10 | typedef long long int64; 11 | typedef unsigned long long uint64; 12 | #endif 13 | #if defined(_MSC_VER) && _MSC_VER < 1300 14 | #define for if (false) ; else for 15 | #endif 16 | 17 | #ifndef _MSC_VER 18 | #define __forceinline inline 19 | #endif 20 | 21 | #define foreach BOOST_FOREACH 22 | #define loop for (;;) 23 | #define BEGIN(a) ((char*)&(a)) 24 | #define END(a) ((char*)&((&(a))[1])) 25 | #define UBEGIN(a) ((unsigned char*)&(a)) 26 | #define UEND(a) ((unsigned char*)&((&(a))[1])) 27 | #define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0])) 28 | 29 | #ifdef _WINDOWS 30 | #define printf OutputDebugStringF 31 | #endif 32 | 33 | #ifdef snprintf 34 | #undef snprintf 35 | #endif 36 | #define snprintf my_snprintf 37 | 38 | #ifndef PRId64 39 | #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MSVCRT__) 40 | #define PRId64 "I64d" 41 | #define PRIu64 "I64u" 42 | #define PRIx64 "I64x" 43 | #else 44 | #define PRId64 "lld" 45 | #define PRIu64 "llu" 46 | #define PRIx64 "llx" 47 | #endif 48 | #endif 49 | 50 | // This is needed because the foreach macro can't get over the comma in pair 51 | #define PAIRTYPE(t1, t2) pair 52 | 53 | // Used to bypass the rule against non-const reference to temporary 54 | // where it makes sense with wrappers such as CFlatData or CTxDB 55 | template 56 | inline T& REF(const T& val) 57 | { 58 | return (T&)val; 59 | } 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | extern bool fDebug; 70 | 71 | void RandAddSeed(bool fPerfmon=false); 72 | int my_snprintf(char* buffer, size_t limit, const char* format, ...); 73 | string strprintf(const char* format, ...); 74 | bool error(const char* format, ...); 75 | void PrintException(std::exception* pex, const char* pszThread); 76 | void ParseString(const string& str, char c, vector& v); 77 | string FormatMoney(int64 n, bool fPlus=false); 78 | bool ParseMoney(const char* pszIn, int64& nRet); 79 | bool FileExists(const char* psz); 80 | int GetFilesize(FILE* file); 81 | uint64 GetRand(uint64 nMax); 82 | int64 GetTime(); 83 | int64 GetAdjustedTime(); 84 | void AddTimeData(unsigned int ip, int64 nTime); 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | // Wrapper to automatically initialize critical section 98 | // Could use wxCriticalSection for portability, but it doesn't support TryEnterCriticalSection 99 | class CCriticalSection 100 | { 101 | protected: 102 | CRITICAL_SECTION cs; 103 | public: 104 | char* pszFile; 105 | int nLine; 106 | explicit CCriticalSection() { InitializeCriticalSection(&cs); } 107 | ~CCriticalSection() { DeleteCriticalSection(&cs); } 108 | void Enter() { EnterCriticalSection(&cs); } 109 | void Leave() { LeaveCriticalSection(&cs); } 110 | bool TryEnter() { return TryEnterCriticalSection(&cs); } 111 | CRITICAL_SECTION* operator&() { return &cs; } 112 | }; 113 | 114 | // Automatically leave critical section when leaving block, needed for exception safety 115 | class CCriticalBlock 116 | { 117 | protected: 118 | CRITICAL_SECTION* pcs; 119 | public: 120 | CCriticalBlock(CRITICAL_SECTION& csIn) { pcs = &csIn; EnterCriticalSection(pcs); } 121 | CCriticalBlock(CCriticalSection& csIn) { pcs = &csIn; EnterCriticalSection(pcs); } 122 | ~CCriticalBlock() { LeaveCriticalSection(pcs); } 123 | }; 124 | 125 | // WARNING: This will catch continue and break! 126 | // break is caught with an assertion, but there's no way to detect continue. 127 | // I'd rather be careful than suffer the other more error prone syntax. 128 | // The compiler will optimise away all this loop junk. 129 | #define CRITICAL_BLOCK(cs) \ 130 | for (bool fcriticalblockonce=true; fcriticalblockonce; assert(("break caught by CRITICAL_BLOCK!", !fcriticalblockonce)), fcriticalblockonce=false) \ 131 | for (CCriticalBlock criticalblock(cs); fcriticalblockonce && (cs.pszFile=__FILE__, cs.nLine=__LINE__, true); fcriticalblockonce=false, cs.pszFile=NULL, cs.nLine=0) 132 | 133 | class CTryCriticalBlock 134 | { 135 | protected: 136 | CRITICAL_SECTION* pcs; 137 | public: 138 | CTryCriticalBlock(CRITICAL_SECTION& csIn) { pcs = (TryEnterCriticalSection(&csIn) ? &csIn : NULL); } 139 | CTryCriticalBlock(CCriticalSection& csIn) { pcs = (TryEnterCriticalSection(&csIn) ? &csIn : NULL); } 140 | ~CTryCriticalBlock() { if (pcs) LeaveCriticalSection(pcs); } 141 | bool Entered() { return pcs != NULL; } 142 | }; 143 | 144 | #define TRY_CRITICAL_BLOCK(cs) \ 145 | for (bool fcriticalblockonce=true; fcriticalblockonce; assert(("break caught by TRY_CRITICAL_BLOCK!", !fcriticalblockonce)), fcriticalblockonce=false) \ 146 | for (CTryCriticalBlock criticalblock(cs); fcriticalblockonce && (fcriticalblockonce = criticalblock.Entered()) && (cs.pszFile=__FILE__, cs.nLine=__LINE__, true); fcriticalblockonce=false, cs.pszFile=NULL, cs.nLine=0) 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | inline string i64tostr(int64 n) 160 | { 161 | return strprintf("%"PRId64, n); 162 | } 163 | 164 | inline string itostr(int n) 165 | { 166 | return strprintf("%d", n); 167 | } 168 | 169 | inline int64 atoi64(const char* psz) 170 | { 171 | #ifdef _MSC_VER 172 | return _atoi64(psz); 173 | #else 174 | return strtoll(psz, NULL, 10); 175 | #endif 176 | } 177 | 178 | inline int64 atoi64(const string& str) 179 | { 180 | #ifdef _MSC_VER 181 | return _atoi64(str.c_str()); 182 | #else 183 | return strtoll(str.c_str(), NULL, 10); 184 | #endif 185 | } 186 | 187 | inline int atoi(const string& str) 188 | { 189 | return atoi(str.c_str()); 190 | } 191 | 192 | inline int roundint(double d) 193 | { 194 | return (int)(d > 0 ? d + 0.5 : d - 0.5); 195 | } 196 | 197 | template 198 | string HexStr(const T itbegin, const T itend, bool fSpaces=true) 199 | { 200 | const unsigned char* pbegin = (const unsigned char*)&itbegin[0]; 201 | const unsigned char* pend = pbegin + (itend - itbegin) * sizeof(itbegin[0]); 202 | string str; 203 | for (const unsigned char* p = pbegin; p != pend; p++) 204 | str += strprintf((fSpaces && p != pend-1 ? "%02x " : "%02x"), *p); 205 | return str; 206 | } 207 | 208 | template 209 | string HexNumStr(const T itbegin, const T itend, bool f0x=true) 210 | { 211 | const unsigned char* pbegin = (const unsigned char*)&itbegin[0]; 212 | const unsigned char* pend = pbegin + (itend - itbegin) * sizeof(itbegin[0]); 213 | string str = (f0x ? "0x" : ""); 214 | for (const unsigned char* p = pend-1; p >= pbegin; p--) 215 | str += strprintf("%02X", *p); 216 | return str; 217 | } 218 | 219 | template 220 | void PrintHex(const T pbegin, const T pend, const char* pszFormat="%s", bool fSpaces=true) 221 | { 222 | printf(pszFormat, HexStr(pbegin, pend, fSpaces).c_str()); 223 | } 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | inline int OutputDebugStringF(const char* pszFormat, ...) 233 | { 234 | #ifdef __WXDEBUG__ 235 | // log file 236 | FILE* fileout = fopen("debug.log", "a"); 237 | if (fileout) 238 | { 239 | va_list arg_ptr; 240 | va_start(arg_ptr, pszFormat); 241 | vfprintf(fileout, pszFormat, arg_ptr); 242 | va_end(arg_ptr); 243 | fclose(fileout); 244 | } 245 | 246 | // accumulate a line at a time 247 | static CCriticalSection cs_OutputDebugStringF; 248 | CRITICAL_BLOCK(cs_OutputDebugStringF) 249 | { 250 | static char pszBuffer[50000]; 251 | static char* pend; 252 | if (pend == NULL) 253 | pend = pszBuffer; 254 | va_list arg_ptr; 255 | va_start(arg_ptr, pszFormat); 256 | int limit = END(pszBuffer) - pend - 2; 257 | int ret = _vsnprintf(pend, limit, pszFormat, arg_ptr); 258 | va_end(arg_ptr); 259 | if (ret < 0 || ret >= limit) 260 | { 261 | pend = END(pszBuffer) - 2; 262 | *pend++ = '\n'; 263 | } 264 | else 265 | pend += ret; 266 | *pend = '\0'; 267 | char* p1 = pszBuffer; 268 | char* p2; 269 | while (p2 = strchr(p1, '\n')) 270 | { 271 | p2++; 272 | char c = *p2; 273 | *p2 = '\0'; 274 | OutputDebugString(p1); 275 | *p2 = c; 276 | p1 = p2; 277 | } 278 | if (p1 != pszBuffer) 279 | memmove(pszBuffer, p1, pend - p1 + 1); 280 | pend -= (p1 - pszBuffer); 281 | return ret; 282 | } 283 | #endif 284 | 285 | if (!wxTheApp) 286 | { 287 | // print to console 288 | va_list arg_ptr; 289 | va_start(arg_ptr, pszFormat); 290 | vprintf(pszFormat, arg_ptr); 291 | va_end(arg_ptr); 292 | } 293 | return 0; 294 | } 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | inline void heapchk() 305 | { 306 | if (_heapchk() != _HEAPOK) 307 | DebugBreak(); 308 | } 309 | 310 | // Randomize the stack to help protect against buffer overrun exploits 311 | #define IMPLEMENT_RANDOMIZE_STACK(ThreadFn) \ 312 | { \ 313 | static char nLoops; \ 314 | if (nLoops <= 0) \ 315 | nLoops = GetRand(50) + 1; \ 316 | if (nLoops-- > 1) \ 317 | { \ 318 | ThreadFn; \ 319 | return; \ 320 | } \ 321 | } 322 | 323 | #define CATCH_PRINT_EXCEPTION(pszFn) \ 324 | catch (std::exception& e) { \ 325 | PrintException(&e, (pszFn)); \ 326 | } catch (...) { \ 327 | PrintException(NULL, (pszFn)); \ 328 | } 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | template 339 | inline uint256 Hash(const T1 pbegin, const T1 pend) 340 | { 341 | uint256 hash1; 342 | SHA256((unsigned char*)&pbegin[0], (pend - pbegin) * sizeof(pbegin[0]), (unsigned char*)&hash1); 343 | uint256 hash2; 344 | SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); 345 | return hash2; 346 | } 347 | 348 | template 349 | inline uint256 Hash(const T1 p1begin, const T1 p1end, 350 | const T2 p2begin, const T2 p2end) 351 | { 352 | uint256 hash1; 353 | SHA256_CTX ctx; 354 | SHA256_Init(&ctx); 355 | SHA256_Update(&ctx, (unsigned char*)&p1begin[0], (p1end - p1begin) * sizeof(p1begin[0])); 356 | SHA256_Update(&ctx, (unsigned char*)&p2begin[0], (p2end - p2begin) * sizeof(p2begin[0])); 357 | SHA256_Final((unsigned char*)&hash1, &ctx); 358 | uint256 hash2; 359 | SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); 360 | return hash2; 361 | } 362 | 363 | template 364 | inline uint256 Hash(const T1 p1begin, const T1 p1end, 365 | const T2 p2begin, const T2 p2end, 366 | const T3 p3begin, const T3 p3end) 367 | { 368 | uint256 hash1; 369 | SHA256_CTX ctx; 370 | SHA256_Init(&ctx); 371 | SHA256_Update(&ctx, (unsigned char*)&p1begin[0], (p1end - p1begin) * sizeof(p1begin[0])); 372 | SHA256_Update(&ctx, (unsigned char*)&p2begin[0], (p2end - p2begin) * sizeof(p2begin[0])); 373 | SHA256_Update(&ctx, (unsigned char*)&p3begin[0], (p3end - p3begin) * sizeof(p3begin[0])); 374 | SHA256_Final((unsigned char*)&hash1, &ctx); 375 | uint256 hash2; 376 | SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); 377 | return hash2; 378 | } 379 | 380 | template 381 | uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=VERSION) 382 | { 383 | // Most of the time is spent allocating and deallocating CDataStream's 384 | // buffer. If this ever needs to be optimized further, make a CStaticStream 385 | // class with its buffer on the stack. 386 | CDataStream ss(nType, nVersion); 387 | ss.reserve(10000); 388 | ss << obj; 389 | return Hash(ss.begin(), ss.end()); 390 | } 391 | 392 | inline uint160 Hash160(const vector& vch) 393 | { 394 | uint256 hash1; 395 | SHA256(&vch[0], vch.size(), (unsigned char*)&hash1); 396 | uint160 hash2; 397 | RIPEMD160((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); 398 | return hash2; 399 | } 400 | --------------------------------------------------------------------------------