Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
- inline string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
- {
- CAutoBN_CTX pctx;
- CBigNum bn58 = 58;
- CBigNum bn0 = 0;
- vector<unsigned char> vchTmp(pend-pbegin+1, 0);
- reverse_copy(pbegin, pend, vchTmp.begin());
- CBigNum bn;
- bn.setvch(vchTmp);
- string str;
- str.reserve((pend - pbegin) * 138 / 100 + 1);
- CBigNum dv;
- CBigNum rem;
- while (bn > bn0)
- {
- if (!BN_div(&dv, &rem, &bn, &bn58, pctx))
- throw bignum_error("EncodeBase58 : BN_div failed");
- bn = dv;
- unsigned int c = rem.getulong();
- str += pszBase58[c];
- }
- for (const unsigned char* p = pbegin; p < pend && *p == 0; p++)
- str += pszBase58[0];
- reverse(str.begin(), str.end());
- return str;
- }
- inline string EncodeBase58(const vector<unsigned char>& vch)
- {
- return EncodeBase58(&vch[0], &vch[0] + vch.size());
- }
- inline bool DecodeBase58(const char* psz, vector<unsigned char>& vchRet)
- {
- CAutoBN_CTX pctx;
- vchRet.clear();
- CBigNum bn58 = 58;
- CBigNum bn = 0;
- CBigNum bnChar;
- while (isspace(*psz))
- psz++;
- for (const char* p = psz; *p; p++)
- {
- const char* p1 = strchr(pszBase58, *p);
- if (p1 == NULL)
- {
- while (isspace(*p))
- p++;
- if (*p != '\0')
- return false;
- break;
- }
- bnChar.setulong(p1 - pszBase58);
- if (!BN_mul(&bn, &bn, &bn58, pctx))
- throw bignum_error("DecodeBase58 : BN_mul failed");
- bn += bnChar;
- }
- vector<unsigned char> vchTmp = bn.getvch();
- if (vchTmp.size() >= 2 && vchTmp.end()[-1] == 0 && vchTmp.end()[-2] >= 0x80)
- vchTmp.erase(vchTmp.end()-1);
- int nLeadingZeros = 0;
- for (const char* p = psz; *p == pszBase58[0]; p++)
- nLeadingZeros++;
- vchRet.assign(nLeadingZeros + vchTmp.size(), 0);
- reverse_copy(vchTmp.begin(), vchTmp.end(), vchRet.end() - vchTmp.size());
- return true;
- }
- inline bool DecodeBase58(const string& str, vector<unsigned char>& vchRet)
- {
- return DecodeBase58(str.c_str(), vchRet);
- }
- inline string EncodeBase58Check(const vector<unsigned char>& vchIn)
- {
- vector<unsigned char> vch(vchIn);
- uint256 hash = Hash(vch.begin(), vch.end());
- vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
- return EncodeBase58(vch);
- }
- inline bool DecodeBase58Check(const char* psz, vector<unsigned char>& vchRet)
- {
- if (!DecodeBase58(psz, vchRet))
- return false;
- if (vchRet.size() < 4)
- {
- vchRet.clear();
- return false;
- }
- uint256 hash = Hash(vchRet.begin(), vchRet.end()-4);
- if (memcmp(&hash, &vchRet.end()[-4], 4) != 0)
- {
- vchRet.clear();
- return false;
- }
- vchRet.resize(vchRet.size()-4);
- return true;
- }
- inline bool DecodeBase58Check(const string& str, vector<unsigned char>& vchRet)
- {
- return DecodeBase58Check(str.c_str(), vchRet);
- }
- static const unsigned char ADDRESSVERSION = 0;
- inline string Hash160ToAddress(uint160 hash160)
- {
- vector<unsigned char> vch(1, ADDRESSVERSION);
- vch.insert(vch.end(), UBEGIN(hash160), UEND(hash160));
- return EncodeBase58Check(vch);
- }
- inline bool AddressToHash160(const char* psz, uint160& hash160Ret)
- {
- vector<unsigned char> vch;
- if (!DecodeBase58Check(psz, vch))
- return false;
- if (vch.empty())
- return false;
- unsigned char nVersion = vch[0];
- if (vch.size() != sizeof(hash160Ret) + 1)
- return false;
- memcpy(&hash160Ret, &vch[1], sizeof(hash160Ret));
- return (nVersion <= ADDRESSVERSION);
- }
- inline bool AddressToHash160(const string& str, uint160& hash160Ret)
- {
- return AddressToHash160(str.c_str(), hash160Ret);
- }
- inline bool IsValidBitcoinAddress(const char* psz)
- {
- uint160 hash160;
- return AddressToHash160(psz, hash160);
- }
- inline bool IsValidBitcoinAddress(const string& str)
- {
- return IsValidBitcoinAddress(str.c_str());
- }
- inline string PubKeyToAddress(const vector<unsigned char>& vchPubKey)
- {
- return Hash160ToAddress(Hash160(vchPubKey));
- }
- #include <stdexcept>
- #include <vector>
- #include <openssl/bn.h>
- class bignum_error : public std::runtime_error
- {
- public:
- explicit bignum_error(const std::string& str) : std::runtime_error(str) {}
- };
- class CAutoBN_CTX
- {
- protected:
- BN_CTX* pctx;
- BN_CTX* operator=(BN_CTX* pnew) { return pctx = pnew; }
- public:
- CAutoBN_CTX()
- {
- pctx = BN_CTX_new();
- if (pctx == NULL)
- throw bignum_error("CAutoBN_CTX : BN_CTX_new() returned NULL");
- }
- ~CAutoBN_CTX()
- {
- if (pctx != NULL)
- BN_CTX_free(pctx);
- }
- operator BN_CTX*() { return pctx; }
- BN_CTX& operator*() { return *pctx; }
- BN_CTX** operator&() { return &pctx; }
- bool operator!() { return (pctx == NULL); }
- };
- class CBigNum : public BIGNUM
- {
- public:
- CBigNum()
- {
- BN_init(this);
- }
- CBigNum(const CBigNum& b)
- {
- BN_init(this);
- if (!BN_copy(this, &b))
- {
- BN_clear_free(this);
- throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed");
- }
- }
- explicit CBigNum(const std::string& str)
- {
- BN_init(this);
- SetHex(str);
- }
- CBigNum& operator=(const CBigNum& b)
- {
- if (!BN_copy(this, &b))
- throw bignum_error("CBigNum::operator= : BN_copy failed");
- return (*this);
- }
- ~CBigNum()
- {
- BN_clear_free(this);
- }
- CBigNum(char n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
- CBigNum(short n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
- CBigNum(int n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
- CBigNum(long n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
- CBigNum(int64 n) { BN_init(this); setint64(n); }
- CBigNum(unsigned char n) { BN_init(this); setulong(n); }
- CBigNum(unsigned short n) { BN_init(this); setulong(n); }
- CBigNum(unsigned int n) { BN_init(this); setulong(n); }
- CBigNum(unsigned long n) { BN_init(this); setulong(n); }
- CBigNum(uint64 n) { BN_init(this); setuint64(n); }
- explicit CBigNum(uint256 n) { BN_init(this); setuint256(n); }
- explicit CBigNum(const std::vector<unsigned char>& vch)
- {
- BN_init(this);
- setvch(vch);
- }
- void setulong(unsigned long n)
- {
- if (!BN_set_word(this, n))
- throw bignum_error("CBigNum conversion from unsigned long : BN_set_word failed");
- }
- unsigned long getulong() const
- {
- return BN_get_word(this);
- }
- unsigned int getuint() const
- {
- return BN_get_word(this);
- }
- int getint() const
- {
- unsigned long n = BN_get_word(this);
- if (!BN_is_negative(this))
- return (n > INT_MAX ? INT_MAX : n);
- else
- return (n > INT_MAX ? INT_MIN : -(int)n);
- }
- void setint64(int64 n)
- {
- unsigned char pch[sizeof(n) + 6];
- unsigned char* p = pch + 4;
- bool fNegative = false;
- if (n < (int64)0)
- {
- n = -n;
- fNegative = true;
- }
- bool fLeadingZeroes = true;
- for (int i = 0; i < 8; i++)
- {
- unsigned char c = (n >> 56) & 0xff;
- n <<= 8;
- if (fLeadingZeroes)
- {
- if (c == 0)
- continue;
- if (c & 0x80)
- *p++ = (fNegative ? 0x80 : 0);
- else if (fNegative)
- c |= 0x80;
- fLeadingZeroes = false;
- }
- *p++ = c;
- }
- unsigned int nSize = p - (pch + 4);
- pch[0] = (nSize >> 24) & 0xff;
- pch[1] = (nSize >> 16) & 0xff;
- pch[2] = (nSize >> 8) & 0xff;
- pch[3] = (nSize) & 0xff;
- BN_mpi2bn(pch, p - pch, this);
- }
- void setuint64(uint64 n)
- {
- unsigned char pch[sizeof(n) + 6];
- unsigned char* p = pch + 4;
- bool fLeadingZeroes = true;
- for (int i = 0; i < 8; i++)
- {
- unsigned char c = (n >> 56) & 0xff;
- n <<= 8;
- if (fLeadingZeroes)
- {
- if (c == 0)
- continue;
- if (c & 0x80)
- *p++ = 0;
- fLeadingZeroes = false;
- }
- *p++ = c;
- }
- unsigned int nSize = p - (pch + 4);
- pch[0] = (nSize >> 24) & 0xff;
- pch[1] = (nSize >> 16) & 0xff;
- pch[2] = (nSize >> 8) & 0xff;
- pch[3] = (nSize) & 0xff;
- BN_mpi2bn(pch, p - pch, this);
- }
- void setuint256(uint256 n)
- {
- unsigned char pch[sizeof(n) + 6];
- unsigned char* p = pch + 4;
- bool fLeadingZeroes = true;
- unsigned char* pbegin = (unsigned char*)&n;
- unsigned char* psrc = pbegin + sizeof(n);
- while (psrc != pbegin)
- {
- unsigned char c = *(--psrc);
- if (fLeadingZeroes)
- {
- if (c == 0)
- continue;
- if (c & 0x80)
- *p++ = 0;
- fLeadingZeroes = false;
- }
- *p++ = c;
- }
- unsigned int nSize = p - (pch + 4);
- pch[0] = (nSize >> 24) & 0xff;
- pch[1] = (nSize >> 16) & 0xff;
- pch[2] = (nSize >> 8) & 0xff;
- pch[3] = (nSize >> 0) & 0xff;
- BN_mpi2bn(pch, p - pch, this);
- }
- uint256 getuint256()
- {
- unsigned int nSize = BN_bn2mpi(this, NULL);
- if (nSize < 4)
- return 0;
- std::vector<unsigned char> vch(nSize);
- BN_bn2mpi(this, &vch[0]);
- if (vch.size() > 4)
- vch[4] &= 0x7f;
- uint256 n = 0;
- for (int i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--)
- ((unsigned char*)&n)[i] = vch[j];
- return n;
- }
- void setvch(const std::vector<unsigned char>& vch)
- {
- std::vector<unsigned char> vch2(vch.size() + 4);
- unsigned int nSize = vch.size();
- vch2[0] = (nSize >> 24) & 0xff;
- vch2[1] = (nSize >> 16) & 0xff;
- vch2[2] = (nSize >> 8) & 0xff;
- vch2[3] = (nSize >> 0) & 0xff;
- reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4);
- BN_mpi2bn(&vch2[0], vch2.size(), this);
- }
- std::vector<unsigned char> getvch() const
- {
- unsigned int nSize = BN_bn2mpi(this, NULL);
- if (nSize < 4)
- return std::vector<unsigned char>();
- std::vector<unsigned char> vch(nSize);
- BN_bn2mpi(this, &vch[0]);
- vch.erase(vch.begin(), vch.begin() + 4);
- reverse(vch.begin(), vch.end());
- return vch;
- }
- CBigNum& SetCompact(unsigned int nCompact)
- {
- unsigned int nSize = nCompact >> 24;
- std::vector<unsigned char> vch(4 + nSize);
- vch[3] = nSize;
- if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff;
- if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff;
- if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff;
- BN_mpi2bn(&vch[0], vch.size(), this);
- return *this;
- }
- unsigned int GetCompact() const
- {
- unsigned int nSize = BN_bn2mpi(this, NULL);
- std::vector<unsigned char> vch(nSize);
- nSize -= 4;
- BN_bn2mpi(this, &vch[0]);
- unsigned int nCompact = nSize << 24;
- if (nSize >= 1) nCompact |= (vch[4] << 16);
- if (nSize >= 2) nCompact |= (vch[5] << 8);
- if (nSize >= 3) nCompact |= (vch[6] << 0);
- return nCompact;
- }
- void SetHex(const std::string& str)
- {
- const char* psz = str.c_str();
- while (isspace(*psz))
- psz++;
- bool fNegative = false;
- if (*psz == '-')
- {
- fNegative = true;
- psz++;
- }
- if (psz[0] == '0' && tolower(psz[1]) == 'x')
- psz += 2;
- while (isspace(*psz))
- psz++;
- 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 };
- *this = 0;
- while (isxdigit(*psz))
- {
- *this <<= 4;
- int n = phexdigit[*psz++];
- *this += n;
- }
- if (fNegative)
- *this = 0 - *this;
- }
- unsigned int GetSerializeSize(int nType=0, int nVersion=VERSION) const
- {
- return ::GetSerializeSize(getvch(), nType, nVersion);
- }
- template<typename Stream>
- void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const
- {
- ::Serialize(s, getvch(), nType, nVersion);
- }
- template<typename Stream>
- void Unserialize(Stream& s, int nType=0, int nVersion=VERSION)
- {
- vector<unsigned char> vch;
- ::Unserialize(s, vch, nType, nVersion);
- setvch(vch);
- }
- bool operator!() const
- {
- return BN_is_zero(this);
- }
- CBigNum& operator+=(const CBigNum& b)
- {
- if (!BN_add(this, this, &b))
- throw bignum_error("CBigNum::operator+= : BN_add failed");
- return *this;
- }
- CBigNum& operator-=(const CBigNum& b)
- {
- *this = *this - b;
- return *this;
- }
- CBigNum& operator*=(const CBigNum& b)
- {
- CAutoBN_CTX pctx;
- if (!BN_mul(this, this, &b, pctx))
- throw bignum_error("CBigNum::operator*= : BN_mul failed");
- return *this;
- }
- CBigNum& operator/=(const CBigNum& b)
- {
- *this = *this / b;
- return *this;
- }
- CBigNum& operator%=(const CBigNum& b)
- {
- *this = *this % b;
- return *this;
- }
- CBigNum& operator<<=(unsigned int shift)
- {
- if (!BN_lshift(this, this, shift))
- throw bignum_error("CBigNum:operator<<= : BN_lshift failed");
- return *this;
- }
- CBigNum& operator>>=(unsigned int shift)
- {
- if (!BN_rshift(this, this, shift))
- throw bignum_error("CBigNum:operator>>= : BN_rshift failed");
- return *this;
- }
- CBigNum& operator++()
- {
- if (!BN_add(this, this, BN_value_one()))
- throw bignum_error("CBigNum::operator++ : BN_add failed");
- return *this;
- }
- const CBigNum operator++(int)
- {
- const CBigNum ret = *this;
- ++(*this);
- return ret;
- }
- CBigNum& operator--()
- {
- CBigNum r;
- if (!BN_sub(&r, this, BN_value_one()))
- throw bignum_error("CBigNum::operator-- : BN_sub failed");
- *this = r;
- return *this;
- }
- const CBigNum operator--(int)
- {
- const CBigNum ret = *this;
- --(*this);
- return ret;
- }
- friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b);
- friend inline const CBigNum operator/(const CBigNum& a, const CBigNum& b);
- friend inline const CBigNum operator%(const CBigNum& a, const CBigNum& b);
- };
- inline const CBigNum operator+(const CBigNum& a, const CBigNum& b)
- {
- CBigNum r;
- if (!BN_add(&r, &a, &b))
- throw bignum_error("CBigNum::operator+ : BN_add failed");
- return r;
- }
- inline const CBigNum operator-(const CBigNum& a, const CBigNum& b)
- {
- CBigNum r;
- if (!BN_sub(&r, &a, &b))
- throw bignum_error("CBigNum::operator- : BN_sub failed");
- return r;
- }
- inline const CBigNum operator-(const CBigNum& a)
- {
- CBigNum r(a);
- BN_set_negative(&r, !BN_is_negative(&r));
- return r;
- }
- inline const CBigNum operator*(const CBigNum& a, const CBigNum& b)
- {
- CAutoBN_CTX pctx;
- CBigNum r;
- if (!BN_mul(&r, &a, &b, pctx))
- throw bignum_error("CBigNum::operator* : BN_mul failed");
- return r;
- }
- inline const CBigNum operator/(const CBigNum& a, const CBigNum& b)
- {
- CAutoBN_CTX pctx;
- CBigNum r;
- if (!BN_div(&r, NULL, &a, &b, pctx))
- throw bignum_error("CBigNum::operator/ : BN_div failed");
- return r;
- }
- inline const CBigNum operator%(const CBigNum& a, const CBigNum& b)
- {
- CAutoBN_CTX pctx;
- CBigNum r;
- if (!BN_mod(&r, &a, &b, pctx))
- throw bignum_error("CBigNum::operator% : BN_div failed");
- return r;
- }
- inline const CBigNum operator<<(const CBigNum& a, unsigned int shift)
- {
- CBigNum r;
- if (!BN_lshift(&r, &a, shift))
- throw bignum_error("CBigNum:operator<< : BN_lshift failed");
- return r;
- }
- inline const CBigNum operator>>(const CBigNum& a, unsigned int shift)
- {
- CBigNum r;
- if (!BN_rshift(&r, &a, shift))
- throw bignum_error("CBigNum:operator>> : BN_rshift failed");
- return r;
- }
- inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) == 0); }
- inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) != 0); }
- inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) <= 0); }
- inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) >= 0); }
- inline bool operator<(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) < 0); }
- inline bool operator>(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) > 0); }
- #include "headers.h"
- static CCriticalSection cs_db;
- static bool fDbEnvInit = false;
- DbEnv dbenv(0);
- static map<string, int> mapFileUseCount;
- class CDBInit
- {
- public:
- CDBInit()
- {
- }
- ~CDBInit()
- {
- if (fDbEnvInit)
- {
- dbenv.close(0);
- fDbEnvInit = false;
- }
- }
- }
- instance_of_cdbinit;
- CDB::CDB(const char* pszFile, const char* pszMode, bool fTxn) : pdb(NULL)
- {
- int ret;
- if (pszFile == NULL)
- return;
- bool fCreate = strchr(pszMode, 'c');
- bool fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w'));
- unsigned int nFlags = DB_THREAD;
- if (fCreate)
- nFlags |= DB_CREATE;
- else if (fReadOnly)
- nFlags |= DB_RDONLY;
- if (!fReadOnly || fTxn)
- nFlags |= DB_AUTO_COMMIT;
- CRITICAL_BLOCK(cs_db)
- {
- if (!fDbEnvInit)
- {
- string strAppDir = GetAppDir();
- string strLogDir = strAppDir + "\\database";
- _mkdir(strLogDir.c_str());
- printf("dbenv.open strAppDir=%s\n", strAppDir.c_str());
- dbenv.set_lg_dir(strLogDir.c_str());
- dbenv.set_lg_max(10000000);
- dbenv.set_lk_max_locks(10000);
- dbenv.set_lk_max_objects(10000);
- dbenv.set_errfile(fopen("db.log", "a"));
- ret = dbenv.open(strAppDir.c_str(),
- DB_CREATE |
- DB_INIT_LOCK |
- DB_INIT_LOG |
- DB_INIT_MPOOL |
- DB_INIT_TXN |
- DB_THREAD |
- DB_PRIVATE |
- DB_RECOVER,
- 0);
- if (ret > 0)
- throw runtime_error(strprintf("CDB() : error %d opening database environment\n", ret));
- fDbEnvInit = true;
- }
- strFile = pszFile;
- ++mapFileUseCount[strFile];
- }
- pdb = new Db(&dbenv, 0);
- ret = pdb->open(NULL,
- pszFile,
- "main",
- DB_BTREE,
- nFlags,
- 0);
- if (ret > 0)
- {
- delete pdb;
- pdb = NULL;
- CRITICAL_BLOCK(cs_db)
- --mapFileUseCount[strFile];
- strFile = "";
- throw runtime_error(strprintf("CDB() : can't open database file %s, error %d\n", pszFile, ret));
- }
- if (fCreate && !Exists(string("version")))
- WriteVersion(VERSION);
- RandAddSeed();
- }
- void CDB::Close()
- {
- if (!pdb)
- return;
- if (!vTxn.empty())
- vTxn.front()->abort();
- vTxn.clear();
- pdb->close(0);
- delete pdb;
- pdb = NULL;
- dbenv.txn_checkpoint(0, 0, 0);
- CRITICAL_BLOCK(cs_db)
- --mapFileUseCount[strFile];
- RandAddSeed();
- }
- void DBFlush(bool fShutdown)
- {
- printf("DBFlush(%s)\n", fShutdown ? "true" : "false");
- CRITICAL_BLOCK(cs_db)
- {
- dbenv.txn_checkpoint(0, 0, 0);
- map<string, int>::iterator mi = mapFileUseCount.begin();
- while (mi != mapFileUseCount.end())
- {
- string strFile = (*mi).first;
- int nRefCount = (*mi).second;
- if (nRefCount == 0)
- {
- dbenv.lsn_reset(strFile.c_str(), 0);
- mapFileUseCount.erase(mi++);
- }
- else
- mi++;
- }
- if (fShutdown)
- {
- char** listp;
- if (mapFileUseCount.empty())
- dbenv.log_archive(&listp, DB_ARCH_REMOVE);
- dbenv.close(0);
- fDbEnvInit = false;
- }
- }
- }
- bool CTxDB::ReadTxIndex(uint256 hash, CTxIndex& txindex)
- {
- assert(!fClient);
- txindex.SetNull();
- return Read(make_pair(string("tx"), hash), txindex);
- }
- bool CTxDB::UpdateTxIndex(uint256 hash, const CTxIndex& txindex)
- {
- assert(!fClient);
- return Write(make_pair(string("tx"), hash), txindex);
- }
- bool CTxDB::AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight)
- {
- assert(!fClient);
- uint256 hash = tx.GetHash();
- CTxIndex txindex(pos, tx.vout.size());
- return Write(make_pair(string("tx"), hash), txindex);
- }
- bool CTxDB::EraseTxIndex(const CTransaction& tx)
- {
- assert(!fClient);
- uint256 hash = tx.GetHash();
- return Erase(make_pair(string("tx"), hash));
- }
- bool CTxDB::ContainsTx(uint256 hash)
- {
- assert(!fClient);
- return Exists(make_pair(string("tx"), hash));
- }
- bool CTxDB::ReadOwnerTxes(uint160 hash160, int nMinHeight, vector<CTransaction>& vtx)
- {
- assert(!fClient);
- vtx.clear();
- Dbc* pcursor = GetCursor();
- if (!pcursor)
- return false;
- unsigned int fFlags = DB_SET_RANGE;
- loop
- {
- CDataStream ssKey;
- if (fFlags == DB_SET_RANGE)
- ssKey << string("owner") << hash160 << CDiskTxPos(0, 0, 0);
- CDataStream ssValue;
- int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
- fFlags = DB_NEXT;
- if (ret == DB_NOTFOUND)
- break;
- else if (ret != 0)
- return false;
- string strType;
- uint160 hashItem;
- CDiskTxPos pos;
- ssKey >> strType >> hashItem >> pos;
- int nItemHeight;
- ssValue >> nItemHeight;
- if (strType != "owner" || hashItem != hash160)
- break;
- if (nItemHeight >= nMinHeight)
- {
- vtx.resize(vtx.size()+1);
- if (!vtx.back().ReadFromDisk(pos))
- return false;
- }
- }
- return true;
- }
- bool CTxDB::ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex)
- {
- assert(!fClient);
- tx.SetNull();
- if (!ReadTxIndex(hash, txindex))
- return false;
- return (tx.ReadFromDisk(txindex.pos));
- }
- bool CTxDB::ReadDiskTx(uint256 hash, CTransaction& tx)
- {
- CTxIndex txindex;
- return ReadDiskTx(hash, tx, txindex);
- }
- bool CTxDB::ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex)
- {
- return ReadDiskTx(outpoint.hash, tx, txindex);
- }
- bool CTxDB::ReadDiskTx(COutPoint outpoint, CTransaction& tx)
- {
- CTxIndex txindex;
- return ReadDiskTx(outpoint.hash, tx, txindex);
- }
- bool CTxDB::WriteBlockIndex(const CDiskBlockIndex& blockindex)
- {
- return Write(make_pair(string("blockindex"), blockindex.GetBlockHash()), blockindex);
- }
- bool CTxDB::EraseBlockIndex(uint256 hash)
- {
- return Erase(make_pair(string("blockindex"), hash));
- }
- bool CTxDB::ReadHashBestChain(uint256& hashBestChain)
- {
- return Read(string("hashBestChain"), hashBestChain);
- }
- bool CTxDB::WriteHashBestChain(uint256 hashBestChain)
- {
- return Write(string("hashBestChain"), hashBestChain);
- }
- CBlockIndex* InsertBlockIndex(uint256 hash)
- {
- if (hash == 0)
- return NULL;
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
- if (mi != mapBlockIndex.end())
- return (*mi).second;
- CBlockIndex* pindexNew = new CBlockIndex();
- if (!pindexNew)
- throw runtime_error("LoadBlockIndex() : new CBlockIndex failed");
- mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
- pindexNew->phashBlock = &((*mi).first);
- return pindexNew;
- }
- bool CTxDB::LoadBlockIndex()
- {
- Dbc* pcursor = GetCursor();
- if (!pcursor)
- return false;
- unsigned int fFlags = DB_SET_RANGE;
- loop
- {
- CDataStream ssKey;
- if (fFlags == DB_SET_RANGE)
- ssKey << make_pair(string("blockindex"), uint256(0));
- CDataStream ssValue;
- int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
- fFlags = DB_NEXT;
- if (ret == DB_NOTFOUND)
- break;
- else if (ret != 0)
- return false;
- string strType;
- ssKey >> strType;
- if (strType == "blockindex")
- {
- CDiskBlockIndex diskindex;
- ssValue >> diskindex;
- CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
- pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev);
- pindexNew->pnext = InsertBlockIndex(diskindex.hashNext);
- pindexNew->nFile = diskindex.nFile;
- pindexNew->nBlockPos = diskindex.nBlockPos;
- pindexNew->nHeight = diskindex.nHeight;
- pindexNew->nVersion = diskindex.nVersion;
- pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
- pindexNew->nTime = diskindex.nTime;
- pindexNew->nBits = diskindex.nBits;
- pindexNew->nNonce = diskindex.nNonce;
- if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == hashGenesisBlock)
- pindexGenesisBlock = pindexNew;
- }
- else
- {
- break;
- }
- }
- if (!ReadHashBestChain(hashBestChain))
- {
- if (pindexGenesisBlock == NULL)
- return true;
- return error("CTxDB::LoadBlockIndex() : hashBestChain not found\n");
- }
- if (!mapBlockIndex.count(hashBestChain))
- return error("CTxDB::LoadBlockIndex() : blockindex for hashBestChain not found\n");
- pindexBest = mapBlockIndex[hashBestChain];
- nBestHeight = pindexBest->nHeight;
- printf("LoadBlockIndex(): hashBestChain=%s height=%d\n", hashBestChain.ToString().substr(0,14).c_str(), nBestHeight);
- return true;
- }
- bool CAddrDB::WriteAddress(const CAddress& addr)
- {
- return Write(make_pair(string("addr"), addr.GetKey()), addr);
- }
- bool CAddrDB::LoadAddresses()
- {
- CRITICAL_BLOCK(cs_mapAddresses)
- {
- CAutoFile filein = fopen("addr.txt", "rt");
- if (filein)
- {
- try
- {
- char psz[1000];
- while (fgets(psz, sizeof(psz), filein))
- {
- CAddress addr(psz, NODE_NETWORK);
- if (addr.ip != 0)
- AddAddress(*this, addr);
- }
- }
- catch (...) { }
- }
- Dbc* pcursor = GetCursor();
- if (!pcursor)
- return false;
- loop
- {
- CDataStream ssKey;
- CDataStream ssValue;
- int ret = ReadAtCursor(pcursor, ssKey, ssValue);
- if (ret == DB_NOTFOUND)
- break;
- else if (ret != 0)
- return false;
- string strType;
- ssKey >> strType;
- if (strType == "addr")
- {
- CAddress addr;
- ssValue >> addr;
- mapAddresses.insert(make_pair(addr.GetKey(), addr));
- }
- }
- printf("mapAddresses:\n");
- foreach(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
- item.second.print();
- printf("-----\n");
- }
- return true;
- }
- bool LoadAddresses()
- {
- return CAddrDB("cr+").LoadAddresses();
- }
- bool CReviewDB::ReadReviews(uint256 hash, vector<CReview>& vReviews)
- {
- vReviews.size();
- return Read(make_pair(string("reviews"), hash), vReviews);
- }
- bool CReviewDB::WriteReviews(uint256 hash, const vector<CReview>& vReviews)
- {
- return Write(make_pair(string("reviews"), hash), vReviews);
- }
- bool CWalletDB::LoadWallet(vector<unsigned char>& vchDefaultKeyRet)
- {
- vchDefaultKeyRet.clear();
- CRITICAL_BLOCK(cs_mapKeys)
- CRITICAL_BLOCK(cs_mapWallet)
- {
- Dbc* pcursor = GetCursor();
- if (!pcursor)
- return false;
- loop
- {
- CDataStream ssKey;
- CDataStream ssValue;
- int ret = ReadAtCursor(pcursor, ssKey, ssValue);
- if (ret == DB_NOTFOUND)
- break;
- else if (ret != 0)
- return false;
- string strType;
- ssKey >> strType;
- if (strType == "name")
- {
- string strAddress;
- ssKey >> strAddress;
- ssValue >> mapAddressBook[strAddress];
- }
- else if (strType == "tx")
- {
- uint256 hash;
- ssKey >> hash;
- CWalletTx& wtx = mapWallet[hash];
- ssValue >> wtx;
- if (wtx.GetHash() != hash)
- printf("Error in wallet.dat, hash mismatch\n");
- }
- else if (strType == "key")
- {
- vector<unsigned char> vchPubKey;
- ssKey >> vchPubKey;
- CPrivKey vchPrivKey;
- ssValue >> vchPrivKey;
- mapKeys[vchPubKey] = vchPrivKey;
- mapPubKeys[Hash160(vchPubKey)] = vchPubKey;
- }
- else if (strType == "defaultkey")
- {
- ssValue >> vchDefaultKeyRet;
- }
- else if (strType == "setting")
- {
- string strKey;
- ssKey >> strKey;
- if (strKey == "fGenerateBitcoins") ssValue >> fGenerateBitcoins;
- if (strKey == "nTransactionFee") ssValue >> nTransactionFee;
- if (strKey == "addrIncoming") ssValue >> addrIncoming;
- }
- }
- }
- printf("fGenerateBitcoins = %d\n", fGenerateBitcoins);
- printf("nTransactionFee = %I64d\n", nTransactionFee);
- printf("addrIncoming = %s\n", addrIncoming.ToString().c_str());
- return true;
- }
- bool LoadWallet()
- {
- vector<unsigned char> vchDefaultKey;
- if (!CWalletDB("cr").LoadWallet(vchDefaultKey))
- return false;
- if (mapKeys.count(vchDefaultKey))
- {
- keyUser.SetPubKey(vchDefaultKey);
- keyUser.SetPrivKey(mapKeys[vchDefaultKey]);
- }
- else
- {
- keyUser.MakeNewKey();
- if (!AddKey(keyUser))
- return false;
- if (!SetAddressBookName(PubKeyToAddress(keyUser.GetPubKey()), "Your Address"))
- return false;
- CWalletDB().WriteDefaultKey(keyUser.GetPubKey());
- }
- return true;
- }
- #include <db_cxx.h>
- class CTransaction;
- class CTxIndex;
- class CDiskBlockIndex;
- class CDiskTxPos;
- class COutPoint;
- class CUser;
- class CReview;
- class CAddress;
- class CWalletTx;
- extern map<string, string> mapAddressBook;
- extern bool fClient;
- extern DbEnv dbenv;
- extern void DBFlush(bool fShutdown);
- class CDB
- {
- protected:
- Db* pdb;
- string strFile;
- vector<DbTxn*> vTxn;
- explicit CDB(const char* pszFile, const char* pszMode="r+", bool fTxn=false);
- ~CDB() { Close(); }
- public:
- void Close();
- private:
- CDB(const CDB&);
- void operator=(const CDB&);
- protected:
- template<typename K, typename T>
- bool Read(const K& key, T& value)
- {
- if (!pdb)
- return false;
- CDataStream ssKey(SER_DISK);
- ssKey.reserve(1000);
- ssKey << key;
- Dbt datKey(&ssKey[0], ssKey.size());
- Dbt datValue;
- datValue.set_flags(DB_DBT_MALLOC);
- int ret = pdb->get(GetTxn(), &datKey, &datValue, 0);
- memset(datKey.get_data(), 0, datKey.get_size());
- if (datValue.get_data() == NULL)
- return false;
- CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK);
- ssValue >> value;
- memset(datValue.get_data(), 0, datValue.get_size());
- free(datValue.get_data());
- return (ret == 0);
- }
- template<typename K, typename T>
- bool Write(const K& key, const T& value, bool fOverwrite=true)
- {
- if (!pdb)
- return false;
- CDataStream ssKey(SER_DISK);
- ssKey.reserve(1000);
- ssKey << key;
- Dbt datKey(&ssKey[0], ssKey.size());
- CDataStream ssValue(SER_DISK);
- ssValue.reserve(10000);
- ssValue << value;
- Dbt datValue(&ssValue[0], ssValue.size());
- int ret = pdb->put(GetTxn(), &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
- memset(datKey.get_data(), 0, datKey.get_size());
- memset(datValue.get_data(), 0, datValue.get_size());
- return (ret == 0);
- }
- template<typename K>
- bool Erase(const K& key)
- {
- if (!pdb)
- return false;
- CDataStream ssKey(SER_DISK);
- ssKey.reserve(1000);
- ssKey << key;
- Dbt datKey(&ssKey[0], ssKey.size());
- int ret = pdb->del(GetTxn(), &datKey, 0);
- memset(datKey.get_data(), 0, datKey.get_size());
- return (ret == 0 || ret == DB_NOTFOUND);
- }
- template<typename K>
- bool Exists(const K& key)
- {
- if (!pdb)
- return false;
- CDataStream ssKey(SER_DISK);
- ssKey.reserve(1000);
- ssKey << key;
- Dbt datKey(&ssKey[0], ssKey.size());
- int ret = pdb->exists(GetTxn(), &datKey, 0);
- memset(datKey.get_data(), 0, datKey.get_size());
- return (ret == 0);
- }
- Dbc* GetCursor()
- {
- if (!pdb)
- return NULL;
- Dbc* pcursor = NULL;
- int ret = pdb->cursor(NULL, &pcursor, 0);
- if (ret != 0)
- return NULL;
- return pcursor;
- }
- int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, unsigned int fFlags=DB_NEXT)
- {
- Dbt datKey;
- if (fFlags == DB_SET || fFlags == DB_SET_RANGE || fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)
- {
- datKey.set_data(&ssKey[0]);
- datKey.set_size(ssKey.size());
- }
- Dbt datValue;
- if (fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)
- {
- datValue.set_data(&ssValue[0]);
- datValue.set_size(ssValue.size());
- }
- datKey.set_flags(DB_DBT_MALLOC);
- datValue.set_flags(DB_DBT_MALLOC);
- int ret = pcursor->get(&datKey, &datValue, fFlags);
- if (ret != 0)
- return ret;
- else if (datKey.get_data() == NULL || datValue.get_data() == NULL)
- return 99999;
- ssKey.SetType(SER_DISK);
- ssKey.clear();
- ssKey.write((char*)datKey.get_data(), datKey.get_size());
- ssValue.SetType(SER_DISK);
- ssValue.clear();
- ssValue.write((char*)datValue.get_data(), datValue.get_size());
- memset(datKey.get_data(), 0, datKey.get_size());
- memset(datValue.get_data(), 0, datValue.get_size());
- free(datKey.get_data());
- free(datValue.get_data());
- return 0;
- }
- DbTxn* GetTxn()
- {
- if (!vTxn.empty())
- return vTxn.back();
- else
- return NULL;
- }
- public:
- bool TxnBegin()
- {
- if (!pdb)
- return false;
- DbTxn* ptxn = NULL;
- int ret = dbenv.txn_begin(GetTxn(), &ptxn, 0);
- if (!ptxn || ret != 0)
- return false;
- vTxn.push_back(ptxn);
- return true;
- }
- bool TxnCommit()
- {
- if (!pdb)
- return false;
- if (vTxn.empty())
- return false;
- int ret = vTxn.back()->commit(0);
- vTxn.pop_back();
- return (ret == 0);
- }
- bool TxnAbort()
- {
- if (!pdb)
- return false;
- if (vTxn.empty())
- return false;
- int ret = vTxn.back()->abort();
- vTxn.pop_back();
- return (ret == 0);
- }
- bool ReadVersion(int& nVersion)
- {
- nVersion = 0;
- return Read(string("version"), nVersion);
- }
- bool WriteVersion(int nVersion)
- {
- return Write(string("version"), nVersion);
- }
- };
- class CTxDB : public CDB
- {
- public:
- CTxDB(const char* pszMode="r+", bool fTxn=false) : CDB(!fClient ? "blkindex.dat" : NULL, pszMode, fTxn) { }
- private:
- CTxDB(const CTxDB&);
- void operator=(const CTxDB&);
- public:
- bool ReadTxIndex(uint256 hash, CTxIndex& txindex);
- bool UpdateTxIndex(uint256 hash, const CTxIndex& txindex);
- bool AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight);
- bool EraseTxIndex(const CTransaction& tx);
- bool ContainsTx(uint256 hash);
- bool ReadOwnerTxes(uint160 hash160, int nHeight, vector<CTransaction>& vtx);
- bool ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex);
- bool ReadDiskTx(uint256 hash, CTransaction& tx);
- bool ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex);
- bool ReadDiskTx(COutPoint outpoint, CTransaction& tx);
- bool WriteBlockIndex(const CDiskBlockIndex& blockindex);
- bool EraseBlockIndex(uint256 hash);
- bool ReadHashBestChain(uint256& hashBestChain);
- bool WriteHashBestChain(uint256 hashBestChain);
- bool LoadBlockIndex();
- };
- class CReviewDB : public CDB
- {
- public:
- CReviewDB(const char* pszMode="r+", bool fTxn=false) : CDB("reviews.dat", pszMode, fTxn) { }
- private:
- CReviewDB(const CReviewDB&);
- void operator=(const CReviewDB&);
- public:
- bool ReadUser(uint256 hash, CUser& user)
- {
- return Read(make_pair(string("user"), hash), user);
- }
- bool WriteUser(uint256 hash, const CUser& user)
- {
- return Write(make_pair(string("user"), hash), user);
- }
- bool ReadReviews(uint256 hash, vector<CReview>& vReviews);
- bool WriteReviews(uint256 hash, const vector<CReview>& vReviews);
- };
- class CMarketDB : public CDB
- {
- public:
- CMarketDB(const char* pszMode="r+", bool fTxn=false) : CDB("market.dat", pszMode, fTxn) { }
- private:
- CMarketDB(const CMarketDB&);
- void operator=(const CMarketDB&);
- };
- class CAddrDB : public CDB
- {
- public:
- CAddrDB(const char* pszMode="r+", bool fTxn=false) : CDB("addr.dat", pszMode, fTxn) { }
- private:
- CAddrDB(const CAddrDB&);
- void operator=(const CAddrDB&);
- public:
- bool WriteAddress(const CAddress& addr);
- bool LoadAddresses();
- };
- bool LoadAddresses();
- class CWalletDB : public CDB
- {
- public:
- CWalletDB(const char* pszMode="r+", bool fTxn=false) : CDB("wallet.dat", pszMode, fTxn) { }
- private:
- CWalletDB(const CWalletDB&);
- void operator=(const CWalletDB&);
- public:
- bool ReadName(const string& strAddress, string& strName)
- {
- strName = "";
- return Read(make_pair(string("name"), strAddress), strName);
- }
- bool WriteName(const string& strAddress, const string& strName)
- {
- mapAddressBook[strAddress] = strName;
- return Write(make_pair(string("name"), strAddress), strName);
- }
- bool EraseName(const string& strAddress)
- {
- mapAddressBook.erase(strAddress);
- return Erase(make_pair(string("name"), strAddress));
- }
- bool ReadTx(uint256 hash, CWalletTx& wtx)
- {
- return Read(make_pair(string("tx"), hash), wtx);
- }
- bool WriteTx(uint256 hash, const CWalletTx& wtx)
- {
- return Write(make_pair(string("tx"), hash), wtx);
- }
- bool EraseTx(uint256 hash)
- {
- return Erase(make_pair(string("tx"), hash));
- }
- bool ReadKey(const vector<unsigned char>& vchPubKey, CPrivKey& vchPrivKey)
- {
- vchPrivKey.clear();
- return Read(make_pair(string("key"), vchPubKey), vchPrivKey);
- }
- bool WriteKey(const vector<unsigned char>& vchPubKey, const CPrivKey& vchPrivKey)
- {
- return Write(make_pair(string("key"), vchPubKey), vchPrivKey, false);
- }
- bool ReadDefaultKey(vector<unsigned char>& vchPubKey)
- {
- vchPubKey.clear();
- return Read(string("defaultkey"), vchPubKey);
- }
- bool WriteDefaultKey(const vector<unsigned char>& vchPubKey)
- {
- return Write(string("defaultkey"), vchPubKey);
- }
- template<typename T>
- bool ReadSetting(const string& strKey, T& value)
- {
- return Read(make_pair(string("setting"), strKey), value);
- }
- template<typename T>
- bool WriteSetting(const string& strKey, const T& value)
- {
- return Write(make_pair(string("setting"), strKey), value);
- }
- bool LoadWallet(vector<unsigned char>& vchDefaultKeyRet);
- };
- bool LoadWallet();
- inline bool SetAddressBookName(const string& strAddress, const string& strName)
- {
- return CWalletDB().WriteName(strAddress, strName);
- }
- #ifdef _MSC_VER
- #pragma warning(disable:4786)
- #pragma warning(disable:4804)
- #pragma warning(disable:4717)
- #endif
- #ifdef _WIN32_WINNT
- #undef _WIN32_WINNT
- #endif
- #define _WIN32_WINNT 0x0400
- #define WIN32_LEAN_AND_MEAN 1
- #include <wx/wx.h>
- #include <wx/clipbrd.h>
- #include <wx/snglinst.h>
- #include <openssl/ecdsa.h>
- #include <openssl/evp.h>
- #include <openssl/rand.h>
- #include <openssl/sha.h>
- #include <openssl/ripemd.h>
- #include <windows.h>
- #include <winsock2.h>
- #include <mswsock.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <io.h>
- #include <math.h>
- #include <limits.h>
- #include <float.h>
- #include <assert.h>
- #include <process.h>
- #include <malloc.h>
- #include <memory>
- #define BOUNDSCHECK 1
- #include <sstream>
- #include <string>
- #include <vector>
- #include <list>
- #include <deque>
- #include <map>
- #include <set>
- #include <algorithm>
- #include <numeric>
- #include <boost/foreach.hpp>
- #include <boost/lexical_cast.hpp>
- #include <boost/tuple/tuple.hpp>
- #include <boost/tuple/tuple_comparison.hpp>
- #include <boost/tuple/tuple_io.hpp>
- #include <boost/array.hpp>
- #pragma hdrstop
- using namespace std;
- using namespace boost;
- #include "serialize.h"
- #include "uint256.h"
- #include "util.h"
- #include "key.h"
- #include "bignum.h"
- #include "base58.h"
- #include "script.h"
- #include "db.h"
- #include "net.h"
- #include "irc.h"
- #include "main.h"
- #include "market.h"
- #include "uibase.h"
- #include "ui.h"
- #include "headers.h"
- #pragma pack(1)
- struct ircaddr
- {
- int ip;
- short port;
- };
- string EncodeAddress(const CAddress& addr)
- {
- struct ircaddr tmp;
- tmp.ip = addr.ip;
- tmp.port = addr.port;
- vector<unsigned char> vch(UBEGIN(tmp), UEND(tmp));
- return string("u") + EncodeBase58Check(vch);
- }
- bool DecodeAddress(string str, CAddress& addr)
- {
- vector<unsigned char> vch;
- if (!DecodeBase58Check(str.substr(1), vch))
- return false;
- struct ircaddr tmp;
- if (vch.size() != sizeof(tmp))
- return false;
- memcpy(&tmp, &vch[0], sizeof(tmp));
- addr = CAddress(tmp.ip, tmp.port);
- return true;
- }
- static bool Send(SOCKET hSocket, const char* pszSend)
- {
- if (strstr(pszSend, "PONG") != pszSend)
- printf("SENDING: %s\n", pszSend);
- const char* psz = pszSend;
- const char* pszEnd = psz + strlen(psz);
- while (psz < pszEnd)
- {
- int ret = send(hSocket, psz, pszEnd - psz, 0);
- if (ret < 0)
- return false;
- psz += ret;
- }
- return true;
- }
- bool RecvLine(SOCKET hSocket, string& strLine)
- {
- strLine = "";
- loop
- {
- char c;
- int nBytes = recv(hSocket, &c, 1, 0);
- if (nBytes > 0)
- {
- if (c == '\n')
- continue;
- if (c == '\r')
- return true;
- strLine += c;
- }
- else if (nBytes <= 0)
- {
- if (!strLine.empty())
- return true;
- printf("IRC socket closed\n");
- return false;
- }
- else
- {
- int nErr = WSAGetLastError();
- if (nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
- {
- printf("IRC recv failed: %d\n", nErr);
- return false;
- }
- }
- }
- }
- bool RecvLineIRC(SOCKET hSocket, string& strLine)
- {
- loop
- {
- bool fRet = RecvLine(hSocket, strLine);
- if (fRet)
- {
- if (fShutdown)
- return false;
- vector<string> vWords;
- ParseString(strLine, ' ', vWords);
- if (vWords[0] == "PING")
- {
- strLine[1] = 'O';
- strLine += '\r';
- Send(hSocket, strLine.c_str());
- continue;
- }
- }
- return fRet;
- }
- }
- bool RecvUntil(SOCKET hSocket, const char* psz1, const char* psz2=NULL, const char* psz3=NULL)
- {
- loop
- {
- string strLine;
- if (!RecvLineIRC(hSocket, strLine))
- return false;
- printf("IRC %s\n", strLine.c_str());
- if (psz1 && strLine.find(psz1) != -1)
- return true;
- if (psz2 && strLine.find(psz2) != -1)
- return true;
- if (psz3 && strLine.find(psz3) != -1)
- return true;
- }
- }
- bool fRestartIRCSeed = false;
- void ThreadIRCSeed(void* parg)
- {
- loop
- {
- struct hostent* phostent = gethostbyname("chat.freenode.net");
- CAddress addrConnect(*(u_long*)phostent->h_addr_list[0], htons(6667));
- SOCKET hSocket;
- if (!ConnectSocket(addrConnect, hSocket))
- {
- printf("IRC connect failed\n");
- return;
- }
- if (!RecvUntil(hSocket, "Found your hostname", "using your IP address instead", "Couldn't look up your hostname"))
- {
- closesocket(hSocket);
- return;
- }
- string strMyName = EncodeAddress(addrLocalHost);
- if (!addrLocalHost.IsRoutable())
- strMyName = strprintf("x%u", GetRand(1000000000));
- Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str());
- Send(hSocket, strprintf("USER %s 8 * : %s\r", strMyName.c_str(), strMyName.c_str()).c_str());
- if (!RecvUntil(hSocket, " 004 "))
- {
- closesocket(hSocket);
- return;
- }
- Sleep(500);
- Send(hSocket, "JOIN #bitcoin\r");
- Send(hSocket, "WHO #bitcoin\r");
- while (!fRestartIRCSeed)
- {
- string strLine;
- if (fShutdown || !RecvLineIRC(hSocket, strLine))
- {
- closesocket(hSocket);
- return;
- }
- if (strLine.empty() || strLine[0] != ':')
- continue;
- printf("IRC %s\n", strLine.c_str());
- vector<string> vWords;
- ParseString(strLine, ' ', vWords);
- if (vWords.size() < 2)
- continue;
- char pszName[10000];
- pszName[0] = '\0';
- if (vWords[1] == "352" && vWords.size() >= 8)
- {
- strcpy(pszName, vWords[7].c_str());
- printf("GOT WHO: [%s] ", pszName);
- }
- if (vWords[1] == "JOIN")
- {
- strcpy(pszName, vWords[0].c_str() + 1);
- if (strchr(pszName, '!'))
- *strchr(pszName, '!') = '\0';
- printf("GOT JOIN: [%s] ", pszName);
- }
- if (pszName[0] == 'u')
- {
- CAddress addr;
- if (DecodeAddress(pszName, addr))
- {
- CAddrDB addrdb;
- if (AddAddress(addrdb, addr))
- printf("new ");
- addr.print();
- }
- else
- {
- printf("decode failed\n");
- }
- }
- }
- fRestartIRCSeed = false;
- closesocket(hSocket);
- }
- }
- #ifdef TEST
- int main(int argc, char *argv[])
- {
- WSADATA wsadata;
- if (WSAStartup(MAKEWORD(2,2), &wsadata) != NO_ERROR)
- {
- printf("Error at WSAStartup()\n");
- return false;
- }
- ThreadIRCSeed(NULL);
- WSACleanup();
- return 0;
- }
- #endif
- extern bool RecvLine(SOCKET hSocket, string& strLine);
- extern void ThreadIRCSeed(void* parg);
- extern bool fRestartIRCSeed;
- class key_error : public std::runtime_error
- {
- public:
- explicit key_error(const std::string& str) : std::runtime_error(str) {}
- };
- typedef vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
- class CKey
- {
- protected:
- EC_KEY* pkey;
- public:
- CKey()
- {
- pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
- if (pkey == NULL)
- throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
- }
- CKey(const CKey& b)
- {
- pkey = EC_KEY_dup(b.pkey);
- if (pkey == NULL)
- throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
- }
- CKey& operator=(const CKey& b)
- {
- if (!EC_KEY_copy(pkey, b.pkey))
- throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
- return (*this);
- }
- ~CKey()
- {
- EC_KEY_free(pkey);
- }
- void MakeNewKey()
- {
- if (!EC_KEY_generate_key(pkey))
- throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
- }
- bool SetPrivKey(const CPrivKey& vchPrivKey)
- {
- const unsigned char* pbegin = &vchPrivKey[0];
- if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
- return false;
- return true;
- }
- CPrivKey GetPrivKey() const
- {
- unsigned int nSize = i2d_ECPrivateKey(pkey, NULL);
- if (!nSize)
- throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
- CPrivKey vchPrivKey(nSize, 0);
- unsigned char* pbegin = &vchPrivKey[0];
- if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
- throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
- return vchPrivKey;
- }
- bool SetPubKey(const vector<unsigned char>& vchPubKey)
- {
- const unsigned char* pbegin = &vchPubKey[0];
- if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
- return false;
- return true;
- }
- vector<unsigned char> GetPubKey() const
- {
- unsigned int nSize = i2o_ECPublicKey(pkey, NULL);
- if (!nSize)
- throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
- vector<unsigned char> vchPubKey(nSize, 0);
- unsigned char* pbegin = &vchPubKey[0];
- if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
- throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
- return vchPubKey;
- }
- bool Sign(uint256 hash, vector<unsigned char>& vchSig)
- {
- vchSig.clear();
- unsigned char pchSig[10000];
- unsigned int nSize = 0;
- if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), pchSig, &nSize, pkey))
- return false;
- vchSig.resize(nSize);
- memcpy(&vchSig[0], pchSig, nSize);
- return true;
- }
- bool Verify(uint256 hash, const vector<unsigned char>& vchSig)
- {
- if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
- return false;
- return true;
- }
- static bool Sign(const CPrivKey& vchPrivKey, uint256 hash, vector<unsigned char>& vchSig)
- {
- CKey key;
- if (!key.SetPrivKey(vchPrivKey))
- return false;
- return key.Sign(hash, vchSig);
- }
- static bool Verify(const vector<unsigned char>& vchPubKey, uint256 hash, const vector<unsigned char>& vchSig)
- {
- CKey key;
- if (!key.SetPubKey(vchPubKey))
- return false;
- return key.Verify(hash, vchSig);
- }
- };
- #include "headers.h"
- #include "sha.h"
- CCriticalSection cs_main;
- map<uint256, CTransaction> mapTransactions;
- CCriticalSection cs_mapTransactions;
- unsigned int nTransactionsUpdated = 0;
- map<COutPoint, CInPoint> mapNextTx;
- map<uint256, CBlockIndex*> mapBlockIndex;
- const uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
- CBlockIndex* pindexGenesisBlock = NULL;
- int nBestHeight = -1;
- uint256 hashBestChain = 0;
- CBlockIndex* pindexBest = NULL;
- map<uint256, CBlock*> mapOrphanBlocks;
- multimap<uint256, CBlock*> mapOrphanBlocksByPrev;
- map<uint256, CDataStream*> mapOrphanTransactions;
- multimap<uint256, CDataStream*> mapOrphanTransactionsByPrev;
- map<uint256, CWalletTx> mapWallet;
- vector<pair<uint256, bool> > vWalletUpdated;
- CCriticalSection cs_mapWallet;
- map<vector<unsigned char>, CPrivKey> mapKeys;
- map<uint160, vector<unsigned char> > mapPubKeys;
- CCriticalSection cs_mapKeys;
- CKey keyUser;
- string strSetDataDir;
- int nDropMessagesTest = 0;
- int fGenerateBitcoins;
- int64 nTransactionFee = 0;
- CAddress addrIncoming;
- bool AddKey(const CKey& key)
- {
- CRITICAL_BLOCK(cs_mapKeys)
- {
- mapKeys[key.GetPubKey()] = key.GetPrivKey();
- mapPubKeys[Hash160(key.GetPubKey())] = key.GetPubKey();
- }
- return CWalletDB().WriteKey(key.GetPubKey(), key.GetPrivKey());
- }
- vector<unsigned char> GenerateNewKey()
- {
- CKey key;
- key.MakeNewKey();
- if (!AddKey(key))
- throw runtime_error("GenerateNewKey() : AddKey failed\n");
- return key.GetPubKey();
- }
- bool AddToWallet(const CWalletTx& wtxIn)
- {
- uint256 hash = wtxIn.GetHash();
- CRITICAL_BLOCK(cs_mapWallet)
- {
- pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
- CWalletTx& wtx = (*ret.first).second;
- bool fInsertedNew = ret.second;
- if (fInsertedNew)
- wtx.nTimeReceived = GetAdjustedTime();
- printf("AddToWallet %s %s\n", wtxIn.GetHash().ToString().substr(0,6).c_str(), fInsertedNew ? "new" : "update");
- if (!fInsertedNew)
- {
- bool fUpdated = false;
- if (wtxIn.hashBlock != 0 && wtxIn.hashBlock != wtx.hashBlock)
- {
- wtx.hashBlock = wtxIn.hashBlock;
- fUpdated = true;
- }
- if (wtxIn.nIndex != -1 && (wtxIn.vMerkleBranch != wtx.vMerkleBranch || wtxIn.nIndex != wtx.nIndex))
- {
- wtx.vMerkleBranch = wtxIn.vMerkleBranch;
- wtx.nIndex = wtxIn.nIndex;
- fUpdated = true;
- }
- if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
- {
- wtx.fFromMe = wtxIn.fFromMe;
- fUpdated = true;
- }
- if (wtxIn.fSpent && wtxIn.fSpent != wtx.fSpent)
- {
- wtx.fSpent = wtxIn.fSpent;
- fUpdated = true;
- }
- if (!fUpdated)
- return true;
- }
- if (!wtx.WriteToDisk())
- return false;
- vWalletUpdated.push_back(make_pair(hash, fInsertedNew));
- }
- MainFrameRepaint();
- return true;
- }
- bool AddToWalletIfMine(const CTransaction& tx, const CBlock* pblock)
- {
- if (tx.IsMine() || mapWallet.count(tx.GetHash()))
- {
- CWalletTx wtx(tx);
- if (pblock)
- wtx.SetMerkleBranch(pblock);
- return AddToWallet(wtx);
- }
- return true;
- }
- bool EraseFromWallet(uint256 hash)
- {
- CRITICAL_BLOCK(cs_mapWallet)
- {
- if (mapWallet.erase(hash))
- CWalletDB().EraseTx(hash);
- }
- return true;
- }
- void AddOrphanTx(const CDataStream& vMsg)
- {
- CTransaction tx;
- CDataStream(vMsg) >> tx;
- uint256 hash = tx.GetHash();
- if (mapOrphanTransactions.count(hash))
- return;
- CDataStream* pvMsg = mapOrphanTransactions[hash] = new CDataStream(vMsg);
- foreach(const CTxIn& txin, tx.vin)
- mapOrphanTransactionsByPrev.insert(make_pair(txin.prevout.hash, pvMsg));
- }
- void EraseOrphanTx(uint256 hash)
- {
- if (!mapOrphanTransactions.count(hash))
- return;
- const CDataStream* pvMsg = mapOrphanTransactions[hash];
- CTransaction tx;
- CDataStream(*pvMsg) >> tx;
- foreach(const CTxIn& txin, tx.vin)
- {
- for (multimap<uint256, CDataStream*>::iterator mi = mapOrphanTransactionsByPrev.lower_bound(txin.prevout.hash);
- mi != mapOrphanTransactionsByPrev.upper_bound(txin.prevout.hash);)
- {
- if ((*mi).second == pvMsg)
- mapOrphanTransactionsByPrev.erase(mi++);
- else
- mi++;
- }
- }
- delete pvMsg;
- mapOrphanTransactions.erase(hash);
- }
- bool CTxIn::IsMine() const
- {
- CRITICAL_BLOCK(cs_mapWallet)
- {
- map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
- if (mi != mapWallet.end())
- {
- const CWalletTx& prev = (*mi).second;
- if (prevout.n < prev.vout.size())
- if (prev.vout[prevout.n].IsMine())
- return true;
- }
- }
- return false;
- }
- int64 CTxIn::GetDebit() const
- {
- CRITICAL_BLOCK(cs_mapWallet)
- {
- map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
- if (mi != mapWallet.end())
- {
- const CWalletTx& prev = (*mi).second;
- if (prevout.n < prev.vout.size())
- if (prev.vout[prevout.n].IsMine())
- return prev.vout[prevout.n].nValue;
- }
- }
- return 0;
- }
- int64 CWalletTx::GetTxTime() const
- {
- if (!fTimeReceivedIsTxTime && hashBlock != 0)
- {
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
- if (mi != mapBlockIndex.end())
- {
- CBlockIndex* pindex = (*mi).second;
- if (pindex)
- return pindex->GetMedianTime();
- }
- }
- return nTimeReceived;
- }
- int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
- {
- if (fClient)
- {
- if (hashBlock == 0)
- return 0;
- }
- else
- {
- CBlock blockTmp;
- if (pblock == NULL)
- {
- CTxIndex txindex;
- if (!CTxDB("r").ReadTxIndex(GetHash(), txindex))
- return 0;
- if (!blockTmp.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, true))
- return 0;
- pblock = &blockTmp;
- }
- hashBlock = pblock->GetHash();
- for (nIndex = 0; nIndex < pblock->vtx.size(); nIndex++)
- if (pblock->vtx[nIndex] == *(CTransaction*)this)
- break;
- if (nIndex == pblock->vtx.size())
- {
- vMerkleBranch.clear();
- nIndex = -1;
- printf("ERROR: SetMerkleBranch() : couldn't find tx in block\n");
- return 0;
- }
- vMerkleBranch = pblock->GetMerkleBranch(nIndex);
- }
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
- if (mi == mapBlockIndex.end())
- return 0;
- CBlockIndex* pindex = (*mi).second;
- if (!pindex || !pindex->IsInMainChain())
- return 0;
- return pindexBest->nHeight - pindex->nHeight + 1;
- }
- void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
- {
- vtxPrev.clear();
- const int COPY_DEPTH = 3;
- if (SetMerkleBranch() < COPY_DEPTH)
- {
- vector<uint256> vWorkQueue;
- foreach(const CTxIn& txin, vin)
- vWorkQueue.push_back(txin.prevout.hash);
- CRITICAL_BLOCK(cs_mapWallet)
- {
- map<uint256, const CMerkleTx*> mapWalletPrev;
- set<uint256> setAlreadyDone;
- for (int i = 0; i < vWorkQueue.size(); i++)
- {
- uint256 hash = vWorkQueue[i];
- if (setAlreadyDone.count(hash))
- continue;
- setAlreadyDone.insert(hash);
- CMerkleTx tx;
- if (mapWallet.count(hash))
- {
- tx = mapWallet[hash];
- foreach(const CMerkleTx& txWalletPrev, mapWallet[hash].vtxPrev)
- mapWalletPrev[txWalletPrev.GetHash()] = &txWalletPrev;
- }
- else if (mapWalletPrev.count(hash))
- {
- tx = *mapWalletPrev[hash];
- }
- else if (!fClient && txdb.ReadDiskTx(hash, tx))
- {
- ;
- }
- else
- {
- printf("ERROR: AddSupportingTransactions() : unsupported transaction\n");
- continue;
- }
- int nDepth = tx.SetMerkleBranch();
- vtxPrev.push_back(tx);
- if (nDepth < COPY_DEPTH)
- foreach(const CTxIn& txin, tx.vin)
- vWorkQueue.push_back(txin.prevout.hash);
- }
- }
- }
- reverse(vtxPrev.begin(), vtxPrev.end());
- }
- bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMissingInputs)
- {
- if (pfMissingInputs)
- *pfMissingInputs = false;
- if (IsCoinBase())
- return error("AcceptTransaction() : coinbase as individual tx");
- if (!CheckTransaction())
- return error("AcceptTransaction() : CheckTransaction failed");
- uint256 hash = GetHash();
- CRITICAL_BLOCK(cs_mapTransactions)
- if (mapTransactions.count(hash))
- return false;
- if (fCheckInputs)
- if (txdb.ContainsTx(hash))
- return false;
- CTransaction* ptxOld = NULL;
- for (int i = 0; i < vin.size(); i++)
- {
- COutPoint outpoint = vin[i].prevout;
- if (mapNextTx.count(outpoint))
- {
- if (i != 0)
- return false;
- ptxOld = mapNextTx[outpoint].ptx;
- if (!IsNewerThan(*ptxOld))
- return false;
- for (int i = 0; i < vin.size(); i++)
- {
- COutPoint outpoint = vin[i].prevout;
- if (!mapNextTx.count(outpoint) || mapNextTx[outpoint].ptx != ptxOld)
- return false;
- }
- break;
- }
- }
- map<uint256, CTxIndex> mapUnused;
- int64 nFees = 0;
- if (fCheckInputs && !ConnectInputs(txdb, mapUnused, CDiskTxPos(1,1,1), 0, nFees, false, false))
- {
- if (pfMissingInputs)
- *pfMissingInputs = true;
- return error("AcceptTransaction() : ConnectInputs failed %s", hash.ToString().substr(0,6).c_str());
- }
- CRITICAL_BLOCK(cs_mapTransactions)
- {
- if (ptxOld)
- {
- printf("mapTransaction.erase(%s) replacing with new version\n", ptxOld->GetHash().ToString().c_str());
- mapTransactions.erase(ptxOld->GetHash());
- }
- AddToMemoryPool();
- }
- if (ptxOld)
- EraseFromWallet(ptxOld->GetHash());
- printf("AcceptTransaction(): accepted %s\n", hash.ToString().substr(0,6).c_str());
- return true;
- }
- bool CTransaction::AddToMemoryPool()
- {
- CRITICAL_BLOCK(cs_mapTransactions)
- {
- uint256 hash = GetHash();
- mapTransactions[hash] = *this;
- for (int i = 0; i < vin.size(); i++)
- mapNextTx[vin[i].prevout] = CInPoint(&mapTransactions[hash], i);
- nTransactionsUpdated++;
- }
- return true;
- }
- bool CTransaction::RemoveFromMemoryPool()
- {
- CRITICAL_BLOCK(cs_mapTransactions)
- {
- foreach(const CTxIn& txin, vin)
- mapNextTx.erase(txin.prevout);
- mapTransactions.erase(GetHash());
- nTransactionsUpdated++;
- }
- return true;
- }
- int CMerkleTx::GetDepthInMainChain() const
- {
- if (hashBlock == 0 || nIndex == -1)
- return 0;
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
- if (mi == mapBlockIndex.end())
- return 0;
- CBlockIndex* pindex = (*mi).second;
- if (!pindex || !pindex->IsInMainChain())
- return 0;
- if (!fMerkleVerified)
- {
- if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot)
- return 0;
- fMerkleVerified = true;
- }
- return pindexBest->nHeight - pindex->nHeight + 1;
- }
- int CMerkleTx::GetBlocksToMaturity() const
- {
- if (!IsCoinBase())
- return 0;
- return max(0, (COINBASE_MATURITY+20) - GetDepthInMainChain());
- }
- bool CMerkleTx::AcceptTransaction(CTxDB& txdb, bool fCheckInputs)
- {
- if (fClient)
- {
- if (!IsInMainChain() && !ClientConnectInputs())
- return false;
- return CTransaction::AcceptTransaction(txdb, false);
- }
- else
- {
- return CTransaction::AcceptTransaction(txdb, fCheckInputs);
- }
- }
- bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs)
- {
- CRITICAL_BLOCK(cs_mapTransactions)
- {
- foreach(CMerkleTx& tx, vtxPrev)
- {
- if (!tx.IsCoinBase())
- {
- uint256 hash = tx.GetHash();
- if (!mapTransactions.count(hash) && !txdb.ContainsTx(hash))
- tx.AcceptTransaction(txdb, fCheckInputs);
- }
- }
- if (!IsCoinBase())
- return AcceptTransaction(txdb, fCheckInputs);
- }
- return true;
- }
- void ReacceptWalletTransactions()
- {
- CTxDB txdb("r");
- CRITICAL_BLOCK(cs_mapWallet)
- {
- foreach(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
- {
- CWalletTx& wtx = item.second;
- if (!wtx.IsCoinBase() && !txdb.ContainsTx(wtx.GetHash()))
- wtx.AcceptWalletTransaction(txdb, false);
- }
- }
- }
- void CWalletTx::RelayWalletTransaction(CTxDB& txdb)
- {
- foreach(const CMerkleTx& tx, vtxPrev)
- {
- if (!tx.IsCoinBase())
- {
- uint256 hash = tx.GetHash();
- if (!txdb.ContainsTx(hash))
- RelayMessage(CInv(MSG_TX, hash), (CTransaction)tx);
- }
- }
- if (!IsCoinBase())
- {
- uint256 hash = GetHash();
- if (!txdb.ContainsTx(hash))
- {
- printf("Relaying wtx %s\n", hash.ToString().substr(0,6).c_str());
- RelayMessage(CInv(MSG_TX, hash), (CTransaction)*this);
- }
- }
- }
- void RelayWalletTransactions()
- {
- static int64 nLastTime;
- if (GetTime() - nLastTime < 10 * 60)
- return;
- nLastTime = GetTime();
- printf("RelayWalletTransactions()\n");
- CTxDB txdb("r");
- CRITICAL_BLOCK(cs_mapWallet)
- {
- multimap<unsigned int, CWalletTx*> mapSorted;
- foreach(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
- {
- CWalletTx& wtx = item.second;
- mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
- }
- foreach(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
- {
- CWalletTx& wtx = *item.second;
- wtx.RelayWalletTransaction(txdb);
- }
- }
- }
- bool CBlock::ReadFromDisk(const CBlockIndex* pblockindex, bool fReadTransactions)
- {
- return ReadFromDisk(pblockindex->nFile, pblockindex->nBlockPos, fReadTransactions);
- }
- uint256 GetOrphanRoot(const CBlock* pblock)
- {
- while (mapOrphanBlocks.count(pblock->hashPrevBlock))
- pblock = mapOrphanBlocks[pblock->hashPrevBlock];
- return pblock->GetHash();
- }
- int64 CBlock::GetBlockValue(int64 nFees) const
- {
- int64 nSubsidy = 50 * COIN;
- nSubsidy >>= (nBestHeight / 210000);
- return nSubsidy + nFees;
- }
- unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast)
- {
- const unsigned int nTargetTimespan = 14 * 24 * 60 * 60;
- const unsigned int nTargetSpacing = 10 * 60;
- const unsigned int nInterval = nTargetTimespan / nTargetSpacing;
- if (pindexLast == NULL)
- return bnProofOfWorkLimit.GetCompact();
- if ((pindexLast->nHeight+1) % nInterval != 0)
- return pindexLast->nBits;
- const CBlockIndex* pindexFirst = pindexLast;
- for (int i = 0; pindexFirst && i < nInterval-1; i++)
- pindexFirst = pindexFirst->pprev;
- assert(pindexFirst);
- unsigned int nActualTimespan = pindexLast->nTime - pindexFirst->nTime;
- printf(" nActualTimespan = %d before bounds\n", nActualTimespan);
- if (nActualTimespan < nTargetTimespan/4)
- nActualTimespan = nTargetTimespan/4;
- if (nActualTimespan > nTargetTimespan*4)
- nActualTimespan = nTargetTimespan*4;
- CBigNum bnNew;
- bnNew.SetCompact(pindexLast->nBits);
- bnNew *= nActualTimespan;
- bnNew /= nTargetTimespan;
- if (bnNew > bnProofOfWorkLimit)
- bnNew = bnProofOfWorkLimit;
- printf("\n\n\nGetNextWorkRequired RETARGET *****\n");
- printf("nTargetTimespan = %d nActualTimespan = %d\n", nTargetTimespan, nActualTimespan);
- printf("Before: %08x %s\n", pindexLast->nBits, CBigNum().SetCompact(pindexLast->nBits).getuint256().ToString().c_str());
- printf("After: %08x %s\n", bnNew.GetCompact(), bnNew.getuint256().ToString().c_str());
- return bnNew.GetCompact();
- }
- bool CTransaction::DisconnectInputs(CTxDB& txdb)
- {
- if (!IsCoinBase())
- {
- foreach(const CTxIn& txin, vin)
- {
- COutPoint prevout = txin.prevout;
- CTxIndex txindex;
- if (!txdb.ReadTxIndex(prevout.hash, txindex))
- return error("DisconnectInputs() : ReadTxIndex failed");
- if (prevout.n >= txindex.vSpent.size())
- return error("DisconnectInputs() : prevout.n out of range");
- txindex.vSpent[prevout.n].SetNull();
- txdb.UpdateTxIndex(prevout.hash, txindex);
- }
- }
- if (!txdb.EraseTxIndex(*this))
- return error("DisconnectInputs() : EraseTxPos failed");
- return true;
- }
- bool CTransaction::ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPool, CDiskTxPos posThisTx, int nHeight, int64& nFees, bool fBlock, bool fMiner, int64 nMinFee)
- {
- if (!IsCoinBase())
- {
- int64 nValueIn = 0;
- for (int i = 0; i < vin.size(); i++)
- {
- COutPoint prevout = vin[i].prevout;
- CTxIndex txindex;
- bool fFound = true;
- if (fMiner && mapTestPool.count(prevout.hash))
- {
- txindex = mapTestPool[prevout.hash];
- }
- else
- {
- fFound = txdb.ReadTxIndex(prevout.hash, txindex);
- }
- if (!fFound && (fBlock || fMiner))
- return fMiner ? false : error("ConnectInputs() : %s prev tx %s index entry not found", GetHash().ToString().substr(0,6).c_str(), prevout.hash.ToString().substr(0,6).c_str());
- CTransaction txPrev;
- if (!fFound || txindex.pos == CDiskTxPos(1,1,1))
- {
- CRITICAL_BLOCK(cs_mapTransactions)
- {
- if (!mapTransactions.count(prevout.hash))
- return error("ConnectInputs() : %s mapTransactions prev not found %s", GetHash().ToString().substr(0,6).c_str(), prevout.hash.ToString().substr(0,6).c_str());
- txPrev = mapTransactions[prevout.hash];
- }
- if (!fFound)
- txindex.vSpent.resize(txPrev.vout.size());
- }
- else
- {
- if (!txPrev.ReadFromDisk(txindex.pos))
- return error("ConnectInputs() : %s ReadFromDisk prev tx %s failed", GetHash().ToString().substr(0,6).c_str(), prevout.hash.ToString().substr(0,6).c_str());
- }
- if (prevout.n >= txPrev.vout.size() || prevout.n >= txindex.vSpent.size())
- return error("ConnectInputs() : %s prevout.n out of range %d %d %d", GetHash().ToString().substr(0,6).c_str(), prevout.n, txPrev.vout.size(), txindex.vSpent.size());
- if (txPrev.IsCoinBase())
- for (CBlockIndex* pindex = pindexBest; pindex && nBestHeight - pindex->nHeight < COINBASE_MATURITY-1; pindex = pindex->pprev)
- if (pindex->nBlockPos == txindex.pos.nBlockPos && pindex->nFile == txindex.pos.nFile)
- return error("ConnectInputs() : tried to spend coinbase at depth %d", nBestHeight - pindex->nHeight);
- if (!VerifySignature(txPrev, *this, i))
- return error("ConnectInputs() : %s VerifySignature failed", GetHash().ToString().substr(0,6).c_str());
- if (!txindex.vSpent[prevout.n].IsNull())
- return fMiner ? false : error("ConnectInputs() : %s prev tx already used at %s", GetHash().ToString().substr(0,6).c_str(), txindex.vSpent[prevout.n].ToString().c_str());
- txindex.vSpent[prevout.n] = posThisTx;
- if (fBlock)
- txdb.UpdateTxIndex(prevout.hash, txindex);
- else if (fMiner)
- mapTestPool[prevout.hash] = txindex;
- nValueIn += txPrev.vout[prevout.n].nValue;
- }
- int64 nTxFee = nValueIn - GetValueOut();
- if (nTxFee < 0)
- return error("ConnectInputs() : %s nTxFee < 0", GetHash().ToString().substr(0,6).c_str());
- if (nTxFee < nMinFee)
- return false;
- nFees += nTxFee;
- }
- if (fBlock)
- {
- if (!txdb.AddTxIndex(*this, posThisTx, nHeight))
- return error("ConnectInputs() : AddTxPos failed");
- }
- else if (fMiner)
- {
- mapTestPool[GetHash()] = CTxIndex(CDiskTxPos(1,1,1), vout.size());
- }
- return true;
- }
- bool CTransaction::ClientConnectInputs()
- {
- if (IsCoinBase())
- return false;
- CRITICAL_BLOCK(cs_mapTransactions)
- {
- int64 nValueIn = 0;
- for (int i = 0; i < vin.size(); i++)
- {
- COutPoint prevout = vin[i].prevout;
- if (!mapTransactions.count(prevout.hash))
- return false;
- CTransaction& txPrev = mapTransactions[prevout.hash];
- if (prevout.n >= txPrev.vout.size())
- return false;
- if (!VerifySignature(txPrev, *this, i))
- return error("ConnectInputs() : VerifySignature failed");
- nValueIn += txPrev.vout[prevout.n].nValue;
- }
- if (GetValueOut() > nValueIn)
- return false;
- }
- return true;
- }
- bool CBlock::DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex)
- {
- for (int i = vtx.size()-1; i >= 0; i--)
- if (!vtx[i].DisconnectInputs(txdb))
- return false;
- if (pindex->pprev)
- {
- CDiskBlockIndex blockindexPrev(pindex->pprev);
- blockindexPrev.hashNext = 0;
- txdb.WriteBlockIndex(blockindexPrev);
- }
- return true;
- }
- bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex)
- {
- unsigned int nTxPos = pindex->nBlockPos + ::GetSerializeSize(CBlock(), SER_DISK) - 1 + GetSizeOfCompactSize(vtx.size());
- map<uint256, CTxIndex> mapUnused;
- int64 nFees = 0;
- foreach(CTransaction& tx, vtx)
- {
- CDiskTxPos posThisTx(pindex->nFile, pindex->nBlockPos, nTxPos);
- nTxPos += ::GetSerializeSize(tx, SER_DISK);
- if (!tx.ConnectInputs(txdb, mapUnused, posThisTx, pindex->nHeight, nFees, true, false))
- return false;
- }
- if (vtx[0].GetValueOut() > GetBlockValue(nFees))
- return false;
- if (pindex->pprev)
- {
- CDiskBlockIndex blockindexPrev(pindex->pprev);
- blockindexPrev.hashNext = pindex->GetBlockHash();
- txdb.WriteBlockIndex(blockindexPrev);
- }
- foreach(CTransaction& tx, vtx)
- AddToWalletIfMine(tx, this);
- return true;
- }
- bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
- {
- printf("*** REORGANIZE ***\n");
- CBlockIndex* pfork = pindexBest;
- CBlockIndex* plonger = pindexNew;
- while (pfork != plonger)
- {
- if (!(pfork = pfork->pprev))
- return error("Reorganize() : pfork->pprev is null");
- while (plonger->nHeight > pfork->nHeight)
- if (!(plonger = plonger->pprev))
- return error("Reorganize() : plonger->pprev is null");
- }
- vector<CBlockIndex*> vDisconnect;
- for (CBlockIndex* pindex = pindexBest; pindex != pfork; pindex = pindex->pprev)
- vDisconnect.push_back(pindex);
- vector<CBlockIndex*> vConnect;
- for (CBlockIndex* pindex = pindexNew; pindex != pfork; pindex = pindex->pprev)
- vConnect.push_back(pindex);
- reverse(vConnect.begin(), vConnect.end());
- vector<CTransaction> vResurrect;
- foreach(CBlockIndex* pindex, vDisconnect)
- {
- CBlock block;
- if (!block.ReadFromDisk(pindex->nFile, pindex->nBlockPos, true))
- return error("Reorganize() : ReadFromDisk for disconnect failed");
- if (!block.DisconnectBlock(txdb, pindex))
- return error("Reorganize() : DisconnectBlock failed");
- foreach(const CTransaction& tx, block.vtx)
- if (!tx.IsCoinBase())
- vResurrect.push_back(tx);
- }
- vector<CTransaction> vDelete;
- for (int i = 0; i < vConnect.size(); i++)
- {
- CBlockIndex* pindex = vConnect[i];
- CBlock block;
- if (!block.ReadFromDisk(pindex->nFile, pindex->nBlockPos, true))
- return error("Reorganize() : ReadFromDisk for connect failed");
- if (!block.ConnectBlock(txdb, pindex))
- {
- txdb.TxnAbort();
- for (int j = i; j < vConnect.size(); j++)
- {
- CBlockIndex* pindex = vConnect[j];
- pindex->EraseBlockFromDisk();
- txdb.EraseBlockIndex(pindex->GetBlockHash());
- mapBlockIndex.erase(pindex->GetBlockHash());
- delete pindex;
- }
- return error("Reorganize() : ConnectBlock failed");
- }
- foreach(const CTransaction& tx, block.vtx)
- vDelete.push_back(tx);
- }
- if (!txdb.WriteHashBestChain(pindexNew->GetBlockHash()))
- return error("Reorganize() : WriteHashBestChain failed");
- txdb.TxnCommit();
- foreach(CBlockIndex* pindex, vDisconnect)
- if (pindex->pprev)
- pindex->pprev->pnext = NULL;
- foreach(CBlockIndex* pindex, vConnect)
- if (pindex->pprev)
- pindex->pprev->pnext = pindex;
- foreach(CTransaction& tx, vResurrect)
- tx.AcceptTransaction(txdb, false);
- foreach(CTransaction& tx, vDelete)
- tx.RemoveFromMemoryPool();
- return true;
- }
- bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
- {
- uint256 hash = GetHash();
- if (mapBlockIndex.count(hash))
- return error("AddToBlockIndex() : %s already exists", hash.ToString().substr(0,14).c_str());
- CBlockIndex* pindexNew = new CBlockIndex(nFile, nBlockPos, *this);
- if (!pindexNew)
- return error("AddToBlockIndex() : new CBlockIndex failed");
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
- pindexNew->phashBlock = &((*mi).first);
- map<uint256, CBlockIndex*>::iterator miPrev = mapBlockIndex.find(hashPrevBlock);
- if (miPrev != mapBlockIndex.end())
- {
- pindexNew->pprev = (*miPrev).second;
- pindexNew->nHeight = pindexNew->pprev->nHeight + 1;
- }
- CTxDB txdb;
- txdb.TxnBegin();
- txdb.WriteBlockIndex(CDiskBlockIndex(pindexNew));
- if (pindexNew->nHeight > nBestHeight)
- {
- if (pindexGenesisBlock == NULL && hash == hashGenesisBlock)
- {
- pindexGenesisBlock = pindexNew;
- txdb.WriteHashBestChain(hash);
- }
- else if (hashPrevBlock == hashBestChain)
- {
- if (!ConnectBlock(txdb, pindexNew) || !txdb.WriteHashBestChain(hash))
- {
- txdb.TxnAbort();
- pindexNew->EraseBlockFromDisk();
- mapBlockIndex.erase(pindexNew->GetBlockHash());
- delete pindexNew;
- return error("AddToBlockIndex() : ConnectBlock failed");
- }
- txdb.TxnCommit();
- pindexNew->pprev->pnext = pindexNew;
- foreach(CTransaction& tx, vtx)
- tx.RemoveFromMemoryPool();
- }
- else
- {
- if (!Reorganize(txdb, pindexNew))
- {
- txdb.TxnAbort();
- return error("AddToBlockIndex() : Reorganize failed");
- }
- }
- hashBestChain = hash;
- pindexBest = pindexNew;
- nBestHeight = pindexBest->nHeight;
- nTransactionsUpdated++;
- printf("AddToBlockIndex: new best=%s height=%d\n", hashBestChain.ToString().substr(0,14).c_str(), nBestHeight);
- }
- txdb.TxnCommit();
- txdb.Close();
- if (pindexNew == pindexBest)
- RelayWalletTransactions();
- MainFrameRepaint();
- return true;
- }
- bool CBlock::CheckBlock() const
- {
- if (vtx.empty() || vtx.size() > MAX_SIZE || ::GetSerializeSize(*this, SER_DISK) > MAX_SIZE)
- return error("CheckBlock() : size limits failed");
- if (nTime > GetAdjustedTime() + 2 * 60 * 60)
- return error("CheckBlock() : block timestamp too far in the future");
- if (vtx.empty() || !vtx[0].IsCoinBase())
- return error("CheckBlock() : first tx is not coinbase");
- for (int i = 1; i < vtx.size(); i++)
- if (vtx[i].IsCoinBase())
- return error("CheckBlock() : more than one coinbase");
- foreach(const CTransaction& tx, vtx)
- if (!tx.CheckTransaction())
- return error("CheckBlock() : CheckTransaction failed");
- if (CBigNum().SetCompact(nBits) > bnProofOfWorkLimit)
- return error("CheckBlock() : nBits below minimum work");
- if (GetHash() > CBigNum().SetCompact(nBits).getuint256())
- return error("CheckBlock() : hash doesn't match nBits");
- if (hashMerkleRoot != BuildMerkleTree())
- return error("CheckBlock() : hashMerkleRoot mismatch");
- return true;
- }
- bool CBlock::AcceptBlock()
- {
- uint256 hash = GetHash();
- if (mapBlockIndex.count(hash))
- return error("AcceptBlock() : block already in mapBlockIndex");
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashPrevBlock);
- if (mi == mapBlockIndex.end())
- return error("AcceptBlock() : prev block not found");
- CBlockIndex* pindexPrev = (*mi).second;
- if (nTime <= pindexPrev->GetMedianTimePast())
- return error("AcceptBlock() : block's timestamp is too early");
- if (nBits != GetNextWorkRequired(pindexPrev))
- return error("AcceptBlock() : incorrect proof of work");
- unsigned int nFile;
- unsigned int nBlockPos;
- if (!WriteToDisk(!fClient, nFile, nBlockPos))
- return error("AcceptBlock() : WriteToDisk failed");
- if (!AddToBlockIndex(nFile, nBlockPos))
- return error("AcceptBlock() : AddToBlockIndex failed");
- if (hashBestChain == hash)
- RelayInventory(CInv(MSG_BLOCK, hash));
- return true;
- }
- bool ProcessBlock(CNode* pfrom, CBlock* pblock)
- {
- uint256 hash = pblock->GetHash();
- if (mapBlockIndex.count(hash))
- return error("ProcessBlock() : already have block %d %s", mapBlockIndex[hash]->nHeight, hash.ToString().substr(0,14).c_str());
- if (mapOrphanBlocks.count(hash))
- return error("ProcessBlock() : already have block (orphan) %s", hash.ToString().substr(0,14).c_str());
- if (!pblock->CheckBlock())
- {
- delete pblock;
- return error("ProcessBlock() : CheckBlock FAILED");
- }
- if (!mapBlockIndex.count(pblock->hashPrevBlock))
- {
- printf("ProcessBlock: ORPHAN BLOCK, prev=%s\n", pblock->hashPrevBlock.ToString().substr(0,14).c_str());
- mapOrphanBlocks.insert(make_pair(hash, pblock));
- mapOrphanBlocksByPrev.insert(make_pair(pblock->hashPrevBlock, pblock));
- if (pfrom)
- pfrom->PushMessage("getblocks", CBlockLocator(pindexBest), GetOrphanRoot(pblock));
- return true;
- }
- if (!pblock->AcceptBlock())
- {
- delete pblock;
- return error("ProcessBlock() : AcceptBlock FAILED");
- }
- delete pblock;
- vector<uint256> vWorkQueue;
- vWorkQueue.push_back(hash);
- for (int i = 0; i < vWorkQueue.size(); i++)
- {
- uint256 hashPrev = vWorkQueue[i];
- for (multimap<uint256, CBlock*>::iterator mi = mapOrphanBlocksByPrev.lower_bound(hashPrev);
- mi != mapOrphanBlocksByPrev.upper_bound(hashPrev);
- ++mi)
- {
- CBlock* pblockOrphan = (*mi).second;
- if (pblockOrphan->AcceptBlock())
- vWorkQueue.push_back(pblockOrphan->GetHash());
- mapOrphanBlocks.erase(pblockOrphan->GetHash());
- delete pblockOrphan;
- }
- mapOrphanBlocksByPrev.erase(hashPrev);
- }
- printf("ProcessBlock: ACCEPTED\n");
- return true;
- }
- template<typename Stream>
- bool ScanMessageStart(Stream& s)
- {
- s.clear(0);
- short prevmask = s.exceptions(0);
- const char* p = BEGIN(pchMessageStart);
- try
- {
- loop
- {
- char c;
- s.read(&c, 1);
- if (s.fail())
- {
- s.clear(0);
- s.exceptions(prevmask);
- return false;
- }
- if (*p != c)
- p = BEGIN(pchMessageStart);
- if (*p == c)
- {
- if (++p == END(pchMessageStart))
- {
- s.clear(0);
- s.exceptions(prevmask);
- return true;
- }
- }
- }
- }
- catch (...)
- {
- s.clear(0);
- s.exceptions(prevmask);
- return false;
- }
- }
- string GetAppDir()
- {
- string strDir;
- if (!strSetDataDir.empty())
- {
- strDir = strSetDataDir;
- }
- else if (getenv("APPDATA"))
- {
- strDir = strprintf("%s\\Bitcoin", getenv("APPDATA"));
- }
- else if (getenv("USERPROFILE"))
- {
- string strAppData = strprintf("%s\\Application Data", getenv("USERPROFILE"));
- static bool fMkdirDone;
- if (!fMkdirDone)
- {
- fMkdirDone = true;
- _mkdir(strAppData.c_str());
- }
- strDir = strprintf("%s\\Bitcoin", strAppData.c_str());
- }
- else
- {
- return ".";
- }
- static bool fMkdirDone;
- if (!fMkdirDone)
- {
- fMkdirDone = true;
- _mkdir(strDir.c_str());
- }
- return strDir;
- }
- FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode)
- {
- if (nFile == -1)
- return NULL;
- FILE* file = fopen(strprintf("%s\\blk%04d.dat", GetAppDir().c_str(), nFile).c_str(), pszMode);
- if (!file)
- return NULL;
- if (nBlockPos != 0 && !strchr(pszMode, 'a') && !strchr(pszMode, 'w'))
- {
- if (fseek(file, nBlockPos, SEEK_SET) != 0)
- {
- fclose(file);
- return NULL;
- }
- }
- return file;
- }
- static unsigned int nCurrentBlockFile = 1;
- FILE* AppendBlockFile(unsigned int& nFileRet)
- {
- nFileRet = 0;
- loop
- {
- FILE* file = OpenBlockFile(nCurrentBlockFile, 0, "ab");
- if (!file)
- return NULL;
- if (fseek(file, 0, SEEK_END) != 0)
- return NULL;
- if (ftell(file) < 0x7F000000 - MAX_SIZE)
- {
- nFileRet = nCurrentBlockFile;
- return file;
- }
- fclose(file);
- nCurrentBlockFile++;
- }
- }
- bool LoadBlockIndex(bool fAllowNew)
- {
- CTxDB txdb("cr");
- if (!txdb.LoadBlockIndex())
- return false;
- txdb.Close();
- if (mapBlockIndex.empty())
- {
- if (!fAllowNew)
- return false;
- char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";
- CTransaction txNew;
- txNew.vin.resize(1);
- txNew.vout.resize(1);
- txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((unsigned char*)pszTimestamp, (unsigned char*)pszTimestamp + strlen(pszTimestamp));
- txNew.vout[0].nValue = 50 * COIN;
- txNew.vout[0].scriptPubKey = CScript() << CBigNum("0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704") << OP_CHECKSIG;
- CBlock block;
- block.vtx.push_back(txNew);
- block.hashPrevBlock = 0;
- block.hashMerkleRoot = block.BuildMerkleTree();
- block.nVersion = 1;
- block.nTime = 1231006505;
- block.nBits = 0x1d00ffff;
- block.nNonce = 2083236893;
- printf("%s\n", block.GetHash().ToString().c_str());
- printf("%s\n", block.hashMerkleRoot.ToString().c_str());
- printf("%s\n", hashGenesisBlock.ToString().c_str());
- txNew.vout[0].scriptPubKey.print();
- block.print();
- assert(block.hashMerkleRoot == uint256("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
- assert(block.GetHash() == hashGenesisBlock);
- unsigned int nFile;
- unsigned int nBlockPos;
- if (!block.WriteToDisk(!fClient, nFile, nBlockPos))
- return error("LoadBlockIndex() : writing genesis block to disk failed");
- if (!block.AddToBlockIndex(nFile, nBlockPos))
- return error("LoadBlockIndex() : genesis block not accepted");
- }
- return true;
- }
- void PrintBlockTree()
- {
- map<CBlockIndex*, vector<CBlockIndex*> > mapNext;
- for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
- {
- CBlockIndex* pindex = (*mi).second;
- mapNext[pindex->pprev].push_back(pindex);
- }
- vector<pair<int, CBlockIndex*> > vStack;
- vStack.push_back(make_pair(0, pindexGenesisBlock));
- int nPrevCol = 0;
- while (!vStack.empty())
- {
- int nCol = vStack.back().first;
- CBlockIndex* pindex = vStack.back().second;
- vStack.pop_back();
- if (nCol > nPrevCol)
- {
- for (int i = 0; i < nCol-1; i++)
- printf("| ");
- printf("|\\\n");
- }
- else if (nCol < nPrevCol)
- {
- for (int i = 0; i < nCol; i++)
- printf("| ");
- printf("|\n");
- }
- nPrevCol = nCol;
- for (int i = 0; i < nCol; i++)
- printf("| ");
- CBlock block;
- block.ReadFromDisk(pindex, true);
- printf("%d (%u,%u) %s %s tx %d",
- pindex->nHeight,
- pindex->nFile,
- pindex->nBlockPos,
- block.GetHash().ToString().substr(0,14).c_str(),
- DateTimeStr(block.nTime).c_str(),
- block.vtx.size());
- CRITICAL_BLOCK(cs_mapWallet)
- {
- if (mapWallet.count(block.vtx[0].GetHash()))
- {
- CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
- printf(" mine: %d %d %d", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
- }
- }
- printf("\n");
- vector<CBlockIndex*>& vNext = mapNext[pindex];
- for (int i = 0; i < vNext.size(); i++)
- {
- if (vNext[i]->pnext)
- {
- swap(vNext[0], vNext[i]);
- break;
- }
- }
- for (int i = 0; i < vNext.size(); i++)
- vStack.push_back(make_pair(nCol+i, vNext[i]));
- }
- }bool AlreadyHave(CTxDB& txdb, const CInv& inv)
- {
- switch (inv.type)
- {
- case MSG_TX: return mapTransactions.count(inv.hash) || txdb.ContainsTx(inv.hash);
- case MSG_BLOCK: return mapBlockIndex.count(inv.hash) || mapOrphanBlocks.count(inv.hash);
- case MSG_REVIEW: return true;
- case MSG_PRODUCT: return mapProducts.count(inv.hash);
- }
- return true;
- }
- bool ProcessMessages(CNode* pfrom)
- {
- CDataStream& vRecv = pfrom->vRecv;
- if (vRecv.empty())
- return true;
- printf("ProcessMessages(%d bytes)\n", vRecv.size());
- loop
- {
- CDataStream::iterator pstart = search(vRecv.begin(), vRecv.end(), BEGIN(pchMessageStart), END(pchMessageStart));
- if (vRecv.end() - pstart < sizeof(CMessageHeader))
- {
- if (vRecv.size() > sizeof(CMessageHeader))
- {
- printf("\n\nPROCESSMESSAGE MESSAGESTART NOT FOUND\n\n");
- vRecv.erase(vRecv.begin(), vRecv.end() - sizeof(CMessageHeader));
- }
- break;
- }
- if (pstart - vRecv.begin() > 0)
- printf("\n\nPROCESSMESSAGE SKIPPED %d BYTES\n\n", pstart - vRecv.begin());
- vRecv.erase(vRecv.begin(), pstart);
- CMessageHeader hdr;
- vRecv >> hdr;
- if (!hdr.IsValid())
- {
- printf("\n\nPROCESSMESSAGE: ERRORS IN HEADER %s\n\n\n", hdr.GetCommand().c_str());
- continue;
- }
- string strCommand = hdr.GetCommand();
- unsigned int nMessageSize = hdr.nMessageSize;
- if (nMessageSize > vRecv.size())
- {
- printf("MESSAGE-BREAK 2\n");
- vRecv.insert(vRecv.begin(), BEGIN(hdr), END(hdr));
- Sleep(100);
- break;
- }
- CDataStream vMsg(vRecv.begin(), vRecv.begin() + nMessageSize, vRecv.nType, vRecv.nVersion);
- vRecv.ignore(nMessageSize);
- bool fRet = false;
- try
- {
- CheckForShutdown(2);
- CRITICAL_BLOCK(cs_main)
- fRet = ProcessMessage(pfrom, strCommand, vMsg);
- CheckForShutdown(2);
- }
- CATCH_PRINT_EXCEPTION("ProcessMessage()")
- if (!fRet)
- printf("ProcessMessage(%s, %d bytes) from %s to %s FAILED\n", strCommand.c_str(), nMessageSize, pfrom->addr.ToString().c_str(), addrLocalHost.ToString().c_str());
- }
- vRecv.Compact();
- return true;
- }
- bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
- {
- static map<unsigned int, vector<unsigned char> > mapReuseKey;
- printf("received: %-12s (%d bytes) ", strCommand.c_str(), vRecv.size());
- for (int i = 0; i < min(vRecv.size(), (unsigned int)25); i++)
- printf("%02x ", vRecv[i] & 0xff);
- printf("\n");
- if (nDropMessagesTest > 0 && GetRand(nDropMessagesTest) == 0)
- {
- printf("dropmessages DROPPING RECV MESSAGE\n");
- return true;
- }
- if (strCommand == "version")
- {
- if (pfrom->nVersion != 0)
- return false;
- int64 nTime;
- CAddress addrMe;
- vRecv >> pfrom->nVersion >> pfrom->nServices >> nTime >> addrMe;
- if (pfrom->nVersion == 0)
- return false;
- pfrom->vSend.SetVersion(min(pfrom->nVersion, VERSION));
- pfrom->vRecv.SetVersion(min(pfrom->nVersion, VERSION));
- pfrom->fClient = !(pfrom->nServices & NODE_NETWORK);
- if (pfrom->fClient)
- {
- pfrom->vSend.nType |= SER_BLOCKHEADERONLY;
- pfrom->vRecv.nType |= SER_BLOCKHEADERONLY;
- }
- AddTimeData(pfrom->addr.ip, nTime);
- static bool fAskedForBlocks;
- if (!fAskedForBlocks && !pfrom->fClient)
- {
- fAskedForBlocks = true;
- pfrom->PushMessage("getblocks", CBlockLocator(pindexBest), uint256(0));
- }
- printf("version addrMe = %s\n", addrMe.ToString().c_str());
- }
- else if (pfrom->nVersion == 0)
- {
- return false;
- }
- else if (strCommand == "addr")
- {
- vector<CAddress> vAddr;
- vRecv >> vAddr;
- CAddrDB addrdb;
- foreach(const CAddress& addr, vAddr)
- {
- if (fShutdown)
- return true;
- if (AddAddress(addrdb, addr))
- {
- pfrom->setAddrKnown.insert(addr);
- CRITICAL_BLOCK(cs_vNodes)
- foreach(CNode* pnode, vNodes)
- if (!pnode->setAddrKnown.count(addr))
- pnode->vAddrToSend.push_back(addr);
- }
- }
- }
- else if (strCommand == "inv")
- {
- vector<CInv> vInv;
- vRecv >> vInv;
- CTxDB txdb("r");
- foreach(const CInv& inv, vInv)
- {
- if (fShutdown)
- return true;
- pfrom->AddInventoryKnown(inv);
- bool fAlreadyHave = AlreadyHave(txdb, inv);
- printf(" got inventory: %s %s\n", inv.ToString().c_str(), fAlreadyHave ? "have" : "new");
- if (!fAlreadyHave)
- pfrom->AskFor(inv);
- else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash))
- pfrom->PushMessage("getblocks", CBlockLocator(pindexBest), GetOrphanRoot(mapOrphanBlocks[inv.hash]));
- }
- }
- else if (strCommand == "getdata")
- {
- vector<CInv> vInv;
- vRecv >> vInv;
- foreach(const CInv& inv, vInv)
- {
- if (fShutdown)
- return true;
- printf("received getdata for: %s\n", inv.ToString().c_str());
- if (inv.type == MSG_BLOCK)
- {
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(inv.hash);
- if (mi != mapBlockIndex.end())
- {
- CBlock block;
- block.ReadFromDisk((*mi).second, !pfrom->fClient);
- pfrom->PushMessage("block", block);
- }
- }
- else if (inv.IsKnownType())
- {
- CRITICAL_BLOCK(cs_mapRelay)
- {
- map<CInv, CDataStream>::iterator mi = mapRelay.find(inv);
- if (mi != mapRelay.end())
- pfrom->PushMessage(inv.GetCommand(), (*mi).second);
- }
- }
- }
- }
- else if (strCommand == "getblocks")
- {
- CBlockLocator locator;
- uint256 hashStop;
- vRecv >> locator >> hashStop;
- CBlockIndex* pindex = locator.GetBlockIndex();
- if (pindex)
- pindex = pindex->pnext;
- printf("getblocks %d to %s\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().substr(0,14).c_str());
- for (; pindex; pindex = pindex->pnext)
- {
- if (pindex->GetBlockHash() == hashStop)
- {
- printf(" getblocks stopping at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,14).c_str());
- break;
- }
- CRITICAL_BLOCK(pfrom->cs_inventory)
- {
- CInv inv(MSG_BLOCK, pindex->GetBlockHash());
- if (pfrom->setInventoryKnown2.insert(inv).second)
- {
- pfrom->setInventoryKnown.erase(inv);
- pfrom->vInventoryToSend.push_back(inv);
- }
- }
- }
- }
- else if (strCommand == "tx")
- {
- vector<uint256> vWorkQueue;
- CDataStream vMsg(vRecv);
- CTransaction tx;
- vRecv >> tx;
- CInv inv(MSG_TX, tx.GetHash());
- pfrom->AddInventoryKnown(inv);
- bool fMissingInputs = false;
- if (tx.AcceptTransaction(true, &fMissingInputs))
- {
- AddToWalletIfMine(tx, NULL);
- RelayMessage(inv, vMsg);
- mapAlreadyAskedFor.erase(inv);
- vWorkQueue.push_back(inv.hash);
- for (int i = 0; i < vWorkQueue.size(); i++)
- {
- uint256 hashPrev = vWorkQueue[i];
- for (multimap<uint256, CDataStream*>::iterator mi = mapOrphanTransactionsByPrev.lower_bound(hashPrev);
- mi != mapOrphanTransactionsByPrev.upper_bound(hashPrev);
- ++mi)
- {
- const CDataStream& vMsg = *((*mi).second);
- CTransaction tx;
- CDataStream(vMsg) >> tx;
- CInv inv(MSG_TX, tx.GetHash());
- if (tx.AcceptTransaction(true))
- {
- printf(" accepted orphan tx %s\n", inv.hash.ToString().substr(0,6).c_str());
- AddToWalletIfMine(tx, NULL);
- RelayMessage(inv, vMsg);
- mapAlreadyAskedFor.erase(inv);
- vWorkQueue.push_back(inv.hash);
- }
- }
- }
- foreach(uint256 hash, vWorkQueue)
- EraseOrphanTx(hash);
- }
- else if (fMissingInputs)
- {
- printf("storing orphan tx %s\n", inv.hash.ToString().substr(0,6).c_str());
- AddOrphanTx(vMsg);
- }
- }
- else if (strCommand == "review")
- {
- CDataStream vMsg(vRecv);
- CReview review;
- vRecv >> review;
- CInv inv(MSG_REVIEW, review.GetHash());
- pfrom->AddInventoryKnown(inv);
- if (review.AcceptReview())
- {
- RelayMessage(inv, vMsg);
- mapAlreadyAskedFor.erase(inv);
- }
- }
- else if (strCommand == "block")
- {
- auto_ptr<CBlock> pblock(new CBlock);
- vRecv >> *pblock;
- printf("received block:\n"); pblock->print();
- CInv inv(MSG_BLOCK, pblock->GetHash());
- pfrom->AddInventoryKnown(inv);
- if (ProcessBlock(pfrom, pblock.release()))
- mapAlreadyAskedFor.erase(inv);
- }
- else if (strCommand == "getaddr")
- {
- pfrom->vAddrToSend.clear();
- int64 nSince = GetAdjustedTime() - 60 * 60;
- CRITICAL_BLOCK(cs_mapAddresses)
- {
- foreach(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
- {
- if (fShutdown)
- return true;
- const CAddress& addr = item.second;
- if (addr.nTime > nSince)
- pfrom->vAddrToSend.push_back(addr);
- }
- }
- }
- else if (strCommand == "checkorder")
- {
- uint256 hashReply;
- CWalletTx order;
- vRecv >> hashReply >> order;
- if (!mapReuseKey.count(pfrom->addr.ip))
- mapReuseKey[pfrom->addr.ip] = GenerateNewKey();
- CScript scriptPubKey;
- scriptPubKey << mapReuseKey[pfrom->addr.ip] << OP_CHECKSIG;
- pfrom->PushMessage("reply", hashReply, (int)0, scriptPubKey);
- }
- else if (strCommand == "submitorder")
- {
- uint256 hashReply;
- CWalletTx wtxNew;
- vRecv >> hashReply >> wtxNew;
- if (!wtxNew.AcceptWalletTransaction())
- {
- pfrom->PushMessage("reply", hashReply, (int)1);
- return error("submitorder AcceptWalletTransaction() failed, returning error 1");
- }
- wtxNew.fTimeReceivedIsTxTime = true;
- AddToWallet(wtxNew);
- wtxNew.RelayWalletTransaction();
- mapReuseKey.erase(pfrom->addr.ip);
- pfrom->PushMessage("reply", hashReply, (int)0);
- }
- else if (strCommand == "reply")
- {
- uint256 hashReply;
- vRecv >> hashReply;
- CRequestTracker tracker;
- CRITICAL_BLOCK(pfrom->cs_mapRequests)
- {
- map<uint256, CRequestTracker>::iterator mi = pfrom->mapRequests.find(hashReply);
- if (mi != pfrom->mapRequests.end())
- {
- tracker = (*mi).second;
- pfrom->mapRequests.erase(mi);
- }
- }
- if (!tracker.IsNull())
- tracker.fn(tracker.param1, vRecv);
- }
- else
- {
- printf("ProcessMessage(%s) : Ignored unknown message\n", strCommand.c_str());
- }
- if (!vRecv.empty())
- printf("ProcessMessage(%s) : %d extra bytes\n", strCommand.c_str(), vRecv.size());
- return true;
- }
- bool SendMessages(CNode* pto)
- {
- CheckForShutdown(2);
- CRITICAL_BLOCK(cs_main)
- {
- if (pto->nVersion == 0)
- return true;
- vector<CAddress> vAddrToSend;
- vAddrToSend.reserve(pto->vAddrToSend.size());
- foreach(const CAddress& addr, pto->vAddrToSend)
- if (!pto->setAddrKnown.count(addr))
- vAddrToSend.push_back(addr);
- pto->vAddrToSend.clear();
- if (!vAddrToSend.empty())
- pto->PushMessage("addr", vAddrToSend);
- vector<CInv> vInventoryToSend;
- CRITICAL_BLOCK(pto->cs_inventory)
- {
- vInventoryToSend.reserve(pto->vInventoryToSend.size());
- foreach(const CInv& inv, pto->vInventoryToSend)
- {
- if (pto->setInventoryKnown.insert(inv).second)
- vInventoryToSend.push_back(inv);
- }
- pto->vInventoryToSend.clear();
- pto->setInventoryKnown2.clear();
- }
- if (!vInventoryToSend.empty())
- pto->PushMessage("inv", vInventoryToSend);
- vector<CInv> vAskFor;
- int64 nNow = GetTime() * 1000000;
- CTxDB txdb("r");
- while (!pto->mapAskFor.empty() && (*pto->mapAskFor.begin()).first <= nNow)
- {
- const CInv& inv = (*pto->mapAskFor.begin()).second;
- printf("sending getdata: %s\n", inv.ToString().c_str());
- if (!AlreadyHave(txdb, inv))
- vAskFor.push_back(inv);
- pto->mapAskFor.erase(pto->mapAskFor.begin());
- }
- if (!vAskFor.empty())
- pto->PushMessage("getdata", vAskFor);
- }
- return true;
- }
- int FormatHashBlocks(void* pbuffer, unsigned int len)
- {
- unsigned char* pdata = (unsigned char*)pbuffer;
- unsigned int blocks = 1 + ((len + 8) / 64);
- unsigned char* pend = pdata + 64 * blocks;
- memset(pdata + len, 0, 64 * blocks - len);
- pdata[len] = 0x80;
- unsigned int bits = len * 8;
- pend[-1] = (bits >> 0) & 0xff;
- pend[-2] = (bits >> 8) & 0xff;
- pend[-3] = (bits >> 16) & 0xff;
- pend[-4] = (bits >> 24) & 0xff;
- return blocks;
- }
- using CryptoPP::ByteReverse;
- static int detectlittleendian = 1;
- void BlockSHA256(const void* pin, unsigned int nBlocks, void* pout)
- {
- unsigned int* pinput = (unsigned int*)pin;
- unsigned int* pstate = (unsigned int*)pout;
- CryptoPP::SHA256::InitState(pstate);
- if (*(char*)&detectlittleendian != 0)
- {
- for (int n = 0; n < nBlocks; n++)
- {
- unsigned int pbuf[16];
- for (int i = 0; i < 16; i++)
- pbuf[i] = ByteReverse(pinput[n * 16 + i]);
- CryptoPP::SHA256::Transform(pstate, pbuf);
- }
- for (int i = 0; i < 8; i++)
- pstate[i] = ByteReverse(pstate[i]);
- }
- else
- {
- for (int n = 0; n < nBlocks; n++)
- CryptoPP::SHA256::Transform(pstate, pinput + n * 16);
- }
- }
- bool BitcoinMiner()
- { printf("BitcoinMiner started\n");
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);
- CKey key;
- key.MakeNewKey();
- CBigNum bnExtraNonce = 0;
- while (fGenerateBitcoins)
- {
- Sleep(50);
- CheckForShutdown(3);
- while (vNodes.empty())
- {
- Sleep(1000);
- CheckForShutdown(3);
- }
- unsigned int nTransactionsUpdatedLast = nTransactionsUpdated;
- CBlockIndex* pindexPrev = pindexBest;
- unsigned int nBits = GetNextWorkRequired(pindexPrev);
- CTransaction txNew;
- txNew.vin.resize(1);
- txNew.vin[0].prevout.SetNull();
- txNew.vin[0].scriptSig << nBits << ++bnExtraNonce;
- txNew.vout.resize(1);
- txNew.vout[0].scriptPubKey << key.GetPubKey() << OP_CHECKSIG;
- auto_ptr<CBlock> pblock(new CBlock());
- if (!pblock.get())
- return false;
- pblock->vtx.push_back(txNew);
- int64 nFees = 0;
- CRITICAL_BLOCK(cs_main)
- CRITICAL_BLOCK(cs_mapTransactions)
- {
- CTxDB txdb("r");
- map<uint256, CTxIndex> mapTestPool;
- vector<char> vfAlreadyAdded(mapTransactions.size());
- bool fFoundSomething = true;
- unsigned int nBlockSize = 0;
- while (fFoundSomething && nBlockSize < MAX_SIZE/2)
- {
- fFoundSomething = false;
- unsigned int n = 0;
- for (map<uint256, CTransaction>::iterator mi = mapTransactions.begin(); mi != mapTransactions.end(); ++mi, ++n)
- {
- if (vfAlreadyAdded[n])
- continue;
- CTransaction& tx = (*mi).second;
- if (tx.IsCoinBase() || !tx.IsFinal())
- continue;
- int64 nMinFee = tx.GetMinFee(pblock->vtx.size() < 100);
- map<uint256, CTxIndex> mapTestPoolTmp(mapTestPool);
- if (!tx.ConnectInputs(txdb, mapTestPoolTmp, CDiskTxPos(1,1,1), 0, nFees, false, true, nMinFee))
- continue;
- swap(mapTestPool, mapTestPoolTmp);
- pblock->vtx.push_back(tx);
- nBlockSize += ::GetSerializeSize(tx, SER_NETWORK);
- vfAlreadyAdded[n] = true;
- fFoundSomething = true;
- }
- }
- }
- pblock->nBits = nBits;
- pblock->vtx[0].vout[0].nValue = pblock->GetBlockValue(nFees);
- printf("\n\nRunning BitcoinMiner with %d transactions in block\n", pblock->vtx.size());
- struct unnamed1
- {
- struct unnamed2
- {
- int nVersion;
- uint256 hashPrevBlock;
- uint256 hashMerkleRoot;
- unsigned int nTime;
- unsigned int nBits;
- unsigned int nNonce;
- }
- block;
- unsigned char pchPadding0[64];
- uint256 hash1;
- unsigned char pchPadding1[64];
- }
- tmp;
- tmp.block.nVersion = pblock->nVersion;
- tmp.block.hashPrevBlock = pblock->hashPrevBlock = (pindexPrev ? pindexPrev->GetBlockHash() : 0);
- tmp.block.hashMerkleRoot = pblock->hashMerkleRoot = pblock->BuildMerkleTree();
- tmp.block.nTime = pblock->nTime = max((pindexPrev ? pindexPrev->GetMedianTimePast()+1 : 0), GetAdjustedTime());
- tmp.block.nBits = pblock->nBits = nBits;
- tmp.block.nNonce = pblock->nNonce = 1;
- unsigned int nBlocks0 = FormatHashBlocks(&tmp.block, sizeof(tmp.block));
- unsigned int nBlocks1 = FormatHashBlocks(&tmp.hash1, sizeof(tmp.hash1));
- unsigned int nStart = GetTime();
- uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
- uint256 hash;
- loop
- {
- BlockSHA256(&tmp.block, nBlocks0, &tmp.hash1);
- BlockSHA256(&tmp.hash1, nBlocks1, &hash);
- if (hash <= hashTarget)
- {
- pblock->nNonce = tmp.block.nNonce;
- assert(hash == pblock->GetHash());
- printf("BitcoinMiner:\n");
- printf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex().c_str(), hashTarget.GetHex().c_str());
- pblock->print();
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
- CRITICAL_BLOCK(cs_main)
- {
- if (!AddKey(key))
- return false;
- key.MakeNewKey();
- if (!ProcessBlock(NULL, pblock.release()))
- printf("ERROR in BitcoinMiner, ProcessBlock, block not accepted\n");
- }
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);
- Sleep(500);
- break;
- }
- if ((++tmp.block.nNonce & 0x3ffff) == 0)
- {
- CheckForShutdown(3);
- if (tmp.block.nNonce == 0)
- break;
- if (pindexPrev != pindexBest)
- break;
- if (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60)
- break;
- if (!fGenerateBitcoins)
- break;
- tmp.block.nTime = pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
- }
- }
- }
- return true;
- }
- int64 GetBalance()
- {
- int64 nStart, nEnd;
- QueryPerformanceCounter((LARGE_INTEGER*)&nStart);
- int64 nTotal = 0;
- CRITICAL_BLOCK(cs_mapWallet)
- {
- for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
- {
- CWalletTx* pcoin = &(*it).second;
- if (!pcoin->IsFinal() || pcoin->fSpent)
- continue;
- nTotal += pcoin->GetCredit();
- }
- }
- QueryPerformanceCounter((LARGE_INTEGER*)&nEnd);
- return nTotal;
- }
- bool SelectCoins(int64 nTargetValue, set<CWalletTx*>& setCoinsRet)
- {
- setCoinsRet.clear();
- int64 nLowestLarger = _I64_MAX;
- CWalletTx* pcoinLowestLarger = NULL;
- vector<pair<int64, CWalletTx*> > vValue;
- int64 nTotalLower = 0;
- CRITICAL_BLOCK(cs_mapWallet)
- {
- for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
- {
- CWalletTx* pcoin = &(*it).second;
- if (!pcoin->IsFinal() || pcoin->fSpent)
- continue;
- int64 n = pcoin->GetCredit();
- if (n <= 0)
- continue;
- if (n < nTargetValue)
- {
- vValue.push_back(make_pair(n, pcoin));
- nTotalLower += n;
- }
- else if (n == nTargetValue)
- {
- setCoinsRet.insert(pcoin);
- return true;
- }
- else if (n < nLowestLarger)
- {
- nLowestLarger = n;
- pcoinLowestLarger = pcoin;
- }
- }
- }
- if (nTotalLower < nTargetValue)
- {
- if (pcoinLowestLarger == NULL)
- return false;
- setCoinsRet.insert(pcoinLowestLarger);
- return true;
- }
- sort(vValue.rbegin(), vValue.rend());
- vector<char> vfIncluded;
- vector<char> vfBest(vValue.size(), true);
- int64 nBest = nTotalLower;
- for (int nRep = 0; nRep < 1000 && nBest != nTargetValue; nRep++)
- {
- vfIncluded.assign(vValue.size(), false);
- int64 nTotal = 0;
- bool fReachedTarget = false;
- for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
- {
- for (int i = 0; i < vValue.size(); i++)
- {
- if (nPass == 0 ? rand() % 2 : !vfIncluded[i])
- {
- nTotal += vValue[i].first;
- vfIncluded[i] = true;
- if (nTotal >= nTargetValue)
- {
- fReachedTarget = true;
- if (nTotal < nBest)
- {
- nBest = nTotal;
- vfBest = vfIncluded;
- }
- nTotal -= vValue[i].first;
- vfIncluded[i] = false;
- }
- }
- }
- }
- }
- if (pcoinLowestLarger && nLowestLarger - nTargetValue <= nBest - nTargetValue)
- setCoinsRet.insert(pcoinLowestLarger);
- else
- {
- for (int i = 0; i < vValue.size(); i++)
- if (vfBest[i])
- setCoinsRet.insert(vValue[i].second);
- printf("SelectCoins() best subset: ");
- for (int i = 0; i < vValue.size(); i++)
- if (vfBest[i])
- printf("%s ", FormatMoney(vValue[i].first).c_str());
- printf("total %s\n", FormatMoney(nBest).c_str());
- }
- return true;
- }
- bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, int64& nFeeRequiredRet)
- {
- nFeeRequiredRet = 0;
- CRITICAL_BLOCK(cs_main)
- {
- CTxDB txdb("r");
- CRITICAL_BLOCK(cs_mapWallet)
- {
- int64 nFee = nTransactionFee;
- loop
- {
- wtxNew.vin.clear();
- wtxNew.vout.clear();
- if (nValue < 0)
- return false;
- int64 nValueOut = nValue;
- nValue += nFee;
- set<CWalletTx*> setCoins;
- if (!SelectCoins(nValue, setCoins))
- return false;
- int64 nValueIn = 0;
- foreach(CWalletTx* pcoin, setCoins)
- nValueIn += pcoin->GetCredit();
- wtxNew.vout.push_back(CTxOut(nValueOut, scriptPubKey));
- if (nValueIn > nValue)
- {
- vector<unsigned char> vchPubKey;
- CTransaction& txFirst = *(*setCoins.begin());
- foreach(const CTxOut& txout, txFirst.vout)
- if (txout.IsMine())
- if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey))
- break;
- if (vchPubKey.empty())
- return false;
- CScript scriptPubKey;
- scriptPubKey << vchPubKey << OP_CHECKSIG;
- wtxNew.vout.push_back(CTxOut(nValueIn - nValue, scriptPubKey));
- }
- foreach(CWalletTx* pcoin, setCoins)
- for (int nOut = 0; nOut < pcoin->vout.size(); nOut++)
- if (pcoin->vout[nOut].IsMine())
- wtxNew.vin.push_back(CTxIn(pcoin->GetHash(), nOut));
- int nIn = 0;
- foreach(CWalletTx* pcoin, setCoins)
- for (int nOut = 0; nOut < pcoin->vout.size(); nOut++)
- if (pcoin->vout[nOut].IsMine())
- SignSignature(*pcoin, wtxNew, nIn++);
- if (nFee < wtxNew.GetMinFee(true))
- {
- nFee = nFeeRequiredRet = wtxNew.GetMinFee(true);
- continue;
- }
- wtxNew.AddSupportingTransactions(txdb);
- wtxNew.fTimeReceivedIsTxTime = true;
- break;
- }
- }
- }
- return true;
- }
- bool CommitTransactionSpent(const CWalletTx& wtxNew)
- {
- CRITICAL_BLOCK(cs_main)
- CRITICAL_BLOCK(cs_mapWallet)
- {
- AddToWallet(wtxNew);
- set<CWalletTx*> setCoins;
- foreach(const CTxIn& txin, wtxNew.vin)
- setCoins.insert(&mapWallet[txin.prevout.hash]);
- foreach(CWalletTx* pcoin, setCoins)
- {
- pcoin->fSpent = true;
- pcoin->WriteToDisk();
- vWalletUpdated.push_back(make_pair(pcoin->GetHash(), false));
- }
- }
- MainFrameRepaint();
- return true;
- }
- bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew)
- {
- CRITICAL_BLOCK(cs_main)
- {
- int64 nFeeRequired;
- if (!CreateTransaction(scriptPubKey, nValue, wtxNew, nFeeRequired))
- {
- string strError;
- if (nValue + nFeeRequired > GetBalance())
- strError = strprintf("Error: This is an oversized transaction that requires a transaction fee of %s ", FormatMoney(nFeeRequired).c_str());
- else
- strError = "Error: Transaction creation failed ";
- wxMessageBox(strError, "Sending...");
- return error("SendMoney() : %s\n", strError.c_str());
- }
- if (!CommitTransactionSpent(wtxNew))
- {
- wxMessageBox("Error finalizing transaction", "Sending...");
- return error("SendMoney() : Error finalizing transaction");
- }
- printf("SendMoney: %s\n", wtxNew.GetHash().ToString().substr(0,6).c_str());
- if (!wtxNew.AcceptTransaction())
- {
- throw runtime_error("SendMoney() : wtxNew.AcceptTransaction() failed\n");
- wxMessageBox("Error: Transaction not valid", "Sending...");
- return error("SendMoney() : Error: Transaction not valid");
- }
- wtxNew.RelayWalletTransaction();
- }
- MainFrameRepaint();
- return true;
- }
- class COutPoint;
- class CInPoint;
- class CDiskTxPos;
- class CCoinBase;
- class CTxIn;
- class CTxOut;
- class CTransaction;
- class CBlock;
- class CBlockIndex;
- class CWalletTx;
- class CKeyItem;
- static const unsigned int MAX_SIZE = 0x02000000;
- static const int64 COIN = 100000000;
- static const int64 CENT = 1000000;
- static const int COINBASE_MATURITY = 100;
- static const CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
- extern CCriticalSection cs_main;
- extern map<uint256, CBlockIndex*> mapBlockIndex;
- extern const uint256 hashGenesisBlock;
- extern CBlockIndex* pindexGenesisBlock;
- extern int nBestHeight;
- extern uint256 hashBestChain;
- extern CBlockIndex* pindexBest;
- extern unsigned int nTransactionsUpdated;
- extern string strSetDataDir;
- extern int nDropMessagesTest;
- extern int fGenerateBitcoins;
- extern int64 nTransactionFee;
- extern CAddress addrIncoming;
- string GetAppDir();
- FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb");
- FILE* AppendBlockFile(unsigned int& nFileRet);
- bool AddKey(const CKey& key);
- vector<unsigned char> GenerateNewKey();
- bool AddToWallet(const CWalletTx& wtxIn);
- void ReacceptWalletTransactions();
- void RelayWalletTransactions();
- bool LoadBlockIndex(bool fAllowNew=true);
- void PrintBlockTree();
- bool BitcoinMiner();
- bool ProcessMessages(CNode* pfrom);
- bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv);
- bool SendMessages(CNode* pto);
- int64 GetBalance();
- bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& txNew, int64& nFeeRequiredRet);
- bool CommitTransactionSpent(const CWalletTx& wtxNew);
- bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew);
- class CDiskTxPos
- {
- public:
- unsigned int nFile;
- unsigned int nBlockPos;
- unsigned int nTxPos;
- CDiskTxPos()
- {
- SetNull();
- }
- CDiskTxPos(unsigned int nFileIn, unsigned int nBlockPosIn, unsigned int nTxPosIn)
- {
- nFile = nFileIn;
- nBlockPos = nBlockPosIn;
- nTxPos = nTxPosIn;
- }
- IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); )
- void SetNull() { nFile = -1; nBlockPos = 0; nTxPos = 0; }
- bool IsNull() const { return (nFile == -1); }
- friend bool operator==(const CDiskTxPos& a, const CDiskTxPos& b)
- {
- return (a.nFile == b.nFile &&
- a.nBlockPos == b.nBlockPos &&
- a.nTxPos == b.nTxPos);
- }
- friend bool operator!=(const CDiskTxPos& a, const CDiskTxPos& b)
- {
- return !(a == b);
- }
- string ToString() const
- {
- if (IsNull())
- return strprintf("null");
- else
- return strprintf("(nFile=%d, nBlockPos=%d, nTxPos=%d)", nFile, nBlockPos, nTxPos);
- }
- void print() const
- {
- printf("%s", ToString().c_str());
- }
- };
- class CInPoint
- {
- public:
- CTransaction* ptx;
- unsigned int n;
- CInPoint() { SetNull(); }
- CInPoint(CTransaction* ptxIn, unsigned int nIn) { ptx = ptxIn; n = nIn; }
- void SetNull() { ptx = NULL; n = -1; }
- bool IsNull() const { return (ptx == NULL && n == -1); }
- };
- class COutPoint
- {
- public:
- uint256 hash;
- unsigned int n;
- COutPoint() { SetNull(); }
- COutPoint(uint256 hashIn, unsigned int nIn) { hash = hashIn; n = nIn; }
- IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); )
- void SetNull() { hash = 0; n = -1; }
- bool IsNull() const { return (hash == 0 && n == -1); }
- friend bool operator<(const COutPoint& a, const COutPoint& b)
- {
- return (a.hash < b.hash || (a.hash == b.hash && a.n < b.n));
- }
- friend bool operator==(const COutPoint& a, const COutPoint& b)
- {
- return (a.hash == b.hash && a.n == b.n);
- }
- friend bool operator!=(const COutPoint& a, const COutPoint& b)
- {
- return !(a == b);
- }
- string ToString() const
- {
- return strprintf("COutPoint(%s, %d)", hash.ToString().substr(0,6).c_str(), n);
- }
- void print() const
- {
- printf("%s\n", ToString().c_str());
- }
- };
- class CTxIn
- {
- public:
- COutPoint prevout;
- CScript scriptSig;
- unsigned int nSequence;
- CTxIn()
- {
- nSequence = UINT_MAX;
- }
- explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=UINT_MAX)
- {
- prevout = prevoutIn;
- scriptSig = scriptSigIn;
- nSequence = nSequenceIn;
- }
- CTxIn(uint256 hashPrevTx, unsigned int nOut, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=UINT_MAX)
- {
- prevout = COutPoint(hashPrevTx, nOut);
- scriptSig = scriptSigIn;
- nSequence = nSequenceIn;
- }
- IMPLEMENT_SERIALIZE
- (
- READWRITE(prevout);
- READWRITE(scriptSig);
- READWRITE(nSequence);
- )
- bool IsFinal() const
- {
- return (nSequence == UINT_MAX);
- }
- friend bool operator==(const CTxIn& a, const CTxIn& b)
- {
- return (a.prevout == b.prevout &&
- a.scriptSig == b.scriptSig &&
- a.nSequence == b.nSequence);
- }
- friend bool operator!=(const CTxIn& a, const CTxIn& b)
- {
- return !(a == b);
- }
- string ToString() const
- {
- string str;
- str += strprintf("CTxIn(");
- str += prevout.ToString();
- if (prevout.IsNull())
- str += strprintf(", coinbase %s", HexStr(scriptSig.begin(), scriptSig.end(), false).c_str());
- else
- str += strprintf(", scriptSig=%s", scriptSig.ToString().substr(0,24).c_str());
- if (nSequence != UINT_MAX)
- str += strprintf(", nSequence=%u", nSequence);
- str += ")";
- return str;
- }
- void print() const
- {
- printf("%s\n", ToString().c_str());
- }
- bool IsMine() const;
- int64 GetDebit() const;
- };
- class CTxOut
- {
- public:
- int64 nValue;
- CScript scriptPubKey;
- public:
- CTxOut()
- {
- SetNull();
- }
- CTxOut(int64 nValueIn, CScript scriptPubKeyIn)
- {
- nValue = nValueIn;
- scriptPubKey = scriptPubKeyIn;
- }
- IMPLEMENT_SERIALIZE
- (
- READWRITE(nValue);
- READWRITE(scriptPubKey);
- )
- void SetNull()
- {
- nValue = -1;
- scriptPubKey.clear();
- }
- bool IsNull()
- {
- return (nValue == -1);
- }
- uint256 GetHash() const
- {
- return SerializeHash(*this);
- }
- bool IsMine() const
- {
- return ::IsMine(scriptPubKey);
- }
- int64 GetCredit() const
- {
- if (IsMine())
- return nValue;
- return 0;
- }
- friend bool operator==(const CTxOut& a, const CTxOut& b)
- {
- return (a.nValue == b.nValue &&
- a.scriptPubKey == b.scriptPubKey);
- }
- friend bool operator!=(const CTxOut& a, const CTxOut& b)
- {
- return !(a == b);
- }
- string ToString() const
- {
- if (scriptPubKey.size() < 6)
- return "CTxOut(error)";
- return strprintf("CTxOut(nValue=%I64d.%08I64d, scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,24).c_str());
- }
- void print() const
- {
- printf("%s\n", ToString().c_str());
- }
- };
- class CTransaction
- {
- public:
- int nVersion;
- vector<CTxIn> vin;
- vector<CTxOut> vout;
- int nLockTime;
- CTransaction()
- {
- SetNull();
- }
- IMPLEMENT_SERIALIZE
- (
- READWRITE(this->nVersion);
- nVersion = this->nVersion;
- READWRITE(vin);
- READWRITE(vout);
- READWRITE(nLockTime);
- )
- void SetNull()
- {
- nVersion = 1;
- vin.clear();
- vout.clear();
- nLockTime = 0;
- }
- bool IsNull() const
- {
- return (vin.empty() && vout.empty());
- }
- uint256 GetHash() const
- {
- return SerializeHash(*this);
- }
- bool IsFinal() const
- {
- if (nLockTime == 0 || nLockTime < nBestHeight)
- return true;
- foreach(const CTxIn& txin, vin)
- if (!txin.IsFinal())
- return false;
- return true;
- }
- bool IsNewerThan(const CTransaction& old) const
- {
- if (vin.size() != old.vin.size())
- return false;
- for (int i = 0; i < vin.size(); i++)
- if (vin[i].prevout != old.vin[i].prevout)
- return false;
- bool fNewer = false;
- unsigned int nLowest = UINT_MAX;
- for (int i = 0; i < vin.size(); i++)
- {
- if (vin[i].nSequence != old.vin[i].nSequence)
- {
- if (vin[i].nSequence <= nLowest)
- {
- fNewer = false;
- nLowest = vin[i].nSequence;
- }
- if (old.vin[i].nSequence < nLowest)
- {
- fNewer = true;
- nLowest = old.vin[i].nSequence;
- }
- }
- }
- return fNewer;
- }
- bool IsCoinBase() const
- {
- return (vin.size() == 1 && vin[0].prevout.IsNull());
- }
- bool CheckTransaction() const
- {
- if (vin.empty() || vout.empty())
- return error("CTransaction::CheckTransaction() : vin or vout empty");
- foreach(const CTxOut& txout, vout)
- if (txout.nValue < 0)
- return error("CTransaction::CheckTransaction() : txout.nValue negative");
- if (IsCoinBase())
- {
- if (vin[0].scriptSig.size() < 2 || vin[0].scriptSig.size() > 100)
- return error("CTransaction::CheckTransaction() : coinbase script size");
- }
- else
- {
- foreach(const CTxIn& txin, vin)
- if (txin.prevout.IsNull())
- return error("CTransaction::CheckTransaction() : prevout is null");
- }
- return true;
- }
- bool IsMine() const
- {
- foreach(const CTxOut& txout, vout)
- if (txout.IsMine())
- return true;
- return false;
- }
- int64 GetDebit() const
- {
- int64 nDebit = 0;
- foreach(const CTxIn& txin, vin)
- nDebit += txin.GetDebit();
- return nDebit;
- }
- int64 GetCredit() const
- {
- int64 nCredit = 0;
- foreach(const CTxOut& txout, vout)
- nCredit += txout.GetCredit();
- return nCredit;
- }
- int64 GetValueOut() const
- {
- int64 nValueOut = 0;
- foreach(const CTxOut& txout, vout)
- {
- if (txout.nValue < 0)
- throw runtime_error("CTransaction::GetValueOut() : negative value");
- nValueOut += txout.nValue;
- }
- return nValueOut;
- }
- int64 GetMinFee(bool fDiscount=false) const
- {
- unsigned int nBytes = ::GetSerializeSize(*this, SER_NETWORK);
- if (fDiscount && nBytes < 10000)
- return 0;
- return (1 + (int64)nBytes / 1000) * CENT;
- }
- bool ReadFromDisk(CDiskTxPos pos, FILE** pfileRet=NULL)
- {
- CAutoFile filein = OpenBlockFile(pos.nFile, 0, pfileRet ? "rb+" : "rb");
- if (!filein)
- return error("CTransaction::ReadFromDisk() : OpenBlockFile failed");
- if (fseek(filein, pos.nTxPos, SEEK_SET) != 0)
- return error("CTransaction::ReadFromDisk() : fseek failed");
- filein >> *this;
- if (pfileRet)
- {
- if (fseek(filein, pos.nTxPos, SEEK_SET) != 0)
- return error("CTransaction::ReadFromDisk() : second fseek failed");
- *pfileRet = filein.release();
- }
- return true;
- }
- friend bool operator==(const CTransaction& a, const CTransaction& b)
- {
- return (a.nVersion == b.nVersion &&
- a.vin == b.vin &&
- a.vout == b.vout &&
- a.nLockTime == b.nLockTime);
- }
- friend bool operator!=(const CTransaction& a, const CTransaction& b)
- {
- return !(a == b);
- }
- string ToString() const
- {
- string str;
- str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%d, vout.size=%d, nLockTime=%d)\n",
- GetHash().ToString().substr(0,6).c_str(),
- nVersion,
- vin.size(),
- vout.size(),
- nLockTime);
- for (int i = 0; i < vin.size(); i++)
- str += " " + vin[i].ToString() + "\n";
- for (int i = 0; i < vout.size(); i++)
- str += " " + vout[i].ToString() + "\n";
- return str;
- }
- void print() const
- {
- printf("%s", ToString().c_str());
- }
- bool DisconnectInputs(CTxDB& txdb);
- bool ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPool, CDiskTxPos posThisTx, int nHeight, int64& nFees, bool fBlock, bool fMiner, int64 nMinFee=0);
- bool ClientConnectInputs();
- bool AcceptTransaction(CTxDB& txdb, bool fCheckInputs=true, bool* pfMissingInputs=NULL);
- bool AcceptTransaction(bool fCheckInputs=true, bool* pfMissingInputs=NULL)
- {
- CTxDB txdb("r");
- return AcceptTransaction(txdb, fCheckInputs, pfMissingInputs);
- }
- protected:
- bool AddToMemoryPool();
- public:
- bool RemoveFromMemoryPool();
- };
- class CMerkleTx : public CTransaction
- {
- public:
- uint256 hashBlock;
- vector<uint256> vMerkleBranch;
- int nIndex;
- mutable bool fMerkleVerified;
- CMerkleTx()
- {
- Init();
- }
- CMerkleTx(const CTransaction& txIn) : CTransaction(txIn)
- {
- Init();
- }
- void Init()
- {
- hashBlock = 0;
- nIndex = -1;
- fMerkleVerified = false;
- }
- int64 GetCredit() const
- {
- if (IsCoinBase() && GetBlocksToMaturity() > 0)
- return 0;
- return CTransaction::GetCredit();
- }
- IMPLEMENT_SERIALIZE
- (
- nSerSize += SerReadWrite(s, *(CTransaction*)this, nType, nVersion, ser_action);
- nVersion = this->nVersion;
- READWRITE(hashBlock);
- READWRITE(vMerkleBranch);
- READWRITE(nIndex);
- )
- int SetMerkleBranch(const CBlock* pblock=NULL);
- int GetDepthInMainChain() const;
- bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
- int GetBlocksToMaturity() const;
- bool AcceptTransaction(CTxDB& txdb, bool fCheckInputs=true);
- bool AcceptTransaction() { CTxDB txdb("r"); return AcceptTransaction(txdb); }
- };
- class CWalletTx : public CMerkleTx
- {
- public:
- vector<CMerkleTx> vtxPrev;
- map<string, string> mapValue;
- vector<pair<string, string> > vOrderForm;
- unsigned int fTimeReceivedIsTxTime;
- unsigned int nTimeReceived;
- char fFromMe;
- char fSpent;
- mutable unsigned int nTimeDisplayed;
- CWalletTx()
- {
- Init();
- }
- CWalletTx(const CMerkleTx& txIn) : CMerkleTx(txIn)
- {
- Init();
- }
- CWalletTx(const CTransaction& txIn) : CMerkleTx(txIn)
- {
- Init();
- }
- void Init()
- {
- fTimeReceivedIsTxTime = false;
- nTimeReceived = 0;
- fFromMe = false;
- fSpent = false;
- nTimeDisplayed = 0;
- }
- IMPLEMENT_SERIALIZE
- (
- nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion, ser_action);
- nVersion = this->nVersion;
- READWRITE(vtxPrev);
- READWRITE(mapValue);
- READWRITE(vOrderForm);
- READWRITE(fTimeReceivedIsTxTime);
- READWRITE(nTimeReceived);
- READWRITE(fFromMe);
- READWRITE(fSpent);
- )
- bool WriteToDisk()
- {
- return CWalletDB().WriteTx(GetHash(), *this);
- }
- int64 GetTxTime() const;
- void AddSupportingTransactions(CTxDB& txdb);
- bool AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs=true);
- bool AcceptWalletTransaction() { CTxDB txdb("r"); return AcceptWalletTransaction(txdb); }
- void RelayWalletTransaction(CTxDB& txdb);
- void RelayWalletTransaction() { CTxDB txdb("r"); RelayWalletTransaction(txdb); }
- };
- class CTxIndex
- {
- public:
- CDiskTxPos pos;
- vector<CDiskTxPos> vSpent;
- CTxIndex()
- {
- SetNull();
- }
- CTxIndex(const CDiskTxPos& posIn, unsigned int nOutputs)
- {
- pos = posIn;
- vSpent.resize(nOutputs);
- }
- IMPLEMENT_SERIALIZE
- (
- if (!(nType & SER_GETHASH))
- READWRITE(nVersion);
- READWRITE(pos);
- READWRITE(vSpent);
- )
- void SetNull()
- {
- pos.SetNull();
- vSpent.clear();
- }
- bool IsNull()
- {
- return pos.IsNull();
- }
- friend bool operator==(const CTxIndex& a, const CTxIndex& b)
- {
- if (a.pos != b.pos || a.vSpent.size() != b.vSpent.size())
- return false;
- for (int i = 0; i < a.vSpent.size(); i++)
- if (a.vSpent[i] != b.vSpent[i])
- return false;
- return true;
- }
- friend bool operator!=(const CTxIndex& a, const CTxIndex& b)
- {
- return !(a == b);
- }
- };
- class CBlock
- {
- public:
- int nVersion;
- uint256 hashPrevBlock;
- uint256 hashMerkleRoot;
- unsigned int nTime;
- unsigned int nBits;
- unsigned int nNonce;
- vector<CTransaction> vtx;
- mutable vector<uint256> vMerkleTree;
- CBlock()
- {
- SetNull();
- }
- IMPLEMENT_SERIALIZE
- (
- READWRITE(this->nVersion);
- nVersion = this->nVersion;
- READWRITE(hashPrevBlock);
- READWRITE(hashMerkleRoot);
- READWRITE(nTime);
- READWRITE(nBits);
- READWRITE(nNonce);
- if (!(nType & (SER_GETHASH|SER_BLOCKHEADERONLY)))
- READWRITE(vtx);
- else if (fRead)
- const_cast<CBlock*>(this)->vtx.clear();
- )
- void SetNull()
- {
- nVersion = 1;
- hashPrevBlock = 0;
- hashMerkleRoot = 0;
- nTime = 0;
- nBits = 0;
- nNonce = 0;
- vtx.clear();
- vMerkleTree.clear();
- }
- bool IsNull() const
- {
- return (nBits == 0);
- }
- uint256 GetHash() const
- {
- return Hash(BEGIN(nVersion), END(nNonce));
- }
- uint256 BuildMerkleTree() const
- {
- vMerkleTree.clear();
- foreach(const CTransaction& tx, vtx)
- vMerkleTree.push_back(tx.GetHash());
- int j = 0;
- for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
- {
- for (int i = 0; i < nSize; i += 2)
- {
- int i2 = min(i+1, nSize-1);
- vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]), END(vMerkleTree[j+i]),
- BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
- }
- j += nSize;
- }
- return (vMerkleTree.empty() ? 0 : vMerkleTree.back());
- }
- vector<uint256> GetMerkleBranch(int nIndex) const
- {
- if (vMerkleTree.empty())
- BuildMerkleTree();
- vector<uint256> vMerkleBranch;
- int j = 0;
- for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
- {
- int i = min(nIndex^1, nSize-1);
- vMerkleBranch.push_back(vMerkleTree[j+i]);
- nIndex >>= 1;
- j += nSize;
- }
- return vMerkleBranch;
- }
- static uint256 CheckMerkleBranch(uint256 hash, const vector<uint256>& vMerkleBranch, int nIndex)
- {
- if (nIndex == -1)
- return 0;
- foreach(const uint256& otherside, vMerkleBranch)
- {
- if (nIndex & 1)
- hash = Hash(BEGIN(otherside), END(otherside), BEGIN(hash), END(hash));
- else
- hash = Hash(BEGIN(hash), END(hash), BEGIN(otherside), END(otherside));
- nIndex >>= 1;
- }
- return hash;
- }
- bool WriteToDisk(bool fWriteTransactions, unsigned int& nFileRet, unsigned int& nBlockPosRet)
- {
- CAutoFile fileout = AppendBlockFile(nFileRet);
- if (!fileout)
- return error("CBlock::WriteToDisk() : AppendBlockFile failed");
- if (!fWriteTransactions)
- fileout.nType |= SER_BLOCKHEADERONLY;
- unsigned int nSize = fileout.GetSerializeSize(*this);
- fileout << FLATDATA(pchMessageStart) << nSize;
- nBlockPosRet = ftell(fileout);
- if (nBlockPosRet == -1)
- return error("CBlock::WriteToDisk() : ftell failed");
- fileout << *this;
- return true;
- }
- bool ReadFromDisk(unsigned int nFile, unsigned int nBlockPos, bool fReadTransactions)
- {
- SetNull();
- CAutoFile filein = OpenBlockFile(nFile, nBlockPos, "rb");
- if (!filein)
- return error("CBlock::ReadFromDisk() : OpenBlockFile failed");
- if (!fReadTransactions)
- filein.nType |= SER_BLOCKHEADERONLY;
- filein >> *this;
- if (CBigNum().SetCompact(nBits) > bnProofOfWorkLimit)
- return error("CBlock::ReadFromDisk() : nBits errors in block header");
- if (GetHash() > CBigNum().SetCompact(nBits).getuint256())
- return error("CBlock::ReadFromDisk() : GetHash() errors in block header");
- return true;
- }
- void print() const
- {
- printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%d)\n",
- GetHash().ToString().substr(0,14).c_str(),
- nVersion,
- hashPrevBlock.ToString().substr(0,14).c_str(),
- hashMerkleRoot.ToString().substr(0,6).c_str(),
- nTime, nBits, nNonce,
- vtx.size());
- for (int i = 0; i < vtx.size(); i++)
- {
- printf(" ");
- vtx[i].print();
- }
- printf(" vMerkleTree: ");
- for (int i = 0; i < vMerkleTree.size(); i++)
- printf("%s ", vMerkleTree[i].ToString().substr(0,6).c_str());
- printf("\n");
- }
- int64 GetBlockValue(int64 nFees) const;
- bool DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex);
- bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex);
- bool ReadFromDisk(const CBlockIndex* blockindex, bool fReadTransactions);
- bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos);
- bool CheckBlock() const;
- bool AcceptBlock();
- };
- class CBlockIndex
- {
- public:
- const uint256* phashBlock;
- CBlockIndex* pprev;
- CBlockIndex* pnext;
- unsigned int nFile;
- unsigned int nBlockPos;
- int nHeight;
- int nVersion;
- uint256 hashMerkleRoot;
- unsigned int nTime;
- unsigned int nBits;
- unsigned int nNonce;
- CBlockIndex()
- {
- phashBlock = NULL;
- pprev = NULL;
- pnext = NULL;
- nFile = 0;
- nBlockPos = 0;
- nHeight = 0;
- nVersion = 0;
- hashMerkleRoot = 0;
- nTime = 0;
- nBits = 0;
- nNonce = 0;
- }
- CBlockIndex(unsigned int nFileIn, unsigned int nBlockPosIn, CBlock& block)
- {
- phashBlock = NULL;
- pprev = NULL;
- pnext = NULL;
- nFile = nFileIn;
- nBlockPos = nBlockPosIn;
- nHeight = 0;
- nVersion = block.nVersion;
- hashMerkleRoot = block.hashMerkleRoot;
- nTime = block.nTime;
- nBits = block.nBits;
- nNonce = block.nNonce;
- }
- uint256 GetBlockHash() const
- {
- return *phashBlock;
- }
- bool IsInMainChain() const
- {
- return (pnext || this == pindexBest);
- }
- bool EraseBlockFromDisk()
- {
- CAutoFile fileout = OpenBlockFile(nFile, nBlockPos, "rb+");
- if (!fileout)
- return false;
- CBlock block;
- block.SetNull();
- fileout << block;
- return true;
- }
- enum { nMedianTimeSpan=11 };
- int64 GetMedianTimePast() const
- {
- unsigned int pmedian[nMedianTimeSpan];
- unsigned int* pbegin = &pmedian[nMedianTimeSpan];
- unsigned int* pend = &pmedian[nMedianTimeSpan];
- const CBlockIndex* pindex = this;
- for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
- *(--pbegin) = pindex->nTime;
- sort(pbegin, pend);
- return pbegin[(pend - pbegin)/2];
- }
- int64 GetMedianTime() const
- {
- const CBlockIndex* pindex = this;
- for (int i = 0; i < nMedianTimeSpan/2; i++)
- {
- if (!pindex->pnext)
- return nTime;
- pindex = pindex->pnext;
- }
- return pindex->GetMedianTimePast();
- }
- string ToString() const
- {
- return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nHeight=%d, merkle=%s, hashBlock=%s)",
- pprev, pnext, nFile, nBlockPos, nHeight,
- hashMerkleRoot.ToString().substr(0,6).c_str(),
- GetBlockHash().ToString().substr(0,14).c_str());
- }
- void print() const
- {
- printf("%s\n", ToString().c_str());
- }
- };
- class CDiskBlockIndex : public CBlockIndex
- {
- public:
- uint256 hashPrev;
- uint256 hashNext;
- CDiskBlockIndex()
- {
- hashPrev = 0;
- hashNext = 0;
- }
- explicit CDiskBlockIndex(CBlockIndex* pindex) : CBlockIndex(*pindex)
- {
- hashPrev = (pprev ? pprev->GetBlockHash() : 0);
- hashNext = (pnext ? pnext->GetBlockHash() : 0);
- }
- IMPLEMENT_SERIALIZE
- (
- if (!(nType & SER_GETHASH))
- READWRITE(nVersion);
- READWRITE(hashNext);
- READWRITE(nFile);
- READWRITE(nBlockPos);
- READWRITE(nHeight);
- READWRITE(this->nVersion);
- READWRITE(hashPrev);
- READWRITE(hashMerkleRoot);
- READWRITE(nTime);
- READWRITE(nBits);
- READWRITE(nNonce);
- )
- uint256 GetBlockHash() const
- {
- CBlock block;
- block.nVersion = nVersion;
- block.hashPrevBlock = hashPrev;
- block.hashMerkleRoot = hashMerkleRoot;
- block.nTime = nTime;
- block.nBits = nBits;
- block.nNonce = nNonce;
- return block.GetHash();
- }
- string ToString() const
- {
- string str = "CDiskBlockIndex(";
- str += CBlockIndex::ToString();
- str += strprintf("\n hashBlock=%s, hashPrev=%s, hashNext=%s)",
- GetBlockHash().ToString().c_str(),
- hashPrev.ToString().substr(0,14).c_str(),
- hashNext.ToString().substr(0,14).c_str());
- return str;
- }
- void print() const
- {
- printf("%s\n", ToString().c_str());
- }
- };
- class CBlockLocator
- {
- protected:
- vector<uint256> vHave;
- public:
- CBlockLocator()
- {
- }
- explicit CBlockLocator(const CBlockIndex* pindex)
- {
- Set(pindex);
- }
- explicit CBlockLocator(uint256 hashBlock)
- {
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
- if (mi != mapBlockIndex.end())
- Set((*mi).second);
- }
- IMPLEMENT_SERIALIZE
- (
- if (!(nType & SER_GETHASH))
- READWRITE(nVersion);
- READWRITE(vHave);
- )
- void Set(const CBlockIndex* pindex)
- {
- vHave.clear();
- int nStep = 1;
- while (pindex)
- {
- vHave.push_back(pindex->GetBlockHash());
- for (int i = 0; pindex && i < nStep; i++)
- pindex = pindex->pprev;
- if (vHave.size() > 10)
- nStep *= 2;
- }
- vHave.push_back(hashGenesisBlock);
- }
- CBlockIndex* GetBlockIndex()
- {
- foreach(const uint256& hash, vHave)
- {
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
- if (mi != mapBlockIndex.end())
- {
- CBlockIndex* pindex = (*mi).second;
- if (pindex->IsInMainChain())
- return pindex;
- }
- }
- return pindexGenesisBlock;
- }
- uint256 GetBlockHash()
- {
- foreach(const uint256& hash, vHave)
- {
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
- if (mi != mapBlockIndex.end())
- {
- CBlockIndex* pindex = (*mi).second;
- if (pindex->IsInMainChain())
- return hash;
- }
- }
- return hashGenesisBlock;
- }
- int GetHeight()
- {
- CBlockIndex* pindex = GetBlockIndex();
- if (!pindex)
- return 0;
- return pindex->nHeight;
- }
- };
- extern map<uint256, CTransaction> mapTransactions;
- extern map<uint256, CWalletTx> mapWallet;
- extern vector<pair<uint256, bool> > vWalletUpdated;
- extern CCriticalSection cs_mapWallet;
- extern map<vector<unsigned char>, CPrivKey> mapKeys;
- extern map<uint160, vector<unsigned char> > mapPubKeys;
- extern CCriticalSection cs_mapKeys;
- extern CKey keyUser;
- #include "headers.h"
- map<uint256, CProduct> mapMyProducts;
- map<uint256, CProduct> mapProducts;
- CCriticalSection cs_mapProducts;
- bool AdvertInsert(const CProduct& product)
- {
- uint256 hash = product.GetHash();
- bool fNew = false;
- bool fUpdated = false;
- CRITICAL_BLOCK(cs_mapProducts)
- {
- pair<map<uint256, CProduct>::iterator, bool> item = mapProducts.insert(make_pair(hash, product));
- CProduct* pproduct = &(*(item.first)).second;
- fNew = item.second;
- if (product.nSequence > pproduct->nSequence)
- {
- *pproduct = product;
- fUpdated = true;
- }
- }
- return (fNew || fUpdated);
- }
- void AdvertErase(const CProduct& product)
- {
- uint256 hash = product.GetHash();
- CRITICAL_BLOCK(cs_mapProducts)
- mapProducts.erase(hash);
- }
- template<typename T>
- unsigned int Union(T& v1, T& v2)
- {
- T vUnion;
- vUnion.reserve(v1.size() + v2.size());
- set_union(v1.begin(), v1.end(),
- v2.begin(), v2.end(),
- back_inserter(vUnion));
- unsigned int nAdded = vUnion.size() - v1.size();
- if (nAdded > 0)
- v1 = vUnion;
- return nAdded;
- }
- void CUser::AddAtom(unsigned short nAtom, bool fOrigin)
- {
- if (binary_search(vAtomsIn.begin(), vAtomsIn.end(), nAtom) ||
- find(vAtomsNew.begin(), vAtomsNew.end(), nAtom) != vAtomsNew.end())
- return;
- if (nAtom == 0 || fOrigin)
- {
- vector<unsigned short> vTmp(1, nAtom);
- Union(vAtomsIn, vTmp);
- if (fOrigin)
- vAtomsOut.push_back(nAtom);
- return;
- }
- vAtomsNew.push_back(nAtom);
- if (vAtomsNew.size() >= nFlowthroughRate || vAtomsOut.empty())
- {
- vAtomsOut.push_back(vAtomsNew[GetRand(vAtomsNew.size())]);
- sort(vAtomsNew.begin(), vAtomsNew.end());
- Union(vAtomsIn, vAtomsNew);
- vAtomsNew.clear();
- }
- }
- bool AddAtomsAndPropagate(uint256 hashUserStart, const vector<unsigned short>& vAtoms, bool fOrigin)
- {
- CReviewDB reviewdb;
- map<uint256, vector<unsigned short> > pmapPropagate[2];
- pmapPropagate[0][hashUserStart] = vAtoms;
- for (int side = 0; !pmapPropagate[side].empty(); side = 1 - side)
- {
- map<uint256, vector<unsigned short> >& mapFrom = pmapPropagate[side];
- map<uint256, vector<unsigned short> >& mapTo = pmapPropagate[1 - side];
- for (map<uint256, vector<unsigned short> >::iterator mi = mapFrom.begin(); mi != mapFrom.end(); ++mi)
- {
- const uint256& hashUser = (*mi).first;
- const vector<unsigned short>& vReceived = (*mi).second;
- CUser user;
- reviewdb.ReadUser(hashUser, user);
- unsigned int nIn = user.vAtomsIn.size();
- unsigned int nNew = user.vAtomsNew.size();
- unsigned int nOut = user.vAtomsOut.size();
- foreach(unsigned short nAtom, vReceived)
- user.AddAtom(nAtom, fOrigin);
- fOrigin = false;
- if (user.vAtomsIn.size() == nIn && user.vAtomsNew.size() == nNew)
- continue;
- if (user.vAtomsOut.size() > nOut)
- foreach(const uint256& hash, user.vLinksOut)
- mapTo[hash].insert(mapTo[hash].end(), user.vAtomsOut.begin() + nOut, user.vAtomsOut.end());
- if (!reviewdb.WriteUser(hashUser, user))
- return false;
- }
- mapFrom.clear();
- }
- return true;
- }
- bool CReview::AcceptReview()
- {
- nTime = GetTime();
- if (!CKey::Verify(vchPubKeyFrom, GetSigHash(), vchSig))
- return false;
- CReviewDB reviewdb;
- vector<CReview> vReviews;
- reviewdb.ReadReviews(hashTo, vReviews);
- vReviews.push_back(*this);
- if (!reviewdb.WriteReviews(hashTo, vReviews))
- return false;
- CUser user;
- uint256 hashFrom = Hash(vchPubKeyFrom.begin(), vchPubKeyFrom.end());
- reviewdb.ReadUser(hashFrom, user);
- user.vLinksOut.push_back(hashTo);
- if (!reviewdb.WriteUser(hashFrom, user))
- return false;
- reviewdb.Close();
- vector<unsigned short> vZeroAtom(1, 0);
- if (!AddAtomsAndPropagate(hashTo, user.vAtomsOut.size() ? user.vAtomsOut : vZeroAtom, false))
- return false;
- return true;
- }
- bool CProduct::CheckSignature()
- {
- return (CKey::Verify(vchPubKeyFrom, GetSigHash(), vchSig));
- }
- bool CProduct::CheckProduct()
- {
- if (!CheckSignature())
- return false;
- if (!mapDetails.empty() || !vOrderForm.empty())
- return false;
- CReviewDB reviewdb("r");
- CUser user;
- reviewdb.ReadUser(GetUserHash(), user);
- nAtoms = user.GetAtomCount();
- reviewdb.Close();
- return true;
- }
- class CUser;
- class CReview;
- class CProduct;
- static const unsigned int nFlowthroughRate = 2;
- bool AdvertInsert(const CProduct& product);
- void AdvertErase(const CProduct& product);
- bool AddAtomsAndPropagate(uint256 hashUserStart, const vector<unsigned short>& vAtoms, bool fOrigin);
- class CUser
- {
- public:
- vector<unsigned short> vAtomsIn;
- vector<unsigned short> vAtomsNew;
- vector<unsigned short> vAtomsOut;
- vector<uint256> vLinksOut;
- CUser()
- {
- }
- IMPLEMENT_SERIALIZE
- (
- if (!(nType & SER_GETHASH))
- READWRITE(nVersion);
- READWRITE(vAtomsIn);
- READWRITE(vAtomsNew);
- READWRITE(vAtomsOut);
- READWRITE(vLinksOut);
- )
- void SetNull()
- {
- vAtomsIn.clear();
- vAtomsNew.clear();
- vAtomsOut.clear();
- vLinksOut.clear();
- }
- uint256 GetHash() const { return SerializeHash(*this); }
- int GetAtomCount() const
- {
- return (vAtomsIn.size() + vAtomsNew.size());
- }
- void AddAtom(unsigned short nAtom, bool fOrigin);
- };
- class CReview
- {
- public:
- int nVersion;
- uint256 hashTo;
- map<string, string> mapValue;
- vector<unsigned char> vchPubKeyFrom;
- vector<unsigned char> vchSig;
- unsigned int nTime;
- int nAtoms;
- CReview()
- {
- nVersion = 1;
- hashTo = 0;
- nTime = 0;
- nAtoms = 0;
- }
- IMPLEMENT_SERIALIZE
- (
- READWRITE(this->nVersion);
- nVersion = this->nVersion;
- if (!(nType & SER_DISK))
- READWRITE(hashTo);
- READWRITE(mapValue);
- READWRITE(vchPubKeyFrom);
- if (!(nType & SER_GETHASH))
- READWRITE(vchSig);
- )
- uint256 GetHash() const { return SerializeHash(*this); }
- uint256 GetSigHash() const { return SerializeHash(*this, SER_GETHASH|SER_SKIPSIG); }
- uint256 GetUserHash() const { return Hash(vchPubKeyFrom.begin(), vchPubKeyFrom.end()); }
- bool AcceptReview();
- };
- class CProduct
- {
- public:
- int nVersion;
- CAddress addr;
- map<string, string> mapValue;
- map<string, string> mapDetails;
- vector<pair<string, string> > vOrderForm;
- unsigned int nSequence;
- vector<unsigned char> vchPubKeyFrom;
- vector<unsigned char> vchSig;
- int nAtoms;
- set<unsigned int> setSources;
- CProduct()
- {
- nVersion = 1;
- nAtoms = 0;
- nSequence = 0;
- }
- IMPLEMENT_SERIALIZE
- (
- READWRITE(this->nVersion);
- nVersion = this->nVersion;
- READWRITE(addr);
- READWRITE(mapValue);
- if (!(nType & SER_GETHASH))
- {
- READWRITE(mapDetails);
- READWRITE(vOrderForm);
- READWRITE(nSequence);
- }
- READWRITE(vchPubKeyFrom);
- if (!(nType & SER_GETHASH))
- READWRITE(vchSig);
- if (nType & SER_DISK)
- READWRITE(nAtoms);
- )
- uint256 GetHash() const { return SerializeHash(*this); }
- uint256 GetSigHash() const { return SerializeHash(*this, SER_GETHASH|SER_SKIPSIG); }
- uint256 GetUserHash() const { return Hash(vchPubKeyFrom.begin(), vchPubKeyFrom.end()); }
- bool CheckSignature();
- bool CheckProduct();
- };
- extern map<uint256, CProduct> mapProducts;
- extern CCriticalSection cs_mapProducts;
- extern map<uint256, CProduct> mapMyProducts;
- #include "headers.h"
- #include <winsock2.h>
- void ThreadMessageHandler2(void* parg);
- void ThreadSocketHandler2(void* parg);
- void ThreadOpenConnections2(void* parg);
- bool fClient = false;
- uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
- CAddress addrLocalHost(0, DEFAULT_PORT, nLocalServices);
- CNode nodeLocalHost(INVALID_SOCKET, CAddress("127.0.0.1", nLocalServices));
- CNode* pnodeLocalHost = &nodeLocalHost;
- bool fShutdown = false;
- array<bool, 10> vfThreadRunning;
- vector<CNode*> vNodes;
- CCriticalSection cs_vNodes;
- map<vector<unsigned char>, CAddress> mapAddresses;
- CCriticalSection cs_mapAddresses;
- map<CInv, CDataStream> mapRelay;
- deque<pair<int64, CInv> > vRelayExpiration;
- CCriticalSection cs_mapRelay;
- map<CInv, int64> mapAlreadyAskedFor;
- CAddress addrProxy;
- bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
- {
- hSocketRet = INVALID_SOCKET;
- SOCKET hSocket = socket(AF_INET, SOCK_STREAM, 0);
- if (hSocket == INVALID_SOCKET)
- return false;
- bool fRoutable = !(addrConnect.GetByte(3) == 10 || (addrConnect.GetByte(3) == 192 && addrConnect.GetByte(2) == 168));
- bool fProxy = (addrProxy.ip && fRoutable);
- struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr());
- if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
- {
- closesocket(hSocket);
- return false;
- }
- if (fProxy)
- {
- printf("Proxy connecting to %s\n", addrConnect.ToString().c_str());
- char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
- memcpy(pszSocks4IP + 2, &addrConnect.port, 2);
- memcpy(pszSocks4IP + 4, &addrConnect.ip, 4);
- char* pszSocks4 = pszSocks4IP;
- int nSize = sizeof(pszSocks4IP);
- int ret = send(hSocket, pszSocks4, nSize, 0);
- if (ret != nSize)
- {
- closesocket(hSocket);
- return error("Error sending to proxy\n");
- }
- char pchRet[8];
- if (recv(hSocket, pchRet, 8, 0) != 8)
- {
- closesocket(hSocket);
- return error("Error reading proxy response\n");
- }
- if (pchRet[1] != 0x5a)
- {
- closesocket(hSocket);
- return error("Proxy returned error %d\n", pchRet[1]);
- }
- printf("Proxy connection established %s\n", addrConnect.ToString().c_str());
- }
- hSocketRet = hSocket;
- return true;
- }
- bool GetMyExternalIP(unsigned int& ipRet)
- {
- CAddress addrConnect("72.233.89.199:80");
- SOCKET hSocket;
- if (!ConnectSocket(addrConnect, hSocket))
- return error("GetMyExternalIP() : connection to %s failed\n", addrConnect.ToString().c_str());
- char* pszGet =
- "GET /automation/n09230945.asp HTTP/1.1\r\n"
- "Host: www.whatismyip.com\r\n"
- "User-Agent: Bitcoin/0.1\r\n"
- "Connection: close\r\n"
- "\r\n";
- send(hSocket, pszGet, strlen(pszGet), 0);
- string strLine;
- while (RecvLine(hSocket, strLine))
- {
- if (strLine.empty())
- {
- if (!RecvLine(hSocket, strLine))
- {
- closesocket(hSocket);
- return false;
- }
- closesocket(hSocket);
- CAddress addr(strLine.c_str());
- printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str());
- if (addr.ip == 0)
- return false;
- ipRet = addr.ip;
- return true;
- }
- }
- closesocket(hSocket);
- return error("GetMyExternalIP() : connection closed\n");
- }
- bool AddAddress(CAddrDB& addrdb, const CAddress& addr)
- {
- if (!addr.IsRoutable())
- return false;
- if (addr.ip == addrLocalHost.ip)
- return false;
- CRITICAL_BLOCK(cs_mapAddresses)
- {
- map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
- if (it == mapAddresses.end())
- {
- mapAddresses.insert(make_pair(addr.GetKey(), addr));
- addrdb.WriteAddress(addr);
- return true;
- }
- else
- {
- CAddress& addrFound = (*it).second;
- if ((addrFound.nServices | addr.nServices) != addrFound.nServices)
- {
- addrFound.nServices |= addr.nServices;
- addrdb.WriteAddress(addrFound);
- return true;
- }
- }
- }
- return false;
- }
- void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1)
- {
- CRITICAL_BLOCK(cs_vNodes)
- {
- foreach(CNode* pnode, vNodes)
- {
- CRITICAL_BLOCK(pnode->cs_mapRequests)
- {
- for (map<uint256, CRequestTracker>::iterator mi = pnode->mapRequests.begin(); mi != pnode->mapRequests.end();)
- {
- CRequestTracker& tracker = (*mi).second;
- if (tracker.fn == fn && tracker.param1 == param1)
- pnode->mapRequests.erase(mi++);
- else
- mi++;
- }
- }
- }
- }
- }
- bool AnySubscribed(unsigned int nChannel)
- {
- if (pnodeLocalHost->IsSubscribed(nChannel))
- return true;
- CRITICAL_BLOCK(cs_vNodes)
- foreach(CNode* pnode, vNodes)
- if (pnode->IsSubscribed(nChannel))
- return true;
- return false;
- }
- bool CNode::IsSubscribed(unsigned int nChannel)
- {
- if (nChannel >= vfSubscribe.size())
- return false;
- return vfSubscribe[nChannel];
- }
- void CNode::Subscribe(unsigned int nChannel, unsigned int nHops)
- {
- if (nChannel >= vfSubscribe.size())
- return;
- if (!AnySubscribed(nChannel))
- {
- CRITICAL_BLOCK(cs_vNodes)
- foreach(CNode* pnode, vNodes)
- if (pnode != this)
- pnode->PushMessage("subscribe", nChannel, nHops);
- }
- vfSubscribe[nChannel] = true;
- }
- void CNode::CancelSubscribe(unsigned int nChannel)
- {
- if (nChannel >= vfSubscribe.size())
- return;
- if (!vfSubscribe[nChannel])
- return;
- vfSubscribe[nChannel] = false;
- if (!AnySubscribed(nChannel))
- {
- CRITICAL_BLOCK(cs_vNodes)
- foreach(CNode* pnode, vNodes)
- if (pnode != this)
- pnode->PushMessage("sub-cancel", nChannel);
- if (nChannel == MSG_PRODUCT)
- CRITICAL_BLOCK(cs_mapProducts)
- mapProducts.clear();
- }
- }
- CNode* FindNode(unsigned int ip)
- {
- CRITICAL_BLOCK(cs_vNodes)
- {
- foreach(CNode* pnode, vNodes)
- if (pnode->addr.ip == ip)
- return (pnode);
- }
- return NULL;
- }
- CNode* FindNode(CAddress addr)
- {
- CRITICAL_BLOCK(cs_vNodes)
- {
- foreach(CNode* pnode, vNodes)
- if (pnode->addr == addr)
- return (pnode);
- }
- return NULL;
- }
- CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
- {
- if (addrConnect.ip == addrLocalHost.ip)
- return NULL;
- CNode* pnode = FindNode(addrConnect.ip);
- if (pnode)
- {
- if (nTimeout != 0)
- pnode->AddRef(nTimeout);
- else
- pnode->AddRef();
- return pnode;
- }
- printf("trying %s\n", addrConnect.ToString().c_str());
- SOCKET hSocket;
- if (ConnectSocket(addrConnect, hSocket))
- {
- printf("connected %s\n", addrConnect.ToString().c_str());
- CNode* pnode = new CNode(hSocket, addrConnect, false);
- if (nTimeout != 0)
- pnode->AddRef(nTimeout);
- else
- pnode->AddRef();
- CRITICAL_BLOCK(cs_vNodes)
- vNodes.push_back(pnode);
- CRITICAL_BLOCK(cs_mapAddresses)
- mapAddresses[addrConnect.GetKey()].nLastFailed = 0;
- return pnode;
- }
- else
- {
- CRITICAL_BLOCK(cs_mapAddresses)
- mapAddresses[addrConnect.GetKey()].nLastFailed = GetTime();
- return NULL;
- }
- }
- void CNode::Disconnect()
- {
- printf("disconnecting node %s\n", addr.ToString().c_str());
- closesocket(hSocket);
- CRITICAL_BLOCK(cs_mapProducts)
- for (map<uint256, CProduct>::iterator mi = mapProducts.begin(); mi != mapProducts.end();)
- AdvertRemoveSource(this, MSG_PRODUCT, 0, (*(mi++)).second);
- for (unsigned int nChannel = 0; nChannel < vfSubscribe.size(); nChannel++)
- if (vfSubscribe[nChannel])
- CancelSubscribe(nChannel);
- }
- void ThreadSocketHandler(void* parg)
- {
- IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
- loop
- {
- vfThreadRunning[0] = true;
- CheckForShutdown(0);
- try
- {
- ThreadSocketHandler2(parg);
- }
- CATCH_PRINT_EXCEPTION("ThreadSocketHandler()")
- vfThreadRunning[0] = false;
- Sleep(5000);
- }
- }
- void ThreadSocketHandler2(void* parg)
- {
- printf("ThreadSocketHandler started\n");
- SOCKET hListenSocket = *(SOCKET*)parg;
- list<CNode*> vNodesDisconnected;
- int nPrevNodeCount = 0;
- loop
- {
- CRITICAL_BLOCK(cs_vNodes)
- {
- map<unsigned int, CNode*> mapFirst;
- foreach(CNode* pnode, vNodes)
- {
- if (pnode->fDisconnect)
- continue;
- unsigned int ip = pnode->addr.ip;
- if (mapFirst.count(ip) && addrLocalHost.ip < ip)
- {
- CNode* pnodeExtra = mapFirst[ip];
- if (pnodeExtra->GetRefCount() > (pnodeExtra->fNetworkNode ? 1 : 0))
- swap(pnodeExtra, pnode);
- if (pnodeExtra->GetRefCount() <= (pnodeExtra->fNetworkNode ? 1 : 0))
- {
- printf("(%d nodes) disconnecting duplicate: %s\n", vNodes.size(), pnodeExtra->addr.ToString().c_str());
- if (pnodeExtra->fNetworkNode && !pnode->fNetworkNode)
- {
- pnode->AddRef();
- swap(pnodeExtra->fNetworkNode, pnode->fNetworkNode);
- pnodeExtra->Release();
- }
- pnodeExtra->fDisconnect = true;
- }
- }
- mapFirst[ip] = pnode;
- }
- vector<CNode*> vNodesCopy = vNodes;
- foreach(CNode* pnode, vNodesCopy)
- {
- if (pnode->ReadyToDisconnect() && pnode->vRecv.empty() && pnode->vSend.empty())
- {
- vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
- pnode->Disconnect();
- pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 5 * 60);
- if (pnode->fNetworkNode)
- pnode->Release();
- vNodesDisconnected.push_back(pnode);
- }
- }
- list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
- foreach(CNode* pnode, vNodesDisconnectedCopy)
- {
- if (pnode->GetRefCount() <= 0)
- {
- bool fDelete = false;
- TRY_CRITICAL_BLOCK(pnode->cs_vSend)
- TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
- TRY_CRITICAL_BLOCK(pnode->cs_mapRequests)
- TRY_CRITICAL_BLOCK(pnode->cs_inventory)
- fDelete = true;
- if (fDelete)
- {
- vNodesDisconnected.remove(pnode);
- delete pnode;
- }
- }
- }
- }
- if (vNodes.size() != nPrevNodeCount)
- {
- nPrevNodeCount = vNodes.size();
- MainFrameRepaint();
- }
- struct timeval timeout;
- timeout.tv_sec = 0;
- timeout.tv_usec = 50000;
- struct fd_set fdsetRecv;
- struct fd_set fdsetSend;
- FD_ZERO(&fdsetRecv);
- FD_ZERO(&fdsetSend);
- SOCKET hSocketMax = 0;
- FD_SET(hListenSocket, &fdsetRecv);
- hSocketMax = max(hSocketMax, hListenSocket);
- CRITICAL_BLOCK(cs_vNodes)
- {
- foreach(CNode* pnode, vNodes)
- {
- FD_SET(pnode->hSocket, &fdsetRecv);
- hSocketMax = max(hSocketMax, pnode->hSocket);
- TRY_CRITICAL_BLOCK(pnode->cs_vSend)
- if (!pnode->vSend.empty())
- FD_SET(pnode->hSocket, &fdsetSend);
- }
- }
- vfThreadRunning[0] = false;
- int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, NULL, &timeout);
- vfThreadRunning[0] = true;
- CheckForShutdown(0);
- if (nSelect == SOCKET_ERROR)
- {
- int nErr = WSAGetLastError();
- printf("select failed: %d\n", nErr);
- for (int i = 0; i <= hSocketMax; i++)
- {
- FD_SET(i, &fdsetRecv);
- FD_SET(i, &fdsetSend);
- }
- Sleep(timeout.tv_usec/1000);
- }
- RandAddSeed();
- if (FD_ISSET(hListenSocket, &fdsetRecv))
- {
- struct sockaddr_in sockaddr;
- int len = sizeof(sockaddr);
- SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
- CAddress addr(sockaddr);
- if (hSocket == INVALID_SOCKET)
- {
- if (WSAGetLastError() != WSAEWOULDBLOCK)
- printf("ERROR ThreadSocketHandler accept failed: %d\n", WSAGetLastError());
- }
- else
- {
- printf("accepted connection from %s\n", addr.ToString().c_str());
- CNode* pnode = new CNode(hSocket, addr, true);
- pnode->AddRef();
- CRITICAL_BLOCK(cs_vNodes)
- vNodes.push_back(pnode);
- }
- }
- vector<CNode*> vNodesCopy;
- CRITICAL_BLOCK(cs_vNodes)
- vNodesCopy = vNodes;
- foreach(CNode* pnode, vNodesCopy)
- {
- CheckForShutdown(0);
- SOCKET hSocket = pnode->hSocket;
- if (FD_ISSET(hSocket, &fdsetRecv))
- {
- TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
- {
- CDataStream& vRecv = pnode->vRecv;
- unsigned int nPos = vRecv.size();
- const unsigned int nBufSize = 0x10000;
- vRecv.resize(nPos + nBufSize);
- int nBytes = recv(hSocket, &vRecv[nPos], nBufSize, 0);
- vRecv.resize(nPos + max(nBytes, 0));
- if (nBytes == 0)
- {
- if (!pnode->fDisconnect)
- printf("recv: socket closed\n");
- pnode->fDisconnect = true;
- }
- else if (nBytes < 0)
- {
- int nErr = WSAGetLastError();
- if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
- {
- if (!pnode->fDisconnect)
- printf("recv failed: %d\n", nErr);
- pnode->fDisconnect = true;
- }
- }
- }
- }
- if (FD_ISSET(hSocket, &fdsetSend))
- {
- TRY_CRITICAL_BLOCK(pnode->cs_vSend)
- {
- CDataStream& vSend = pnode->vSend;
- if (!vSend.empty())
- {
- int nBytes = send(hSocket, &vSend[0], vSend.size(), 0);
- if (nBytes > 0)
- {
- vSend.erase(vSend.begin(), vSend.begin() + nBytes);
- }
- else if (nBytes == 0)
- {
- if (pnode->ReadyToDisconnect())
- pnode->vSend.clear();
- }
- else
- {
- printf("send error %d\n", nBytes);
- if (pnode->ReadyToDisconnect())
- pnode->vSend.clear();
- }
- }
- }
- }
- }
- Sleep(10);
- }
- }
- void ThreadOpenConnections(void* parg)
- {
- IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
- loop
- {
- vfThreadRunning[1] = true;
- CheckForShutdown(1);
- try
- {
- ThreadOpenConnections2(parg);
- }
- CATCH_PRINT_EXCEPTION("ThreadOpenConnections()")
- vfThreadRunning[1] = false;
- Sleep(5000);
- }
- }
- void ThreadOpenConnections2(void* parg)
- {
- printf("ThreadOpenConnections started\n");
- const int nMaxConnections = 15;
- loop
- {
- vfThreadRunning[1] = false;
- Sleep(500);
- while (vNodes.size() >= nMaxConnections || vNodes.size() >= mapAddresses.size())
- {
- CheckForShutdown(1);
- Sleep(2000);
- }
- vfThreadRunning[1] = true;
- CheckForShutdown(1);
- unsigned char pchIPCMask[4] = { 0xff, 0xff, 0xff, 0x00 };
- unsigned int nIPCMask = *(unsigned int*)pchIPCMask;
- vector<unsigned int> vIPC;
- CRITICAL_BLOCK(cs_mapAddresses)
- {
- vIPC.reserve(mapAddresses.size());
- unsigned int nPrev = 0;
- foreach(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
- {
- const CAddress& addr = item.second;
- if (!addr.IsIPv4())
- continue;
- unsigned int ipC = addr.ip & nIPCMask;
- if (ipC != nPrev)
- vIPC.push_back(nPrev = ipC);
- }
- }
- bool fSuccess = false;
- int nLimit = vIPC.size();
- while (!fSuccess && nLimit-- > 0)
- {
- unsigned int ipC = vIPC[GetRand(vIPC.size())];
- map<unsigned int, vector<CAddress> > mapIP;
- CRITICAL_BLOCK(cs_mapAddresses)
- {
- unsigned int nDelay = ((30 * 60) << vNodes.size());
- if (nDelay > 8 * 60 * 60)
- nDelay = 8 * 60 * 60;
- for (map<vector<unsigned char>, CAddress>::iterator mi = mapAddresses.lower_bound(CAddress(ipC, 0).GetKey());
- mi != mapAddresses.upper_bound(CAddress(ipC | ~nIPCMask, 0xffff).GetKey());
- ++mi)
- {
- const CAddress& addr = (*mi).second;
- unsigned int nRandomizer = (addr.nLastFailed * addr.ip * 7777U) % 20000;
- if (GetTime() - addr.nLastFailed > nDelay * nRandomizer / 10000)
- mapIP[addr.ip].push_back(addr);
- }
- }
- if (mapIP.empty())
- break;
- map<unsigned int, vector<CAddress> >::iterator mi = mapIP.begin();
- advance(mi, GetRand(mapIP.size()));
- foreach(const CAddress& addrConnect, (*mi).second)
- {
- if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() || FindNode(addrConnect.ip))
- continue;
- CNode* pnode = ConnectNode(addrConnect);
- if (!pnode)
- continue;
- pnode->fNetworkNode = true;
- if (addrLocalHost.IsRoutable())
- {
- vector<CAddress> vAddrToSend;
- vAddrToSend.push_back(addrLocalHost);
- pnode->PushMessage("addr", vAddrToSend);
- }
- pnode->PushMessage("getaddr");
- const unsigned int nHops = 0;
- for (unsigned int nChannel = 0; nChannel < pnodeLocalHost->vfSubscribe.size(); nChannel++)
- if (pnodeLocalHost->vfSubscribe[nChannel])
- pnode->PushMessage("subscribe", nChannel, nHops);
- fSuccess = true;
- break;
- }
- }
- }
- }
- void ThreadMessageHandler(void* parg)
- {
- IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
- loop
- {
- vfThreadRunning[2] = true;
- CheckForShutdown(2);
- try
- {
- ThreadMessageHandler2(parg);
- }
- CATCH_PRINT_EXCEPTION("ThreadMessageHandler()")
- vfThreadRunning[2] = false;
- Sleep(5000);
- }
- }
- void ThreadMessageHandler2(void* parg)
- {
- printf("ThreadMessageHandler started\n");
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);
- loop
- {
- vector<CNode*> vNodesCopy;
- CRITICAL_BLOCK(cs_vNodes)
- vNodesCopy = vNodes;
- foreach(CNode* pnode, vNodesCopy)
- {
- pnode->AddRef();
- TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
- ProcessMessages(pnode);
- TRY_CRITICAL_BLOCK(pnode->cs_vSend)
- SendMessages(pnode);
- pnode->Release();
- }
- vfThreadRunning[2] = false;
- Sleep(100);
- vfThreadRunning[2] = true;
- CheckForShutdown(2);
- }
- }
- void ThreadBitcoinMiner(void* parg)
- {
- vfThreadRunning[3] = true;
- CheckForShutdown(3);
- try
- {
- bool fRet = BitcoinMiner();
- printf("BitcoinMiner returned %s\n\n\n", fRet ? "true" : "false");
- }
- CATCH_PRINT_EXCEPTION("BitcoinMiner()")
- vfThreadRunning[3] = false;
- }
- bool StartNode(string& strError)
- {
- strError = "";
- WSADATA wsadata;
- int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
- if (ret != NO_ERROR)
- {
- strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
- printf("%s\n", strError.c_str());
- return false;
- }
- char pszHostName[255];
- if (gethostname(pszHostName, 255) == SOCKET_ERROR)
- {
- strError = strprintf("Error: Unable to get IP address of this computer (gethostname returned error %d)", WSAGetLastError());
- printf("%s\n", strError.c_str());
- return false;
- }
- struct hostent* pHostEnt = gethostbyname(pszHostName);
- if (!pHostEnt)
- {
- strError = strprintf("Error: Unable to get IP address of this computer (gethostbyname returned error %d)", WSAGetLastError());
- printf("%s\n", strError.c_str());
- return false;
- }
- addrLocalHost = CAddress(*(long*)(pHostEnt->h_addr_list[0]),
- DEFAULT_PORT,
- nLocalServices);
- printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
- SOCKET hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (hListenSocket == INVALID_SOCKET)
- {
- strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
- printf("%s\n", strError.c_str());
- return false;
- }
- u_long nOne = 1;
- if (ioctlsocket(hListenSocket, FIONBIO, &nOne) == SOCKET_ERROR)
- {
- strError = strprintf("Error: Couldn't set properties on socket for incoming connections (ioctlsocket returned error %d)", WSAGetLastError());
- printf("%s\n", strError.c_str());
- return false;
- }
- int nRetryLimit = 15;
- struct sockaddr_in sockaddr = addrLocalHost.GetSockAddr();
- if (bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
- {
- int nErr = WSAGetLastError();
- if (nErr == WSAEADDRINUSE)
- strError = strprintf("Error: Unable to bind to port %s on this computer. The program is probably already running.", addrLocalHost.ToString().c_str());
- else
- strError = strprintf("Error: Unable to bind to port %s on this computer (bind returned error %d)", addrLocalHost.ToString().c_str(), nErr);
- printf("%s\n", strError.c_str());
- return false;
- }
- printf("bound to addrLocalHost = %s\n\n", addrLocalHost.ToString().c_str());
- if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
- {
- strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
- printf("%s\n", strError.c_str());
- return false;
- }
- if (addrIncoming.ip)
- addrLocalHost.ip = addrIncoming.ip;
- if (GetMyExternalIP(addrLocalHost.ip))
- {
- addrIncoming = addrLocalHost;
- CWalletDB().WriteSetting("addrIncoming", addrIncoming);
- }
- if (_beginthread(ThreadIRCSeed, 0, NULL) == -1)
- printf("Error: _beginthread(ThreadIRCSeed) failed\n");
- if (_beginthread(ThreadSocketHandler, 0, new SOCKET(hListenSocket)) == -1)
- {
- strError = "Error: _beginthread(ThreadSocketHandler) failed";
- printf("%s\n", strError.c_str());
- return false;
- }
- if (_beginthread(ThreadOpenConnections, 0, NULL) == -1)
- {
- strError = "Error: _beginthread(ThreadOpenConnections) failed";
- printf("%s\n", strError.c_str());
- return false;
- }
- if (_beginthread(ThreadMessageHandler, 0, NULL) == -1)
- {
- strError = "Error: _beginthread(ThreadMessageHandler) failed";
- printf("%s\n", strError.c_str());
- return false;
- }
- return true;
- }
- bool StopNode()
- {
- printf("StopNode()\n");
- fShutdown = true;
- nTransactionsUpdated++;
- while (count(vfThreadRunning.begin(), vfThreadRunning.end(), true))
- Sleep(10);
- Sleep(50);
- WSACleanup();
- return true;
- }
- void CheckForShutdown(int n)
- {
- if (fShutdown)
- {
- if (n != -1)
- vfThreadRunning[n] = false;
- _endthread();
- }
- }
- class CMessageHeader;
- class CAddress;
- class CInv;
- class CRequestTracker;
- class CNode;
- static const unsigned short DEFAULT_PORT = htons(8333);
- static const unsigned int PUBLISH_HOPS = 5;
- enum
- {
- NODE_NETWORK = (1 << 0),
- };
- bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet);
- bool GetMyExternalIP(unsigned int& ipRet);
- bool AddAddress(CAddrDB& addrdb, const CAddress& addr);
- CNode* FindNode(unsigned int ip);
- CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0);
- void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1);
- bool AnySubscribed(unsigned int nChannel);
- void ThreadBitcoinMiner(void* parg);
- bool StartNode(string& strError=REF(string()));
- bool StopNode();
- void CheckForShutdown(int n);
- static const char pchMessageStart[4] = { 0xf9, 0xbe, 0xb4, 0xd9 };
- class CMessageHeader
- {
- public:
- enum { COMMAND_SIZE=12 };
- char pchMessageStart[sizeof(::pchMessageStart)];
- char pchCommand[COMMAND_SIZE];
- unsigned int nMessageSize;
- CMessageHeader()
- {
- memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart));
- memset(pchCommand, 0, sizeof(pchCommand));
- pchCommand[1] = 1;
- nMessageSize = -1;
- }
- CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn)
- {
- memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart));
- strncpy(pchCommand, pszCommand, COMMAND_SIZE);
- nMessageSize = nMessageSizeIn;
- }
- IMPLEMENT_SERIALIZE
- (
- READWRITE(FLATDATA(pchMessageStart));
- READWRITE(FLATDATA(pchCommand));
- READWRITE(nMessageSize);
- )
- string GetCommand()
- {
- if (pchCommand[COMMAND_SIZE-1] == 0)
- return string(pchCommand, pchCommand + strlen(pchCommand));
- else
- return string(pchCommand, pchCommand + COMMAND_SIZE);
- }
- bool IsValid()
- {
- if (memcmp(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart)) != 0)
- return false;
- for (char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; p1++)
- {
- if (*p1 == 0)
- {
- for (; p1 < pchCommand + COMMAND_SIZE; p1++)
- if (*p1 != 0)
- return false;
- }
- else if (*p1 < ' ' || *p1 > 0x7E)
- return false;
- }
- if (nMessageSize > 0x10000000)
- {
- printf("CMessageHeader::IsValid() : nMessageSize too large %u\n", nMessageSize);
- return false;
- }
- return true;
- }
- };
- static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
- class CAddress
- {
- public:
- uint64 nServices;
- unsigned char pchReserved[12];
- unsigned int ip;
- unsigned short port;
- unsigned int nTime;
- unsigned int nLastFailed;
- CAddress()
- {
- nServices = 0;
- memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
- ip = 0;
- port = DEFAULT_PORT;
- nTime = GetAdjustedTime();
- nLastFailed = 0;
- }
- CAddress(unsigned int ipIn, unsigned short portIn, uint64 nServicesIn=0)
- {
- nServices = nServicesIn;
- memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
- ip = ipIn;
- port = portIn;
- nTime = GetAdjustedTime();
- nLastFailed = 0;
- }
- explicit CAddress(const struct sockaddr_in& sockaddr, uint64 nServicesIn=0)
- {
- nServices = nServicesIn;
- memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
- ip = sockaddr.sin_addr.s_addr;
- port = sockaddr.sin_port;
- nTime = GetAdjustedTime();
- nLastFailed = 0;
- }
- explicit CAddress(const char* pszIn, uint64 nServicesIn=0)
- {
- nServices = nServicesIn;
- memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
- ip = 0;
- port = DEFAULT_PORT;
- nTime = GetAdjustedTime();
- nLastFailed = 0;
- char psz[100];
- if (strlen(pszIn) > ARRAYLEN(psz)-1)
- return;
- strcpy(psz, pszIn);
- unsigned int a, b, c, d, e;
- if (sscanf(psz, "%u.%u.%u.%u:%u", &a, &b, &c, &d, &e) < 4)
- return;
- char* pszPort = strchr(psz, ':');
- if (pszPort)
- {
- *pszPort++ = '\0';
- port = htons(atoi(pszPort));
- }
- ip = inet_addr(psz);
- }
- IMPLEMENT_SERIALIZE
- (
- if (nType & SER_DISK)
- {
- READWRITE(nVersion);
- READWRITE(nTime);
- }
- READWRITE(nServices);
- READWRITE(FLATDATA(pchReserved));
- READWRITE(ip);
- READWRITE(port);
- )
- friend inline bool operator==(const CAddress& a, const CAddress& b)
- {
- return (memcmp(a.pchReserved, b.pchReserved, sizeof(a.pchReserved)) == 0 &&
- a.ip == b.ip &&
- a.port == b.port);
- }
- friend inline bool operator<(const CAddress& a, const CAddress& b)
- {
- int ret = memcmp(a.pchReserved, b.pchReserved, sizeof(a.pchReserved));
- if (ret < 0)
- return true;
- else if (ret == 0)
- {
- if (ntohl(a.ip) < ntohl(b.ip))
- return true;
- else if (a.ip == b.ip)
- return ntohs(a.port) < ntohs(b.port);
- }
- return false;
- }
- vector<unsigned char> GetKey() const
- {
- CDataStream ss;
- ss.reserve(18);
- ss << FLATDATA(pchReserved) << ip << port;
- #if defined(_MSC_VER) && _MSC_VER < 1300
- return vector<unsigned char>((unsigned char*)&ss.begin()[0], (unsigned char*)&ss.end()[0]);
- #else
- return vector<unsigned char>(ss.begin(), ss.end());
- #endif
- }
- struct sockaddr_in GetSockAddr() const
- {
- struct sockaddr_in sockaddr;
- sockaddr.sin_family = AF_INET;
- sockaddr.sin_addr.s_addr = ip;
- sockaddr.sin_port = port;
- return sockaddr;
- }
- bool IsIPv4() const
- {
- return (memcmp(pchReserved, pchIPv4, sizeof(pchIPv4)) == 0);
- }
- bool IsRoutable() const
- {
- return !(GetByte(3) == 10 || (GetByte(3) == 192 && GetByte(2) == 168));
- }
- unsigned char GetByte(int n) const
- {
- return ((unsigned char*)&ip)[3-n];
- }
- string ToStringIPPort() const
- {
- return strprintf("%u.%u.%u.%u:%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0), ntohs(port));
- }
- string ToStringIP() const
- {
- return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
- }
- string ToString() const
- {
- return strprintf("%u.%u.%u.%u:%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0), ntohs(port));
- }
- void print() const
- {
- printf("CAddress(%s)\n", ToString().c_str());
- }
- };
- enum
- {
- MSG_TX = 1,
- MSG_BLOCK,
- MSG_REVIEW,
- MSG_PRODUCT,
- MSG_TABLE,
- };
- static const char* ppszTypeName[] =
- {
- "ERROR",
- "tx",
- "block",
- "review",
- "product",
- "table",
- };
- class CInv
- {
- public:
- int type;
- uint256 hash;
- CInv()
- {
- type = 0;
- hash = 0;
- }
- CInv(int typeIn, const uint256& hashIn)
- {
- type = typeIn;
- hash = hashIn;
- }
- CInv(const string& strType, const uint256& hashIn)
- {
- int i;
- for (i = 1; i < ARRAYLEN(ppszTypeName); i++)
- {
- if (strType == ppszTypeName[i])
- {
- type = i;
- break;
- }
- }
- if (i == ARRAYLEN(ppszTypeName))
- throw std::out_of_range(strprintf("CInv::CInv(string, uint256) : unknown type '%s'", strType.c_str()));
- hash = hashIn;
- }
- IMPLEMENT_SERIALIZE
- (
- READWRITE(type);
- READWRITE(hash);
- )
- friend inline bool operator<(const CInv& a, const CInv& b)
- {
- return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
- }
- bool IsKnownType() const
- {
- return (type >= 1 && type < ARRAYLEN(ppszTypeName));
- }
- const char* GetCommand() const
- {
- if (!IsKnownType())
- throw std::out_of_range(strprintf("CInv::GetCommand() : type=% unknown type", type));
- return ppszTypeName[type];
- }
- string ToString() const
- {
- return strprintf("%s %s", GetCommand(), hash.ToString().substr(0,14).c_str());
- }
- void print() const
- {
- printf("CInv(%s)\n", ToString().c_str());
- }
- };
- class CRequestTracker
- {
- public:
- void (*fn)(void*, CDataStream&);
- void* param1;
- explicit CRequestTracker(void (*fnIn)(void*, CDataStream&)=NULL, void* param1In=NULL)
- {
- fn = fnIn;
- param1 = param1In;
- }
- bool IsNull()
- {
- return fn == NULL;
- }
- };
- extern bool fClient;
- extern uint64 nLocalServices;
- extern CAddress addrLocalHost;
- extern CNode* pnodeLocalHost;
- extern bool fShutdown;
- extern array<bool, 10> vfThreadRunning;
- extern vector<CNode*> vNodes;
- extern CCriticalSection cs_vNodes;
- extern map<vector<unsigned char>, CAddress> mapAddresses;
- extern CCriticalSection cs_mapAddresses;
- extern map<CInv, CDataStream> mapRelay;
- extern deque<pair<int64, CInv> > vRelayExpiration;
- extern CCriticalSection cs_mapRelay;
- extern map<CInv, int64> mapAlreadyAskedFor;
- extern CAddress addrProxy;
- class CNode
- {
- public:
- uint64 nServices;
- SOCKET hSocket;
- CDataStream vSend;
- CDataStream vRecv;
- CCriticalSection cs_vSend;
- CCriticalSection cs_vRecv;
- unsigned int nPushPos;
- CAddress addr;
- int nVersion;
- bool fClient;
- bool fInbound;
- bool fNetworkNode;
- bool fDisconnect;
- protected:
- int nRefCount;
- public:
- int64 nReleaseTime;
- map<uint256, CRequestTracker> mapRequests;
- CCriticalSection cs_mapRequests;
- vector<CAddress> vAddrToSend;
- set<CAddress> setAddrKnown;
- set<CInv> setInventoryKnown;
- set<CInv> setInventoryKnown2;
- vector<CInv> vInventoryToSend;
- CCriticalSection cs_inventory;
- multimap<int64, CInv> mapAskFor;
- vector<char> vfSubscribe;
- CNode(SOCKET hSocketIn, CAddress addrIn, bool fInboundIn=false)
- {
- nServices = 0;
- hSocket = hSocketIn;
- vSend.SetType(SER_NETWORK);
- vRecv.SetType(SER_NETWORK);
- nPushPos = -1;
- addr = addrIn;
- nVersion = 0;
- fClient = false;
- fInbound = fInboundIn;
- fNetworkNode = false;
- fDisconnect = false;
- nRefCount = 0;
- nReleaseTime = 0;
- vfSubscribe.assign(256, false);
- int64 nTime = (fInbound ? GetAdjustedTime() : GetTime());
- PushMessage("version", VERSION, nLocalServices, nTime, addr);
- }
- ~CNode()
- {
- if (hSocket != INVALID_SOCKET)
- closesocket(hSocket);
- }
- private:
- CNode(const CNode&);
- void operator=(const CNode&);
- public:
- bool ReadyToDisconnect()
- {
- return fDisconnect || GetRefCount() <= 0;
- }
- int GetRefCount()
- {
- return max(nRefCount, 0) + (GetTime() < nReleaseTime ? 1 : 0);
- }
- void AddRef(int64 nTimeout=0)
- {
- if (nTimeout != 0)
- nReleaseTime = max(nReleaseTime, GetTime() + nTimeout);
- else
- nRefCount++;
- }
- void Release()
- {
- nRefCount--;
- }
- void AddInventoryKnown(const CInv& inv)
- {
- CRITICAL_BLOCK(cs_inventory)
- setInventoryKnown.insert(inv);
- }
- void PushInventory(const CInv& inv)
- {
- CRITICAL_BLOCK(cs_inventory)
- if (!setInventoryKnown.count(inv))
- vInventoryToSend.push_back(inv);
- }
- void AskFor(const CInv& inv)
- {
- int64& nRequestTime = mapAlreadyAskedFor[inv];
- printf("askfor %s %I64d\n", inv.ToString().c_str(), nRequestTime);
- int64 nNow = (GetTime() - 1) * 1000000;
- static int64 nLastTime;
- nLastTime = nNow = max(nNow, ++nLastTime);
- nRequestTime = max(nRequestTime + 2 * 60 * 1000000, nNow);
- mapAskFor.insert(make_pair(nRequestTime, inv));
- }
- void BeginMessage(const char* pszCommand)
- {
- EnterCriticalSection(&cs_vSend);
- if (nPushPos != -1)
- AbortMessage();
- nPushPos = vSend.size();
- vSend << CMessageHeader(pszCommand, 0);
- printf("sending: %-12s ", pszCommand);
- }
- void AbortMessage()
- {
- if (nPushPos == -1)
- return;
- vSend.resize(nPushPos);
- nPushPos = -1;
- LeaveCriticalSection(&cs_vSend);
- printf("(aborted)\n");
- }
- void EndMessage()
- {
- extern int nDropMessagesTest;
- if (nDropMessagesTest > 0 && GetRand(nDropMessagesTest) == 0)
- {
- printf("dropmessages DROPPING SEND MESSAGE\n");
- AbortMessage();
- return;
- }
- if (nPushPos == -1)
- return;
- unsigned int nSize = vSend.size() - nPushPos - sizeof(CMessageHeader);
- memcpy((char*)&vSend[nPushPos] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize));
- printf("(%d bytes) ", nSize);
- printf("\n");
- nPushPos = -1;
- LeaveCriticalSection(&cs_vSend);
- }
- void EndMessageAbortIfEmpty()
- {
- if (nPushPos == -1)
- return;
- int nSize = vSend.size() - nPushPos - sizeof(CMessageHeader);
- if (nSize > 0)
- EndMessage();
- else
- AbortMessage();
- }
- const char* GetMessageCommand() const
- {
- if (nPushPos == -1)
- return "";
- return &vSend[nPushPos] + offsetof(CMessageHeader, pchCommand);
- }
- void PushMessage(const char* pszCommand)
- {
- try
- {
- BeginMessage(pszCommand);
- EndMessage();
- }
- catch (...)
- {
- AbortMessage();
- throw;
- }
- }
- template<typename T1>
- void PushMessage(const char* pszCommand, const T1& a1)
- {
- try
- {
- BeginMessage(pszCommand);
- vSend << a1;
- EndMessage();
- }
- catch (...)
- {
- AbortMessage();
- throw;
- }
- }
- template<typename T1, typename T2>
- void PushMessage(const char* pszCommand, const T1& a1, const T2& a2)
- {
- try
- {
- BeginMessage(pszCommand);
- vSend << a1 << a2;
- EndMessage();
- }
- catch (...)
- {
- AbortMessage();
- throw;
- }
- }
- template<typename T1, typename T2, typename T3>
- void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3)
- {
- try
- {
- BeginMessage(pszCommand);
- vSend << a1 << a2 << a3;
- EndMessage();
- }
- catch (...)
- {
- AbortMessage();
- throw;
- }
- }
- template<typename T1, typename T2, typename T3, typename T4>
- void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4)
- {
- try
- {
- BeginMessage(pszCommand);
- vSend << a1 << a2 << a3 << a4;
- EndMessage();
- }
- catch (...)
- {
- AbortMessage();
- throw;
- }
- }
- void PushRequest(const char* pszCommand,
- void (*fn)(void*, CDataStream&), void* param1)
- {
- uint256 hashReply;
- RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
- CRITICAL_BLOCK(cs_mapRequests)
- mapRequests[hashReply] = CRequestTracker(fn, param1);
- PushMessage(pszCommand, hashReply);
- }
- template<typename T1>
- void PushRequest(const char* pszCommand, const T1& a1,
- void (*fn)(void*, CDataStream&), void* param1)
- {
- uint256 hashReply;
- RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
- CRITICAL_BLOCK(cs_mapRequests)
- mapRequests[hashReply] = CRequestTracker(fn, param1);
- PushMessage(pszCommand, hashReply, a1);
- }
- template<typename T1, typename T2>
- void PushRequest(const char* pszCommand, const T1& a1, const T2& a2,
- void (*fn)(void*, CDataStream&), void* param1)
- {
- uint256 hashReply;
- RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
- CRITICAL_BLOCK(cs_mapRequests)
- mapRequests[hashReply] = CRequestTracker(fn, param1);
- PushMessage(pszCommand, hashReply, a1, a2);
- }
- bool IsSubscribed(unsigned int nChannel);
- void Subscribe(unsigned int nChannel, unsigned int nHops=0);
- void CancelSubscribe(unsigned int nChannel);
- void Disconnect();
- };
- inline void RelayInventory(const CInv& inv)
- {
- CRITICAL_BLOCK(cs_vNodes)
- foreach(CNode* pnode, vNodes)
- pnode->PushInventory(inv);
- }
- template<typename T>
- void RelayMessage(const CInv& inv, const T& a)
- {
- CDataStream ss(SER_NETWORK);
- ss.reserve(10000);
- ss << a;
- RelayMessage(inv, ss);
- }
- template<>
- inline void RelayMessage<>(const CInv& inv, const CDataStream& ss)
- {
- CRITICAL_BLOCK(cs_mapRelay)
- {
- while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
- {
- mapRelay.erase(vRelayExpiration.front().second);
- vRelayExpiration.pop_front();
- }
- mapRelay[inv] = ss;
- vRelayExpiration.push_back(make_pair(GetTime() + 15 * 60, inv));
- }
- RelayInventory(inv);
- }
- template<typename T>
- void AdvertStartPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
- {
- obj.setSources.insert(pfrom->addr.ip);
- if (!AdvertInsert(obj))
- return;
- CRITICAL_BLOCK(cs_vNodes)
- foreach(CNode* pnode, vNodes)
- if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel)))
- pnode->PushMessage("publish", nChannel, nHops, obj);
- }
- template<typename T>
- void AdvertStopPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
- {
- uint256 hash = obj.GetHash();
- CRITICAL_BLOCK(cs_vNodes)
- foreach(CNode* pnode, vNodes)
- if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel)))
- pnode->PushMessage("pub-cancel", nChannel, nHops, hash);
- AdvertErase(obj);
- }
- template<typename T>
- void AdvertRemoveSource(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
- {
- obj.setSources.erase(pfrom->addr.ip);
- if (obj.setSources.empty())
- AdvertStopPublish(pfrom, nChannel, nHops, obj);
- }
- #include "headers.h"
- bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
- typedef vector<unsigned char> valtype;
- static const valtype vchFalse(0);
- static const valtype vchZero(0);
- static const valtype vchTrue(1, 1);
- static const CBigNum bnZero(0);
- static const CBigNum bnOne(1);
- static const CBigNum bnFalse(0);
- static const CBigNum bnTrue(1);
- bool CastToBool(const valtype& vch)
- {
- return (CBigNum(vch) != bnZero);
- }
- void MakeSameSize(valtype& vch1, valtype& vch2)
- {
- if (vch1.size() < vch2.size())
- vch1.resize(vch2.size(), 0);
- if (vch2.size() < vch1.size())
- vch2.resize(vch1.size(), 0);
- }
- #define stacktop(i) (stack.at(stack.size()+(i)))
- #define altstacktop(i) (altstack.at(altstack.size()+(i)))
- bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType,
- vector<vector<unsigned char> >* pvStackRet)
- {
- CAutoBN_CTX pctx;
- CScript::const_iterator pc = script.begin();
- CScript::const_iterator pend = script.end();
- CScript::const_iterator pbegincodehash = script.begin();
- vector<bool> vfExec;
- vector<valtype> stack;
- vector<valtype> altstack;
- if (pvStackRet)
- pvStackRet->clear();
- while (pc < pend)
- {
- bool fExec = !count(vfExec.begin(), vfExec.end(), false);
- opcodetype opcode;
- valtype vchPushValue;
- if (!script.GetOp(pc, opcode, vchPushValue))
- return false;
- if (fExec && opcode <= OP_PUSHDATA4)
- stack.push_back(vchPushValue);
- else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF))
- switch (opcode)
- {
- case OP_1NEGATE:
- case OP_1:
- case OP_2:
- case OP_3:
- case OP_4:
- case OP_5:
- case OP_6:
- case OP_7:
- case OP_8:
- case OP_9:
- case OP_10:
- case OP_11:
- case OP_12:
- case OP_13:
- case OP_14:
- case OP_15:
- case OP_16:
- {
- CBigNum bn((int)opcode - (int)(OP_1 - 1));
- stack.push_back(bn.getvch());
- }
- break;
- case OP_NOP:
- break;
- case OP_VER:
- {
- CBigNum bn(VERSION);
- stack.push_back(bn.getvch());
- }
- break;
- case OP_IF:
- case OP_NOTIF:
- case OP_VERIF:
- case OP_VERNOTIF:
- {
- bool fValue = false;
- if (fExec)
- {
- if (stack.size() < 1)
- return false;
- valtype& vch = stacktop(-1);
- if (opcode == OP_VERIF || opcode == OP_VERNOTIF)
- fValue = (CBigNum(VERSION) >= CBigNum(vch));
- else
- fValue = CastToBool(vch);
- if (opcode == OP_NOTIF || opcode == OP_VERNOTIF)
- fValue = !fValue;
- stack.pop_back();
- }
- vfExec.push_back(fValue);
- }
- break;
- case OP_ELSE:
- {
- if (vfExec.empty())
- return false;
- vfExec.back() = !vfExec.back();
- }
- break;
- case OP_ENDIF:
- {
- if (vfExec.empty())
- return false;
- vfExec.pop_back();
- }
- break;
- case OP_VERIFY:
- {
- if (stack.size() < 1)
- return false;
- bool fValue = CastToBool(stacktop(-1));
- if (fValue)
- stack.pop_back();
- else
- pc = pend;
- }
- break;
- case OP_RETURN:
- {
- pc = pend;
- }
- break;
- case OP_TOALTSTACK:
- {
- if (stack.size() < 1)
- return false;
- altstack.push_back(stacktop(-1));
- stack.pop_back();
- }
- break;
- case OP_FROMALTSTACK:
- {
- if (altstack.size() < 1)
- return false;
- stack.push_back(altstacktop(-1));
- altstack.pop_back();
- }
- break;
- case OP_2DROP:
- {
- stack.pop_back();
- stack.pop_back();
- }
- break;
- case OP_2DUP:
- {
- if (stack.size() < 2)
- return false;
- valtype vch1 = stacktop(-2);
- valtype vch2 = stacktop(-1);
- stack.push_back(vch1);
- stack.push_back(vch2);
- }
- break;
- case OP_3DUP:
- {
- if (stack.size() < 3)
- return false;
- valtype vch1 = stacktop(-3);
- valtype vch2 = stacktop(-2);
- valtype vch3 = stacktop(-1);
- stack.push_back(vch1);
- stack.push_back(vch2);
- stack.push_back(vch3);
- }
- break;
- case OP_2OVER:
- {
- if (stack.size() < 4)
- return false;
- valtype vch1 = stacktop(-4);
- valtype vch2 = stacktop(-3);
- stack.push_back(vch1);
- stack.push_back(vch2);
- }
- break;
- case OP_2ROT:
- {
- if (stack.size() < 6)
- return false;
- valtype vch1 = stacktop(-6);
- valtype vch2 = stacktop(-5);
- stack.erase(stack.end()-6, stack.end()-4);
- stack.push_back(vch1);
- stack.push_back(vch2);
- }
- break;
- case OP_2SWAP:
- {
- if (stack.size() < 4)
- return false;
- swap(stacktop(-4), stacktop(-2));
- swap(stacktop(-3), stacktop(-1));
- }
- break;
- case OP_IFDUP:
- {
- if (stack.size() < 1)
- return false;
- valtype vch = stacktop(-1);
- if (CastToBool(vch))
- stack.push_back(vch);
- }
- break;
- case OP_DEPTH:
- {
- CBigNum bn(stack.size());
- stack.push_back(bn.getvch());
- }
- break;
- case OP_DROP:
- {
- if (stack.size() < 1)
- return false;
- stack.pop_back();
- }
- break;
- case OP_DUP:
- {
- if (stack.size() < 1)
- return false;
- valtype vch = stacktop(-1);
- stack.push_back(vch);
- }
- break;
- case OP_NIP:
- {
- if (stack.size() < 2)
- return false;
- stack.erase(stack.end() - 2);
- }
- break;
- case OP_OVER:
- {
- if (stack.size() < 2)
- return false;
- valtype vch = stacktop(-2);
- stack.push_back(vch);
- }
- break;
- case OP_PICK:
- case OP_ROLL:
- {
- if (stack.size() < 2)
- return false;
- int n = CBigNum(stacktop(-1)).getint();
- stack.pop_back();
- if (n < 0 || n >= stack.size())
- return false;
- valtype vch = stacktop(-n-1);
- if (opcode == OP_ROLL)
- stack.erase(stack.end()-n-1);
- stack.push_back(vch);
- }
- break;
- case OP_ROT:
- {
- if (stack.size() < 3)
- return false;
- swap(stacktop(-3), stacktop(-2));
- swap(stacktop(-2), stacktop(-1));
- }
- break;
- case OP_SWAP:
- {
- if (stack.size() < 2)
- return false;
- swap(stacktop(-2), stacktop(-1));
- }
- break;
- case OP_TUCK:
- {
- if (stack.size() < 2)
- return false;
- valtype vch = stacktop(-1);
- stack.insert(stack.end()-2, vch);
- }
- break;
- case OP_CAT:
- {
- if (stack.size() < 2)
- return false;
- valtype& vch1 = stacktop(-2);
- valtype& vch2 = stacktop(-1);
- vch1.insert(vch1.end(), vch2.begin(), vch2.end());
- stack.pop_back();
- }
- break;
- case OP_SUBSTR:
- {
- if (stack.size() < 3)
- return false;
- valtype& vch = stacktop(-3);
- int nBegin = CBigNum(stacktop(-2)).getint();
- int nEnd = nBegin + CBigNum(stacktop(-1)).getint();
- if (nBegin < 0 || nEnd < nBegin)
- return false;
- if (nBegin > vch.size())
- nBegin = vch.size();
- if (nEnd > vch.size())
- nEnd = vch.size();
- vch.erase(vch.begin() + nEnd, vch.end());
- vch.erase(vch.begin(), vch.begin() + nBegin);
- stack.pop_back();
- stack.pop_back();
- }
- break;
- case OP_LEFT:
- case OP_RIGHT:
- {
- if (stack.size() < 2)
- return false;
- valtype& vch = stacktop(-2);
- int nSize = CBigNum(stacktop(-1)).getint();
- if (nSize < 0)
- return false;
- if (nSize > vch.size())
- nSize = vch.size();
- if (opcode == OP_LEFT)
- vch.erase(vch.begin() + nSize, vch.end());
- else
- vch.erase(vch.begin(), vch.end() - nSize);
- stack.pop_back();
- }
- break;
- case OP_SIZE:
- {
- if (stack.size() < 1)
- return false;
- CBigNum bn(stacktop(-1).size());
- stack.push_back(bn.getvch());
- }
- break;
- case OP_INVERT:
- {
- if (stack.size() < 1)
- return false;
- valtype& vch = stacktop(-1);
- for (int i = 0; i < vch.size(); i++)
- vch[i] = ~vch[i];
- }
- break;
- case OP_AND:
- case OP_OR:
- case OP_XOR:
- {
- if (stack.size() < 2)
- return false;
- valtype& vch1 = stacktop(-2);
- valtype& vch2 = stacktop(-1);
- MakeSameSize(vch1, vch2);
- if (opcode == OP_AND)
- {
- for (int i = 0; i < vch1.size(); i++)
- vch1[i] &= vch2[i];
- }
- else if (opcode == OP_OR)
- {
- for (int i = 0; i < vch1.size(); i++)
- vch1[i] |= vch2[i];
- }
- else if (opcode == OP_XOR)
- {
- for (int i = 0; i < vch1.size(); i++)
- vch1[i] ^= vch2[i];
- }
- stack.pop_back();
- }
- break;
- case OP_EQUAL:
- case OP_EQUALVERIFY:
- {
- if (stack.size() < 2)
- return false;
- valtype& vch1 = stacktop(-2);
- valtype& vch2 = stacktop(-1);
- bool fEqual = (vch1 == vch2);
- stack.pop_back();
- stack.pop_back();
- stack.push_back(fEqual ? vchTrue : vchFalse);
- if (opcode == OP_EQUALVERIFY)
- {
- if (fEqual)
- stack.pop_back();
- else
- pc = pend;
- }
- }
- break;
- case OP_1ADD:
- case OP_1SUB:
- case OP_2MUL:
- case OP_2DIV:
- case OP_NEGATE:
- case OP_ABS:
- case OP_NOT:
- case OP_0NOTEQUAL:
- {
- if (stack.size() < 1)
- return false;
- CBigNum bn(stacktop(-1));
- switch (opcode)
- {
- case OP_1ADD: bn += bnOne; break;
- case OP_1SUB: bn -= bnOne; break;
- case OP_2MUL: bn <<= 1; break;
- case OP_2DIV: bn >>= 1; break;
- case OP_NEGATE: bn = -bn; break;
- case OP_ABS: if (bn < bnZero) bn = -bn; break;
- case OP_NOT: bn = (bn == bnZero); break;
- case OP_0NOTEQUAL: bn = (bn != bnZero); break;
- }
- stack.pop_back();
- stack.push_back(bn.getvch());
- }
- break;
- case OP_ADD:
- case OP_SUB:
- case OP_MUL:
- case OP_DIV:
- case OP_MOD:
- case OP_LSHIFT:
- case OP_RSHIFT:
- case OP_BOOLAND:
- case OP_BOOLOR:
- case OP_NUMEQUAL:
- case OP_NUMEQUALVERIFY:
- case OP_NUMNOTEQUAL:
- case OP_LESSTHAN:
- case OP_GREATERTHAN:
- case OP_LESSTHANOREQUAL:
- case OP_GREATERTHANOREQUAL:
- case OP_MIN:
- case OP_MAX:
- {
- if (stack.size() < 2)
- return false;
- CBigNum bn1(stacktop(-2));
- CBigNum bn2(stacktop(-1));
- CBigNum bn;
- switch (opcode)
- {
- case OP_ADD:
- bn = bn1 + bn2;
- break;
- case OP_SUB:
- bn = bn1 - bn2;
- break;
- case OP_MUL:
- if (!BN_mul(&bn, &bn1, &bn2, pctx))
- return false;
- break;
- case OP_DIV:
- if (!BN_div(&bn, NULL, &bn1, &bn2, pctx))
- return false;
- break;
- case OP_MOD:
- if (!BN_mod(&bn, &bn1, &bn2, pctx))
- return false;
- break;
- case OP_LSHIFT:
- if (bn2 < bnZero)
- return false;
- bn = bn1 << bn2.getulong();
- break;
- case OP_RSHIFT:
- if (bn2 < bnZero)
- return false;
- bn = bn1 >> bn2.getulong();
- break;
- case OP_BOOLAND: bn = (bn1 != bnZero && bn2 != bnZero); break;
- case OP_BOOLOR: bn = (bn1 != bnZero || bn2 != bnZero); break;
- case OP_NUMEQUAL: bn = (bn1 == bn2); break;
- case OP_NUMEQUALVERIFY: bn = (bn1 == bn2); break;
- case OP_NUMNOTEQUAL: bn = (bn1 != bn2); break;
- case OP_LESSTHAN: bn = (bn1 < bn2); break;
- case OP_GREATERTHAN: bn = (bn1 > bn2); break;
- case OP_LESSTHANOREQUAL: bn = (bn1 <= bn2); break;
- case OP_GREATERTHANOREQUAL: bn = (bn1 >= bn2); break;
- case OP_MIN: bn = (bn1 < bn2 ? bn1 : bn2); break;
- case OP_MAX: bn = (bn1 > bn2 ? bn1 : bn2); break;
- }
- stack.pop_back();
- stack.pop_back();
- stack.push_back(bn.getvch());
- if (opcode == OP_NUMEQUALVERIFY)
- {
- if (CastToBool(stacktop(-1)))
- stack.pop_back();
- else
- pc = pend;
- }
- }
- break;
- case OP_WITHIN:
- {
- if (stack.size() < 3)
- return false;
- CBigNum bn1(stacktop(-3));
- CBigNum bn2(stacktop(-2));
- CBigNum bn3(stacktop(-1));
- bool fValue = (bn2 <= bn1 && bn1 < bn3);
- stack.pop_back();
- stack.pop_back();
- stack.pop_back();
- stack.push_back(fValue ? vchTrue : vchFalse);
- }
- break;
- case OP_RIPEMD160:
- case OP_SHA1:
- case OP_SHA256:
- case OP_HASH160:
- case OP_HASH256:
- {
- if (stack.size() < 1)
- return false;
- valtype& vch = stacktop(-1);
- valtype vchHash(opcode == OP_RIPEMD160 || opcode == OP_SHA1 || opcode == OP_HASH160 ? 20 : 32);
- if (opcode == OP_RIPEMD160)
- RIPEMD160(&vch[0], vch.size(), &vchHash[0]);
- else if (opcode == OP_SHA1)
- SHA1(&vch[0], vch.size(), &vchHash[0]);
- else if (opcode == OP_SHA256)
- SHA256(&vch[0], vch.size(), &vchHash[0]);
- else if (opcode == OP_HASH160)
- {
- uint160 hash160 = Hash160(vch);
- memcpy(&vchHash[0], &hash160, sizeof(hash160));
- }
- else if (opcode == OP_HASH256)
- {
- uint256 hash = Hash(vch.begin(), vch.end());
- memcpy(&vchHash[0], &hash, sizeof(hash));
- }
- stack.pop_back();
- stack.push_back(vchHash);
- }
- break;
- case OP_CODESEPARATOR:
- {
- pbegincodehash = pc;
- }
- break;
- case OP_CHECKSIG:
- case OP_CHECKSIGVERIFY:
- {
- if (stack.size() < 2)
- return false;
- valtype& vchSig = stacktop(-2);
- valtype& vchPubKey = stacktop(-1);
- CScript scriptCode(pbegincodehash, pend);
- scriptCode.FindAndDelete(CScript(vchSig));
- bool fSuccess = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType);
- stack.pop_back();
- stack.pop_back();
- stack.push_back(fSuccess ? vchTrue : vchFalse);
- if (opcode == OP_CHECKSIGVERIFY)
- {
- if (fSuccess)
- stack.pop_back();
- else
- pc = pend;
- }
- }
- break;
- case OP_CHECKMULTISIG:
- case OP_CHECKMULTISIGVERIFY:
- {
- int i = 1;
- if (stack.size() < i)
- return false;
- int nKeysCount = CBigNum(stacktop(-i)).getint();
- if (nKeysCount < 0)
- return false;
- int ikey = ++i;
- i += nKeysCount;
- if (stack.size() < i)
- return false;
- int nSigsCount = CBigNum(stacktop(-i)).getint();
- if (nSigsCount < 0 || nSigsCount > nKeysCount)
- return false;
- int isig = ++i;
- i += nSigsCount;
- if (stack.size() < i)
- return false;
- CScript scriptCode(pbegincodehash, pend);
- for (int i = 0; i < nSigsCount; i++)
- {
- valtype& vchSig = stacktop(-isig-i);
- scriptCode.FindAndDelete(CScript(vchSig));
- }
- bool fSuccess = true;
- while (fSuccess && nSigsCount > 0)
- {
- valtype& vchSig = stacktop(-isig);
- valtype& vchPubKey = stacktop(-ikey);
- if (CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType))
- {
- isig++;
- nSigsCount--;
- }
- ikey++;
- nKeysCount--;
- if (nSigsCount > nKeysCount)
- fSuccess = false;
- }
- while (i-- > 0)
- stack.pop_back();
- stack.push_back(fSuccess ? vchTrue : vchFalse);
- if (opcode == OP_CHECKMULTISIGVERIFY)
- {
- if (fSuccess)
- stack.pop_back();
- else
- pc = pend;
- }
- }
- break;
- default:
- return false;
- }
- }
- if (pvStackRet)
- *pvStackRet = stack;
- return (stack.empty() ? false : CastToBool(stack.back()));
- }
- #undef top
- uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
- {
- if (nIn >= txTo.vin.size())
- {
- printf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn);
- return 1;
- }
- CTransaction txTmp(txTo);
- scriptCode.FindAndDelete(CScript(OP_CODESEPARATOR));
- for (int i = 0; i < txTmp.vin.size(); i++)
- txTmp.vin[i].scriptSig = CScript();
- txTmp.vin[nIn].scriptSig = scriptCode;
- if ((nHashType & 0x1f) == SIGHASH_NONE)
- {
- txTmp.vout.clear();
- for (int i = 0; i < txTmp.vin.size(); i++)
- if (i != nIn)
- txTmp.vin[i].nSequence = 0;
- }
- else if ((nHashType & 0x1f) == SIGHASH_SINGLE)
- {
- unsigned int nOut = nIn;
- if (nOut >= txTmp.vout.size())
- {
- printf("ERROR: SignatureHash() : nOut=%d out of range\n", nOut);
- return 1;
- }
- txTmp.vout.resize(nOut+1);
- for (int i = 0; i < nOut; i++)
- txTmp.vout[i].SetNull();
- for (int i = 0; i < txTmp.vin.size(); i++)
- if (i != nIn)
- txTmp.vin[i].nSequence = 0;
- }
- if (nHashType & SIGHASH_ANYONECANPAY)
- {
- txTmp.vin[0] = txTmp.vin[nIn];
- txTmp.vin.resize(1);
- }
- CDataStream ss(SER_GETHASH);
- ss.reserve(10000);
- ss << txTmp << nHashType;
- return Hash(ss.begin(), ss.end());
- }
- bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CScript scriptCode,
- const CTransaction& txTo, unsigned int nIn, int nHashType)
- {
- CKey key;
- if (!key.SetPubKey(vchPubKey))
- return false;
- if (vchSig.empty())
- return false;
- if (nHashType == 0)
- nHashType = vchSig.back();
- else if (nHashType != vchSig.back())
- return false;
- vchSig.pop_back();
- if (key.Verify(SignatureHash(scriptCode, txTo, nIn, nHashType), vchSig))
- return true;
- return false;
- }
- bool Solver(const CScript& scriptPubKey, vector<pair<opcodetype, valtype> >& vSolutionRet)
- {
- static vector<CScript> vTemplates;
- if (vTemplates.empty())
- {
- vTemplates.push_back(CScript() << OP_PUBKEY << OP_CHECKSIG);
- vTemplates.push_back(CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG);
- }
- const CScript& script1 = scriptPubKey;
- foreach(const CScript& script2, vTemplates)
- {
- vSolutionRet.clear();
- opcodetype opcode1, opcode2;
- vector<unsigned char> vch1, vch2;
- CScript::const_iterator pc1 = script1.begin();
- CScript::const_iterator pc2 = script2.begin();
- loop
- {
- bool f1 = script1.GetOp(pc1, opcode1, vch1);
- bool f2 = script2.GetOp(pc2, opcode2, vch2);
- if (!f1 && !f2)
- {
- reverse(vSolutionRet.begin(), vSolutionRet.end());
- return true;
- }
- else if (f1 != f2)
- {
- break;
- }
- else if (opcode2 == OP_PUBKEY)
- {
- if (vch1.size() <= sizeof(uint256))
- break;
- vSolutionRet.push_back(make_pair(opcode2, vch1));
- }
- else if (opcode2 == OP_PUBKEYHASH)
- {
- if (vch1.size() != sizeof(uint160))
- break;
- vSolutionRet.push_back(make_pair(opcode2, vch1));
- }
- else if (opcode1 != opcode2)
- {
- break;
- }
- }
- }
- vSolutionRet.clear();
- return false;
- }
- bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& scriptSigRet)
- {
- scriptSigRet.clear();
- vector<pair<opcodetype, valtype> > vSolution;
- if (!Solver(scriptPubKey, vSolution))
- return false;
- CRITICAL_BLOCK(cs_mapKeys)
- {
- foreach(PAIRTYPE(opcodetype, valtype)& item, vSolution)
- {
- if (item.first == OP_PUBKEY)
- {
- const valtype& vchPubKey = item.second;
- if (!mapKeys.count(vchPubKey))
- return false;
- if (hash != 0)
- {
- vector<unsigned char> vchSig;
- if (!CKey::Sign(mapKeys[vchPubKey], hash, vchSig))
- return false;
- vchSig.push_back((unsigned char)nHashType);
- scriptSigRet << vchSig;
- }
- }
- else if (item.first == OP_PUBKEYHASH)
- {
- map<uint160, valtype>::iterator mi = mapPubKeys.find(uint160(item.second));
- if (mi == mapPubKeys.end())
- return false;
- const vector<unsigned char>& vchPubKey = (*mi).second;
- if (!mapKeys.count(vchPubKey))
- return false;
- if (hash != 0)
- {
- vector<unsigned char> vchSig;
- if (!CKey::Sign(mapKeys[vchPubKey], hash, vchSig))
- return false;
- vchSig.push_back((unsigned char)nHashType);
- scriptSigRet << vchSig << vchPubKey;
- }
- }
- }
- }
- return true;
- }
- bool IsMine(const CScript& scriptPubKey)
- {
- CScript scriptSig;
- return Solver(scriptPubKey, 0, 0, scriptSig);
- }
- bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector<unsigned char>& vchPubKeyRet)
- {
- vchPubKeyRet.clear();
- vector<pair<opcodetype, valtype> > vSolution;
- if (!Solver(scriptPubKey, vSolution))
- return false;
- CRITICAL_BLOCK(cs_mapKeys)
- {
- foreach(PAIRTYPE(opcodetype, valtype)& item, vSolution)
- {
- valtype vchPubKey;
- if (item.first == OP_PUBKEY)
- {
- vchPubKey = item.second;
- }
- else if (item.first == OP_PUBKEYHASH)
- {
- map<uint160, valtype>::iterator mi = mapPubKeys.find(uint160(item.second));
- if (mi == mapPubKeys.end())
- continue;
- vchPubKey = (*mi).second;
- }
- if (!fMineOnly || mapKeys.count(vchPubKey))
- {
- vchPubKeyRet = vchPubKey;
- return true;
- }
- }
- }
- return false;
- }
- bool ExtractHash160(const CScript& scriptPubKey, uint160& hash160Ret)
- {
- hash160Ret = 0;
- vector<pair<opcodetype, valtype> > vSolution;
- if (!Solver(scriptPubKey, vSolution))
- return false;
- foreach(PAIRTYPE(opcodetype, valtype)& item, vSolution)
- {
- if (item.first == OP_PUBKEYHASH)
- {
- hash160Ret = uint160(item.second);
- return true;
- }
- }
- return false;
- }
- bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType, CScript scriptPrereq)
- {
- assert(nIn < txTo.vin.size());
- CTxIn& txin = txTo.vin[nIn];
- assert(txin.prevout.n < txFrom.vout.size());
- const CTxOut& txout = txFrom.vout[txin.prevout.n];
- uint256 hash = SignatureHash(scriptPrereq + txout.scriptPubKey, txTo, nIn, nHashType);
- if (!Solver(txout.scriptPubKey, hash, nHashType, txin.scriptSig))
- return false;
- txin.scriptSig = scriptPrereq + txin.scriptSig;
- if (scriptPrereq.empty())
- if (!EvalScript(txin.scriptSig + CScript(OP_CODESEPARATOR) + txout.scriptPubKey, txTo, nIn))
- return false;
- return true;
- }
- bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, int nHashType)
- {
- assert(nIn < txTo.vin.size());
- const CTxIn& txin = txTo.vin[nIn];
- if (txin.prevout.n >= txFrom.vout.size())
- return false;
- const CTxOut& txout = txFrom.vout[txin.prevout.n];
- if (txin.prevout.hash != txFrom.GetHash())
- return false;
- return EvalScript(txin.scriptSig + CScript(OP_CODESEPARATOR) + txout.scriptPubKey, txTo, nIn, nHashType);
- }
- class CTransaction;
- enum
- {
- SIGHASH_ALL = 1,
- SIGHASH_NONE = 2,
- SIGHASH_SINGLE = 3,
- SIGHASH_ANYONECANPAY = 0x80,
- };
- enum opcodetype
- {
- OP_0=0,
- OP_FALSE=OP_0,
- OP_PUSHDATA1=76,
- OP_PUSHDATA2,
- OP_PUSHDATA4,
- OP_1NEGATE,
- OP_RESERVED,
- OP_1,
- OP_TRUE=OP_1,
- OP_2,
- OP_3,
- OP_4,
- OP_5,
- OP_6,
- OP_7,
- OP_8,
- OP_9,
- OP_10,
- OP_11,
- OP_12,
- OP_13,
- OP_14,
- OP_15,
- OP_16,
- OP_NOP,
- OP_VER,
- OP_IF,
- OP_NOTIF,
- OP_VERIF,
- OP_VERNOTIF,
- OP_ELSE,
- OP_ENDIF,
- OP_VERIFY,
- OP_RETURN,
- OP_TOALTSTACK,
- OP_FROMALTSTACK,
- OP_2DROP,
- OP_2DUP,
- OP_3DUP,
- OP_2OVER,
- OP_2ROT,
- OP_2SWAP,
- OP_IFDUP,
- OP_DEPTH,
- OP_DROP,
- OP_DUP,
- OP_NIP,
- OP_OVER,
- OP_PICK,
- OP_ROLL,
- OP_ROT,
- OP_SWAP,
- OP_TUCK,
- OP_CAT,
- OP_SUBSTR,
- OP_LEFT,
- OP_RIGHT,
- OP_SIZE,
- OP_INVERT,
- OP_AND,
- OP_OR,
- OP_XOR,
- OP_EQUAL,
- OP_EQUALVERIFY,
- OP_RESERVED1,
- OP_RESERVED2,
- OP_1ADD,
- OP_1SUB,
- OP_2MUL,
- OP_2DIV,
- OP_NEGATE,
- OP_ABS,
- OP_NOT,
- OP_0NOTEQUAL,
- OP_ADD,
- OP_SUB,
- OP_MUL,
- OP_DIV,
- OP_MOD,
- OP_LSHIFT,
- OP_RSHIFT,
- OP_BOOLAND,
- OP_BOOLOR,
- OP_NUMEQUAL,
- OP_NUMEQUALVERIFY,
- OP_NUMNOTEQUAL,
- OP_LESSTHAN,
- OP_GREATERTHAN,
- OP_LESSTHANOREQUAL,
- OP_GREATERTHANOREQUAL,
- OP_MIN,
- OP_MAX,
- OP_WITHIN,
- OP_RIPEMD160,
- OP_SHA1,
- OP_SHA256,
- OP_HASH160,
- OP_HASH256,
- OP_CODESEPARATOR,
- OP_CHECKSIG,
- OP_CHECKSIGVERIFY,
- OP_CHECKMULTISIG,
- OP_CHECKMULTISIGVERIFY,
- OP_SINGLEBYTE_END = 0xF0,
- OP_DOUBLEBYTE_BEGIN = 0xF000,
- OP_PUBKEY,
- OP_PUBKEYHASH,
- OP_INVALIDOPCODE = 0xFFFF,
- };
- inline const char* GetOpName(opcodetype opcode)
- {
- switch (opcode)
- {
- case OP_0 : return "0";
- case OP_PUSHDATA1 : return "OP_PUSHDATA1";
- case OP_PUSHDATA2 : return "OP_PUSHDATA2";
- case OP_PUSHDATA4 : return "OP_PUSHDATA4";
- case OP_1NEGATE : return "-1";
- case OP_RESERVED : return "OP_RESERVED";
- case OP_1 : return "1";
- case OP_2 : return "2";
- case OP_3 : return "3";
- case OP_4 : return "4";
- case OP_5 : return "5";
- case OP_6 : return "6";
- case OP_7 : return "7";
- case OP_8 : return "8";
- case OP_9 : return "9";
- case OP_10 : return "10";
- case OP_11 : return "11";
- case OP_12 : return "12";
- case OP_13 : return "13";
- case OP_14 : return "14";
- case OP_15 : return "15";
- case OP_16 : return "16";
- case OP_NOP : return "OP_NOP";
- case OP_VER : return "OP_VER";
- case OP_IF : return "OP_IF";
- case OP_NOTIF : return "OP_NOTIF";
- case OP_VERIF : return "OP_VERIF";
- case OP_VERNOTIF : return "OP_VERNOTIF";
- case OP_ELSE : return "OP_ELSE";
- case OP_ENDIF : return "OP_ENDIF";
- case OP_VERIFY : return "OP_VERIFY";
- case OP_RETURN : return "OP_RETURN";
- case OP_TOALTSTACK : return "OP_TOALTSTACK";
- case OP_FROMALTSTACK : return "OP_FROMALTSTACK";
- case OP_2DROP : return "OP_2DROP";
- case OP_2DUP : return "OP_2DUP";
- case OP_3DUP : return "OP_3DUP";
- case OP_2OVER : return "OP_2OVER";
- case OP_2ROT : return "OP_2ROT";
- case OP_2SWAP : return "OP_2SWAP";
- case OP_IFDUP : return "OP_IFDUP";
- case OP_DEPTH : return "OP_DEPTH";
- case OP_DROP : return "OP_DROP";
- case OP_DUP : return "OP_DUP";
- case OP_NIP : return "OP_NIP";
- case OP_OVER : return "OP_OVER";
- case OP_PICK : return "OP_PICK";
- case OP_ROLL : return "OP_ROLL";
- case OP_ROT : return "OP_ROT";
- case OP_SWAP : return "OP_SWAP";
- case OP_TUCK : return "OP_TUCK";
- case OP_CAT : return "OP_CAT";
- case OP_SUBSTR : return "OP_SUBSTR";
- case OP_LEFT : return "OP_LEFT";
- case OP_RIGHT : return "OP_RIGHT";
- case OP_SIZE : return "OP_SIZE";
- case OP_INVERT : return "OP_INVERT";
- case OP_AND : return "OP_AND";
- case OP_OR : return "OP_OR";
- case OP_XOR : return "OP_XOR";
- case OP_EQUAL : return "OP_EQUAL";
- case OP_EQUALVERIFY : return "OP_EQUALVERIFY";
- case OP_RESERVED1 : return "OP_RESERVED1";
- case OP_RESERVED2 : return "OP_RESERVED2";
- case OP_1ADD : return "OP_1ADD";
- case OP_1SUB : return "OP_1SUB";
- case OP_2MUL : return "OP_2MUL";
- case OP_2DIV : return "OP_2DIV";
- case OP_NEGATE : return "OP_NEGATE";
- case OP_ABS : return "OP_ABS";
- case OP_NOT : return "OP_NOT";
- case OP_0NOTEQUAL : return "OP_0NOTEQUAL";
- case OP_ADD : return "OP_ADD";
- case OP_SUB : return "OP_SUB";
- case OP_MUL : return "OP_MUL";
- case OP_DIV : return "OP_DIV";
- case OP_MOD : return "OP_MOD";
- case OP_LSHIFT : return "OP_LSHIFT";
- case OP_RSHIFT : return "OP_RSHIFT";
- case OP_BOOLAND : return "OP_BOOLAND";
- case OP_BOOLOR : return "OP_BOOLOR";
- case OP_NUMEQUAL : return "OP_NUMEQUAL";
- case OP_NUMEQUALVERIFY : return "OP_NUMEQUALVERIFY";
- case OP_NUMNOTEQUAL : return "OP_NUMNOTEQUAL";
- case OP_LESSTHAN : return "OP_LESSTHAN";
- case OP_GREATERTHAN : return "OP_GREATERTHAN";
- case OP_LESSTHANOREQUAL : return "OP_LESSTHANOREQUAL";
- case OP_GREATERTHANOREQUAL : return "OP_GREATERTHANOREQUAL";
- case OP_MIN : return "OP_MIN";
- case OP_MAX : return "OP_MAX";
- case OP_WITHIN : return "OP_WITHIN";
- case OP_RIPEMD160 : return "OP_RIPEMD160";
- case OP_SHA1 : return "OP_SHA1";
- case OP_SHA256 : return "OP_SHA256";
- case OP_HASH160 : return "OP_HASH160";
- case OP_HASH256 : return "OP_HASH256";
- case OP_CODESEPARATOR : return "OP_CODESEPARATOR";
- case OP_CHECKSIG : return "OP_CHECKSIG";
- case OP_CHECKSIGVERIFY : return "OP_CHECKSIGVERIFY";
- case OP_CHECKMULTISIG : return "OP_CHECKMULTISIG";
- case OP_CHECKMULTISIGVERIFY : return "OP_CHECKMULTISIGVERIFY";
- case OP_SINGLEBYTE_END : return "OP_SINGLEBYTE_END";
- case OP_DOUBLEBYTE_BEGIN : return "OP_DOUBLEBYTE_BEGIN";
- case OP_PUBKEY : return "OP_PUBKEY";
- case OP_PUBKEYHASH : return "OP_PUBKEYHASH";
- case OP_INVALIDOPCODE : return "OP_INVALIDOPCODE";
- default:
- return "UNKNOWN_OPCODE";
- }
- };
- inline string ValueString(const vector<unsigned char>& vch)
- {
- if (vch.size() <= 4)
- return strprintf("%d", CBigNum(vch).getint());
- else
- return HexNumStr(vch.begin(), vch.end());
- }
- inline string StackString(const vector<vector<unsigned char> >& vStack)
- {
- string str;
- foreach(const vector<unsigned char>& vch, vStack)
- {
- if (!str.empty())
- str += " ";
- str += ValueString(vch);
- }
- return str;
- }
- class CScript : public vector<unsigned char>
- {
- protected:
- CScript& push_int64(int64 n)
- {
- if (n == -1 || (n >= 1 && n <= 16))
- {
- push_back(n + (OP_1 - 1));
- }
- else
- {
- CBigNum bn(n);
- *this << bn.getvch();
- }
- return (*this);
- }
- CScript& push_uint64(uint64 n)
- {
- if (n == -1 || (n >= 1 && n <= 16))
- {
- push_back(n + (OP_1 - 1));
- }
- else
- {
- CBigNum bn(n);
- *this << bn.getvch();
- }
- return (*this);
- }
- public:
- CScript() { }
- CScript(const CScript& b) : vector<unsigned char>(b.begin(), b.end()) { }
- CScript(const_iterator pbegin, const_iterator pend) : vector<unsigned char>(pbegin, pend) { }
- #ifndef _MSC_VER
- CScript(const unsigned char* pbegin, const unsigned char* pend) : vector<unsigned char>(pbegin, pend) { }
- #endif
- CScript& operator+=(const CScript& b)
- {
- insert(end(), b.begin(), b.end());
- return *this;
- }
- friend CScript operator+(const CScript& a, const CScript& b)
- {
- CScript ret = a;
- ret += b;
- return (ret);
- }
- explicit CScript(char b) { operator<<(b); }
- explicit CScript(short b) { operator<<(b); }
- explicit CScript(int b) { operator<<(b); }
- explicit CScript(long b) { operator<<(b); }
- explicit CScript(int64 b) { operator<<(b); }
- explicit CScript(unsigned char b) { operator<<(b); }
- explicit CScript(unsigned int b) { operator<<(b); }
- explicit CScript(unsigned short b) { operator<<(b); }
- explicit CScript(unsigned long b) { operator<<(b); }
- explicit CScript(uint64 b) { operator<<(b); }
- explicit CScript(opcodetype b) { operator<<(b); }
- explicit CScript(const uint256& b) { operator<<(b); }
- explicit CScript(const CBigNum& b) { operator<<(b); }
- explicit CScript(const vector<unsigned char>& b) { operator<<(b); }
- CScript& operator<<(char b) { return (push_int64(b)); }
- CScript& operator<<(short b) { return (push_int64(b)); }
- CScript& operator<<(int b) { return (push_int64(b)); }
- CScript& operator<<(long b) { return (push_int64(b)); }
- CScript& operator<<(int64 b) { return (push_int64(b)); }
- CScript& operator<<(unsigned char b) { return (push_uint64(b)); }
- CScript& operator<<(unsigned int b) { return (push_uint64(b)); }
- CScript& operator<<(unsigned short b) { return (push_uint64(b)); }
- CScript& operator<<(unsigned long b) { return (push_uint64(b)); }
- CScript& operator<<(uint64 b) { return (push_uint64(b)); }
- CScript& operator<<(opcodetype opcode)
- {
- if (opcode <= OP_SINGLEBYTE_END)
- {
- insert(end(), (unsigned char)opcode);
- }
- else
- {
- assert(opcode >= OP_DOUBLEBYTE_BEGIN);
- insert(end(), (unsigned char)(opcode >> 8));
- insert(end(), (unsigned char)(opcode & 0xFF));
- }
- return (*this);
- }
- CScript& operator<<(const uint160& b)
- {
- insert(end(), sizeof(b));
- insert(end(), (unsigned char*)&b, (unsigned char*)&b + sizeof(b));
- return (*this);
- }
- CScript& operator<<(const uint256& b)
- {
- insert(end(), sizeof(b));
- insert(end(), (unsigned char*)&b, (unsigned char*)&b + sizeof(b));
- return (*this);
- }
- CScript& operator<<(const CBigNum& b)
- {
- *this << b.getvch();
- return (*this);
- }
- CScript& operator<<(const vector<unsigned char>& b)
- {
- if (b.size() < OP_PUSHDATA1)
- {
- insert(end(), (unsigned char)b.size());
- }
- else if (b.size() <= 0xff)
- {
- insert(end(), OP_PUSHDATA1);
- insert(end(), (unsigned char)b.size());
- }
- else
- {
- insert(end(), OP_PUSHDATA2);
- unsigned short nSize = b.size();
- insert(end(), (unsigned char*)&nSize, (unsigned char*)&nSize + sizeof(nSize));
- }
- insert(end(), b.begin(), b.end());
- return (*this);
- }
- CScript& operator<<(const CScript& b)
- {
- assert(("warning: pushing a CScript onto a CScript with << is probably not intended, use + to concatenate", false));
- return (*this);
- }
- bool GetOp(iterator& pc, opcodetype& opcodeRet, vector<unsigned char>& vchRet)
- {
- const_iterator pc2 = pc;
- bool fRet = GetOp(pc2, opcodeRet, vchRet);
- pc = begin() + (pc2 - begin());
- return fRet;
- }
- bool GetOp(const_iterator& pc, opcodetype& opcodeRet, vector<unsigned char>& vchRet) const
- {
- opcodeRet = OP_INVALIDOPCODE;
- vchRet.clear();
- if (pc >= end())
- return false;
- unsigned int opcode = *pc++;
- if (opcode >= OP_SINGLEBYTE_END)
- {
- if (pc + 1 > end())
- return false;
- opcode <<= 8;
- opcode |= *pc++;
- }
- if (opcode <= OP_PUSHDATA4)
- {
- unsigned int nSize = opcode;
- if (opcode == OP_PUSHDATA1)
- {
- if (pc + 1 > end())
- return false;
- nSize = *pc++;
- }
- else if (opcode == OP_PUSHDATA2)
- {
- if (pc + 2 > end())
- return false;
- nSize = 0;
- memcpy(&nSize, &pc[0], 2);
- pc += 2;
- }
- else if (opcode == OP_PUSHDATA4)
- {
- if (pc + 4 > end())
- return false;
- memcpy(&nSize, &pc[0], 4);
- pc += 4;
- }
- if (pc + nSize > end())
- return false;
- vchRet.assign(pc, pc + nSize);
- pc += nSize;
- }
- opcodeRet = (opcodetype)opcode;
- return true;
- }
- void FindAndDelete(const CScript& b)
- {
- iterator pc = begin();
- opcodetype opcode;
- vector<unsigned char> vchPushValue;
- int count = 0;
- do
- {
- while (end() - pc >= b.size() && memcmp(&pc[0], &b[0], b.size()) == 0)
- {
- erase(pc, pc + b.size());
- count++;
- }
- }
- while (GetOp(pc, opcode, vchPushValue));
- }
- void PrintHex() const
- {
- printf("CScript(%s)\n", HexStr(begin(), end()).c_str());
- }
- string ToString() const
- {
- string str;
- opcodetype opcode;
- vector<unsigned char> vch;
- const_iterator it = begin();
- while (GetOp(it, opcode, vch))
- {
- if (!str.empty())
- str += " ";
- if (opcode <= OP_PUSHDATA4)
- str += ValueString(vch);
- else
- str += GetOpName(opcode);
- }
- return str;
- }
- void print() const
- {
- printf("%s\n", ToString().c_str());
- }
- };
- bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType=0,
- vector<vector<unsigned char> >* pvStackRet=NULL);
- uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
- bool IsMine(const CScript& scriptPubKey);
- bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector<unsigned char>& vchPubKeyRet);
- bool ExtractHash160(const CScript& scriptPubKey, uint160& hash160Ret);
- bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL, CScript scriptPrereq=CScript());
- bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, int nHashType=0);
- #include <vector>
- #include <map>
- #include <boost/type_traits/is_fundamental.hpp>
- #if defined(_MSC_VER) || defined(__BORLANDC__)
- typedef __int64 int64;
- typedef unsigned __int64 uint64;
- #else
- typedef long long int64;
- typedef unsigned long long uint64;
- #endif
- #if defined(_MSC_VER) && _MSC_VER < 1300
- #define for if (false) ; else for
- #endif
- class CScript;
- class CDataStream;
- class CAutoFile;
- static const int VERSION = 101;
- enum
- {
- SER_NETWORK = (1 << 0),
- SER_DISK = (1 << 1),
- SER_GETHASH = (1 << 2),
- SER_SKIPSIG = (1 << 16),
- SER_BLOCKHEADERONLY = (1 << 17),
- };
- #define IMPLEMENT_SERIALIZE(statements) \
- unsigned int GetSerializeSize(int nType=0, int nVersion=VERSION) const \
- { \
- CSerActionGetSerializeSize ser_action; \
- const bool fGetSize = true; \
- const bool fWrite = false; \
- const bool fRead = false; \
- unsigned int nSerSize = 0; \
- ser_streamplaceholder s; \
- s.nType = nType; \
- s.nVersion = nVersion; \
- {statements} \
- return nSerSize; \
- } \
- template<typename Stream> \
- void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const \
- { \
- CSerActionSerialize ser_action; \
- const bool fGetSize = false; \
- const bool fWrite = true; \
- const bool fRead = false; \
- unsigned int nSerSize = 0; \
- {statements} \
- } \
- template<typename Stream> \
- void Unserialize(Stream& s, int nType=0, int nVersion=VERSION) \
- { \
- CSerActionUnserialize ser_action; \
- const bool fGetSize = false; \
- const bool fWrite = false; \
- const bool fRead = true; \
- unsigned int nSerSize = 0; \
- {statements} \
- }
- #define READWRITE(obj) (nSerSize += ::SerReadWrite(s, (obj), nType, nVersion, ser_action))
- #define WRITEDATA(s, obj) s.write((char*)&(obj), sizeof(obj))
- #define READDATA(s, obj) s.read((char*)&(obj), sizeof(obj))
- inline unsigned int GetSerializeSize(char a, int, int=0) { return sizeof(a); }
- inline unsigned int GetSerializeSize(signed char a, int, int=0) { return sizeof(a); }
- inline unsigned int GetSerializeSize(unsigned char a, int, int=0) { return sizeof(a); }
- inline unsigned int GetSerializeSize(signed short a, int, int=0) { return sizeof(a); }
- inline unsigned int GetSerializeSize(unsigned short a, int, int=0) { return sizeof(a); }
- inline unsigned int GetSerializeSize(signed int a, int, int=0) { return sizeof(a); }
- inline unsigned int GetSerializeSize(unsigned int a, int, int=0) { return sizeof(a); }
- inline unsigned int GetSerializeSize(signed long a, int, int=0) { return sizeof(a); }
- inline unsigned int GetSerializeSize(unsigned long a, int, int=0) { return sizeof(a); }
- inline unsigned int GetSerializeSize(int64 a, int, int=0) { return sizeof(a); }
- inline unsigned int GetSerializeSize(uint64 a, int, int=0) { return sizeof(a); }
- inline unsigned int GetSerializeSize(float a, int, int=0) { return sizeof(a); }
- inline unsigned int GetSerializeSize(double a, int, int=0) { return sizeof(a); }
- template<typename Stream> inline void Serialize(Stream& s, char a, int, int=0) { WRITEDATA(s, a); }
- template<typename Stream> inline void Serialize(Stream& s, signed char a, int, int=0) { WRITEDATA(s, a); }
- template<typename Stream> inline void Serialize(Stream& s, unsigned char a, int, int=0) { WRITEDATA(s, a); }
- template<typename Stream> inline void Serialize(Stream& s, signed short a, int, int=0) { WRITEDATA(s, a); }
- template<typename Stream> inline void Serialize(Stream& s, unsigned short a, int, int=0) { WRITEDATA(s, a); }
- template<typename Stream> inline void Serialize(Stream& s, signed int a, int, int=0) { WRITEDATA(s, a); }
- template<typename Stream> inline void Serialize(Stream& s, unsigned int a, int, int=0) { WRITEDATA(s, a); }
- template<typename Stream> inline void Serialize(Stream& s, signed long a, int, int=0) { WRITEDATA(s, a); }
- template<typename Stream> inline void Serialize(Stream& s, unsigned long a, int, int=0) { WRITEDATA(s, a); }
- template<typename Stream> inline void Serialize(Stream& s, int64 a, int, int=0) { WRITEDATA(s, a); }
- template<typename Stream> inline void Serialize(Stream& s, uint64 a, int, int=0) { WRITEDATA(s, a); }
- template<typename Stream> inline void Serialize(Stream& s, float a, int, int=0) { WRITEDATA(s, a); }
- template<typename Stream> inline void Serialize(Stream& s, double a, int, int=0) { WRITEDATA(s, a); }
- template<typename Stream> inline void Unserialize(Stream& s, char& a, int, int=0) { READDATA(s, a); }
- template<typename Stream> inline void Unserialize(Stream& s, signed char& a, int, int=0) { READDATA(s, a); }
- template<typename Stream> inline void Unserialize(Stream& s, unsigned char& a, int, int=0) { READDATA(s, a); }
- template<typename Stream> inline void Unserialize(Stream& s, signed short& a, int, int=0) { READDATA(s, a); }
- template<typename Stream> inline void Unserialize(Stream& s, unsigned short& a, int, int=0) { READDATA(s, a); }
- template<typename Stream> inline void Unserialize(Stream& s, signed int& a, int, int=0) { READDATA(s, a); }
- template<typename Stream> inline void Unserialize(Stream& s, unsigned int& a, int, int=0) { READDATA(s, a); }
- template<typename Stream> inline void Unserialize(Stream& s, signed long& a, int, int=0) { READDATA(s, a); }
- template<typename Stream> inline void Unserialize(Stream& s, unsigned long& a, int, int=0) { READDATA(s, a); }
- template<typename Stream> inline void Unserialize(Stream& s, int64& a, int, int=0) { READDATA(s, a); }
- template<typename Stream> inline void Unserialize(Stream& s, uint64& a, int, int=0) { READDATA(s, a); }
- template<typename Stream> inline void Unserialize(Stream& s, float& a, int, int=0) { READDATA(s, a); }
- template<typename Stream> inline void Unserialize(Stream& s, double& a, int, int=0) { READDATA(s, a); }
- inline unsigned int GetSerializeSize(bool a, int, int=0) { return sizeof(char); }
- template<typename Stream> inline void Serialize(Stream& s, bool a, int, int=0) { char f=a; WRITEDATA(s, f); }
- template<typename Stream> inline void Unserialize(Stream& s, bool& a, int, int=0) { char f; READDATA(s, f); a=f; }
- inline unsigned int GetSizeOfCompactSize(uint64 nSize)
- {
- if (nSize < UCHAR_MAX-2) return sizeof(unsigned char);
- else if (nSize <= USHRT_MAX) return sizeof(unsigned char) + sizeof(unsigned short);
- else if (nSize <= UINT_MAX) return sizeof(unsigned char) + sizeof(unsigned int);
- else return sizeof(unsigned char) + sizeof(uint64);
- }
- template<typename Stream>
- void WriteCompactSize(Stream& os, uint64 nSize)
- {
- if (nSize < UCHAR_MAX-2)
- {
- unsigned char chSize = nSize;
- WRITEDATA(os, chSize);
- }
- else if (nSize <= USHRT_MAX)
- {
- unsigned char chSize = UCHAR_MAX-2;
- unsigned short xSize = nSize;
- WRITEDATA(os, chSize);
- WRITEDATA(os, xSize);
- }
- else if (nSize <= UINT_MAX)
- {
- unsigned char chSize = UCHAR_MAX-1;
- unsigned int xSize = nSize;
- WRITEDATA(os, chSize);
- WRITEDATA(os, xSize);
- }
- else
- {
- unsigned char chSize = UCHAR_MAX;
- WRITEDATA(os, chSize);
- WRITEDATA(os, nSize);
- }
- return;
- }
- template<typename Stream>
- uint64 ReadCompactSize(Stream& is)
- {
- unsigned char chSize;
- READDATA(is, chSize);
- if (chSize < UCHAR_MAX-2)
- {
- return chSize;
- }
- else if (chSize == UCHAR_MAX-2)
- {
- unsigned short nSize;
- READDATA(is, nSize);
- return nSize;
- }
- else if (chSize == UCHAR_MAX-1)
- {
- unsigned int nSize;
- READDATA(is, nSize);
- return nSize;
- }
- else
- {
- uint64 nSize;
- READDATA(is, nSize);
- return nSize;
- }
- }
- #define FLATDATA(obj) REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj)))
- class CFlatData
- {
- protected:
- char* pbegin;
- char* pend;
- public:
- CFlatData(void* pbeginIn, void* pendIn) : pbegin((char*)pbeginIn), pend((char*)pendIn) { }
- char* begin() { return pbegin; }
- const char* begin() const { return pbegin; }
- char* end() { return pend; }
- const char* end() const { return pend; }
- unsigned int GetSerializeSize(int, int=0) const
- {
- return pend - pbegin;
- }
- template<typename Stream>
- void Serialize(Stream& s, int, int=0) const
- {
- s.write(pbegin, pend - pbegin);
- }
- template<typename Stream>
- void Unserialize(Stream& s, int, int=0)
- {
- s.read(pbegin, pend - pbegin);
- }
- };
- template<std::size_t LEN>
- class CFixedFieldString
- {
- protected:
- const string* pcstr;
- string* pstr;
- public:
- explicit CFixedFieldString(const string& str) : pcstr(&str), pstr(NULL) { }
- explicit CFixedFieldString(string& str) : pcstr(&str), pstr(&str) { }
- unsigned int GetSerializeSize(int, int=0) const
- {
- return LEN;
- }
- template<typename Stream>
- void Serialize(Stream& s, int, int=0) const
- {
- char pszBuf[LEN];
- strncpy(pszBuf, pcstr->c_str(), LEN);
- s.write(pszBuf, LEN);
- }
- template<typename Stream>
- void Unserialize(Stream& s, int, int=0)
- {
- if (pstr == NULL)
- throw std::ios_base::failure("CFixedFieldString::Unserialize : trying to unserialize to const string");
- char pszBuf[LEN+1];
- s.read(pszBuf, LEN);
- pszBuf[LEN] = '\0';
- *pstr = pszBuf;
- }
- };
- template<typename C> unsigned int GetSerializeSize(const basic_string<C>& str, int, int=0);
- template<typename Stream, typename C> void Serialize(Stream& os, const basic_string<C>& str, int, int=0);
- template<typename Stream, typename C> void Unserialize(Stream& is, basic_string<C>& str, int, int=0);
- template<typename T, typename A> unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&);
- template<typename T, typename A> unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&);
- template<typename T, typename A> inline unsigned int GetSerializeSize(const std::vector<T, A>& v, int nType, int nVersion=VERSION);
- template<typename Stream, typename T, typename A> void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&);
- template<typename Stream, typename T, typename A> void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&);
- template<typename Stream, typename T, typename A> inline void Serialize(Stream& os, const std::vector<T, A>& v, int nType, int nVersion=VERSION);
- template<typename Stream, typename T, typename A> void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&);
- template<typename Stream, typename T, typename A> void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&);
- template<typename Stream, typename T, typename A> inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersion=VERSION);
- extern inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion=VERSION);
- template<typename Stream> void Serialize(Stream& os, const CScript& v, int nType, int nVersion=VERSION);
- template<typename Stream> void Unserialize(Stream& is, CScript& v, int nType, int nVersion=VERSION);
- template<typename K, typename T> unsigned int GetSerializeSize(const std::pair<K, T>& item, int nType, int nVersion=VERSION);
- template<typename Stream, typename K, typename T> void Serialize(Stream& os, const std::pair<K, T>& item, int nType, int nVersion=VERSION);
- template<typename Stream, typename K, typename T> void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion=VERSION);
- template<typename K, typename T, typename Pred, typename A> unsigned int GetSerializeSize(const std::map<K, T, Pred, A>& m, int nType, int nVersion=VERSION);
- template<typename Stream, typename K, typename T, typename Pred, typename A> void Serialize(Stream& os, const std::map<K, T, Pred, A>& m, int nType, int nVersion=VERSION);
- template<typename Stream, typename K, typename T, typename Pred, typename A> void Unserialize(Stream& is, std::map<K, T, Pred, A>& m, int nType, int nVersion=VERSION);
- template<typename K, typename Pred, typename A> unsigned int GetSerializeSize(const std::set<K, Pred, A>& m, int nType, int nVersion=VERSION);
- template<typename Stream, typename K, typename Pred, typename A> void Serialize(Stream& os, const std::set<K, Pred, A>& m, int nType, int nVersion=VERSION);
- template<typename Stream, typename K, typename Pred, typename A> void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion=VERSION);
- template<typename T>
- inline unsigned int GetSerializeSize(const T& a, long nType, int nVersion=VERSION)
- {
- return a.GetSerializeSize((int)nType, nVersion);
- }
- template<typename Stream, typename T>
- inline void Serialize(Stream& os, const T& a, long nType, int nVersion=VERSION)
- {
- a.Serialize(os, (int)nType, nVersion);
- }
- template<typename Stream, typename T>
- inline void Unserialize(Stream& is, T& a, long nType, int nVersion=VERSION)
- {
- a.Unserialize(is, (int)nType, nVersion);
- }
- template<typename C>
- unsigned int GetSerializeSize(const basic_string<C>& str, int, int)
- {
- return GetSizeOfCompactSize(str.size()) + str.size() * sizeof(str[0]);
- }
- template<typename Stream, typename C>
- void Serialize(Stream& os, const basic_string<C>& str, int, int)
- {
- WriteCompactSize(os, str.size());
- if (!str.empty())
- os.write((char*)&str[0], str.size() * sizeof(str[0]));
- }
- template<typename Stream, typename C>
- void Unserialize(Stream& is, basic_string<C>& str, int, int)
- {
- unsigned int nSize = ReadCompactSize(is);
- str.resize(nSize);
- if (nSize != 0)
- is.read((char*)&str[0], nSize * sizeof(str[0]));
- }
- template<typename T, typename A>
- unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&)
- {
- return (GetSizeOfCompactSize(v.size()) + v.size() * sizeof(T));
- }
- template<typename T, typename A>
- unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&)
- {
- unsigned int nSize = GetSizeOfCompactSize(v.size());
- for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi)
- nSize += GetSerializeSize((*vi), nType, nVersion);
- return nSize;
- }
- template<typename T, typename A>
- inline unsigned int GetSerializeSize(const std::vector<T, A>& v, int nType, int nVersion)
- {
- return GetSerializeSize_impl(v, nType, nVersion, boost::is_fundamental<T>());
- }
- template<typename Stream, typename T, typename A>
- void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&)
- {
- WriteCompactSize(os, v.size());
- if (!v.empty())
- os.write((char*)&v[0], v.size() * sizeof(T));
- }
- template<typename Stream, typename T, typename A>
- void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&)
- {
- WriteCompactSize(os, v.size());
- for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi)
- ::Serialize(os, (*vi), nType, nVersion);
- }
- template<typename Stream, typename T, typename A>
- inline void Serialize(Stream& os, const std::vector<T, A>& v, int nType, int nVersion)
- {
- Serialize_impl(os, v, nType, nVersion, boost::is_fundamental<T>());
- }
- template<typename Stream, typename T, typename A>
- void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const boost::true_type&)
- {
- v.clear();
- unsigned int nSize = ReadCompactSize(is);
- unsigned int i = 0;
- while (i < nSize)
- {
- unsigned int blk = min(nSize - i, 1 + 4999999 / sizeof(T));
- v.resize(i + blk);
- is.read((char*)&v[i], blk * sizeof(T));
- i += blk;
- }
- }
- template<typename Stream, typename T, typename A>
- void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const boost::false_type&)
- {
- v.clear();
- unsigned int nSize = ReadCompactSize(is);
- unsigned int i = 0;
- unsigned int nMid = 0;
- while (nMid < nSize)
- {
- nMid += 5000000 / sizeof(T);
- if (nMid > nSize)
- nMid = nSize;
- v.resize(nMid);
- for (; i < nMid; i++)
- Unserialize(is, v[i], nType, nVersion);
- }
- }
- template<typename Stream, typename T, typename A>
- inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersion)
- {
- Unserialize_impl(is, v, nType, nVersion, boost::is_fundamental<T>());
- }
- inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion)
- {
- return GetSerializeSize((const vector<unsigned char>&)v, nType, nVersion);
- }
- template<typename Stream>
- void Serialize(Stream& os, const CScript& v, int nType, int nVersion)
- {
- Serialize(os, (const vector<unsigned char>&)v, nType, nVersion);
- }
- template<typename Stream>
- void Unserialize(Stream& is, CScript& v, int nType, int nVersion)
- {
- Unserialize(is, (vector<unsigned char>&)v, nType, nVersion);
- }
- template<typename K, typename T>
- unsigned int GetSerializeSize(const std::pair<K, T>& item, int nType, int nVersion)
- {
- return GetSerializeSize(item.first, nType, nVersion) + GetSerializeSize(item.second, nType, nVersion);
- }
- template<typename Stream, typename K, typename T>
- void Serialize(Stream& os, const std::pair<K, T>& item, int nType, int nVersion)
- {
- Serialize(os, item.first, nType, nVersion);
- Serialize(os, item.second, nType, nVersion);
- }
- template<typename Stream, typename K, typename T>
- void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion)
- {
- Unserialize(is, item.first, nType, nVersion);
- Unserialize(is, item.second, nType, nVersion);
- }
- template<typename K, typename T, typename Pred, typename A>
- unsigned int GetSerializeSize(const std::map<K, T, Pred, A>& m, int nType, int nVersion)
- {
- unsigned int nSize = GetSizeOfCompactSize(m.size());
- for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi)
- nSize += GetSerializeSize((*mi), nType, nVersion);
- return nSize;
- }
- template<typename Stream, typename K, typename T, typename Pred, typename A>
- void Serialize(Stream& os, const std::map<K, T, Pred, A>& m, int nType, int nVersion)
- {
- WriteCompactSize(os, m.size());
- for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi)
- Serialize(os, (*mi), nType, nVersion);
- }
- template<typename Stream, typename K, typename T, typename Pred, typename A>
- void Unserialize(Stream& is, std::map<K, T, Pred, A>& m, int nType, int nVersion)
- {
- m.clear();
- unsigned int nSize = ReadCompactSize(is);
- typename std::map<K, T, Pred, A>::iterator mi = m.begin();
- for (unsigned int i = 0; i < nSize; i++)
- {
- pair<K, T> item;
- Unserialize(is, item, nType, nVersion);
- mi = m.insert(mi, item);
- }
- }
- template<typename K, typename Pred, typename A>
- unsigned int GetSerializeSize(const std::set<K, Pred, A>& m, int nType, int nVersion)
- {
- unsigned int nSize = GetSizeOfCompactSize(m.size());
- for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it)
- nSize += GetSerializeSize((*it), nType, nVersion);
- return nSize;
- }
- template<typename Stream, typename K, typename Pred, typename A>
- void Serialize(Stream& os, const std::set<K, Pred, A>& m, int nType, int nVersion)
- {
- WriteCompactSize(os, m.size());
- for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it)
- Serialize(os, (*it), nType, nVersion);
- }
- template<typename Stream, typename K, typename Pred, typename A>
- void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion)
- {
- m.clear();
- unsigned int nSize = ReadCompactSize(is);
- typename std::set<K, Pred, A>::iterator it = m.begin();
- for (unsigned int i = 0; i < nSize; i++)
- {
- K key;
- Unserialize(is, key, nType, nVersion);
- it = m.insert(it, key);
- }
- }
- class CSerActionGetSerializeSize { };
- class CSerActionSerialize { };
- class CSerActionUnserialize { };
- template<typename Stream, typename T>
- inline unsigned int SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionGetSerializeSize ser_action)
- {
- return ::GetSerializeSize(obj, nType, nVersion);
- }
- template<typename Stream, typename T>
- inline unsigned int SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionSerialize ser_action)
- {
- ::Serialize(s, obj, nType, nVersion);
- return 0;
- }
- template<typename Stream, typename T>
- inline unsigned int SerReadWrite(Stream& s, T& obj, int nType, int nVersion, CSerActionUnserialize ser_action)
- {
- ::Unserialize(s, obj, nType, nVersion);
- return 0;
- }
- struct ser_streamplaceholder
- {
- int nType;
- int nVersion;
- };
- template<typename T>
- struct secure_allocator : public std::allocator<T>
- {
- typedef std::allocator<T> base;
- typedef typename base::size_type size_type;
- typedef typename base::difference_type difference_type;
- typedef typename base::pointer pointer;
- typedef typename base::const_pointer const_pointer;
- typedef typename base::reference reference;
- typedef typename base::const_reference const_reference;
- typedef typename base::value_type value_type;
- secure_allocator() throw() {}
- secure_allocator(const secure_allocator& a) throw() : base(a) {}
- ~secure_allocator() throw() {}
- template<typename _Other> struct rebind
- { typedef secure_allocator<_Other> other; };
- void deallocate(T* p, std::size_t n)
- {
- if (p != NULL)
- memset(p, 0, sizeof(T) * n);
- allocator<T>::deallocate(p, n);
- }
- };
- class CDataStream
- {
- protected:
- typedef vector<char, secure_allocator<char> > vector_type;
- vector_type vch;
- unsigned int nReadPos;
- short state;
- short exceptmask;
- public:
- int nType;
- int nVersion;
- typedef vector_type::allocator_type allocator_type;
- typedef vector_type::size_type size_type;
- typedef vector_type::difference_type difference_type;
- typedef vector_type::reference reference;
- typedef vector_type::const_reference const_reference;
- typedef vector_type::value_type value_type;
- typedef vector_type::iterator iterator;
- typedef vector_type::const_iterator const_iterator;
- typedef vector_type::reverse_iterator reverse_iterator;
- explicit CDataStream(int nTypeIn=0, int nVersionIn=VERSION)
- {
- Init(nTypeIn, nVersionIn);
- }
- CDataStream(const_iterator pbegin, const_iterator pend, int nTypeIn=0, int nVersionIn=VERSION) : vch(pbegin, pend)
- {
- Init(nTypeIn, nVersionIn);
- }
- #if !defined(_MSC_VER) || _MSC_VER >= 1300
- CDataStream(const char* pbegin, const char* pend, int nTypeIn=0, int nVersionIn=VERSION) : vch(pbegin, pend)
- {
- Init(nTypeIn, nVersionIn);
- }
- #endif
- CDataStream(const vector_type& vchIn, int nTypeIn=0, int nVersionIn=VERSION) : vch(vchIn.begin(), vchIn.end())
- {
- Init(nTypeIn, nVersionIn);
- }
- CDataStream(const vector<char>& vchIn, int nTypeIn=0, int nVersionIn=VERSION) : vch(vchIn.begin(), vchIn.end())
- {
- Init(nTypeIn, nVersionIn);
- }
- CDataStream(const vector<unsigned char>& vchIn, int nTypeIn=0, int nVersionIn=VERSION) : vch((char*)&vchIn.begin()[0], (char*)&vchIn.end()[0])
- {
- Init(nTypeIn, nVersionIn);
- }
- void Init(int nTypeIn=0, int nVersionIn=VERSION)
- {
- nReadPos = 0;
- nType = nTypeIn;
- nVersion = nVersionIn;
- state = 0;
- exceptmask = ios::badbit | ios::failbit;
- }
- CDataStream& operator+=(const CDataStream& b)
- {
- vch.insert(vch.end(), b.begin(), b.end());
- return *this;
- }
- friend CDataStream operator+(const CDataStream& a, const CDataStream& b)
- {
- CDataStream ret = a;
- ret += b;
- return (ret);
- }
- string str() const
- {
- return (string(begin(), end()));
- }
- const_iterator begin() const { return vch.begin() + nReadPos; }
- iterator begin() { return vch.begin() + nReadPos; }
- const_iterator end() const { return vch.end(); }
- iterator end() { return vch.end(); }
- size_type size() const { return vch.size() - nReadPos; }
- bool empty() const { return vch.size() == nReadPos; }
- void resize(size_type n, value_type c=0) { vch.resize(n + nReadPos, c); }
- void reserve(size_type n) { vch.reserve(n + nReadPos); }
- const_reference operator[](size_type pos) const { return vch[pos + nReadPos]; }
- reference operator[](size_type pos) { return vch[pos + nReadPos]; }
- void clear() { vch.clear(); nReadPos = 0; }
- iterator insert(iterator it, const char& x=char()) { return vch.insert(it, x); }
- void insert(iterator it, size_type n, const char& x) { vch.insert(it, n, x); }
- void insert(iterator it, const_iterator first, const_iterator last)
- {
- if (it == vch.begin() + nReadPos && last - first <= nReadPos)
- {
- nReadPos -= (last - first);
- memcpy(&vch[nReadPos], &first[0], last - first);
- }
- else
- vch.insert(it, first, last);
- }
- #if !defined(_MSC_VER) || _MSC_VER >= 1300
- void insert(iterator it, const char* first, const char* last)
- {
- insert(it, (const_iterator)first, (const_iterator)last);
- }
- #endif
- iterator erase(iterator it)
- {
- if (it == vch.begin() + nReadPos)
- {
- if (++nReadPos >= vch.size())
- {
- nReadPos = 0;
- return vch.erase(vch.begin(), vch.end());
- }
- return vch.begin() + nReadPos;
- }
- else
- return vch.erase(it);
- }
- iterator erase(iterator first, iterator last)
- {
- if (first == vch.begin() + nReadPos)
- {
- if (last == vch.end())
- {
- nReadPos = 0;
- return vch.erase(vch.begin(), vch.end());
- }
- else
- {
- nReadPos = (last - vch.begin());
- return last;
- }
- }
- else
- return vch.erase(first, last);
- }
- inline void Compact()
- {
- vch.erase(vch.begin(), vch.begin() + nReadPos);
- nReadPos = 0;
- }
- bool Rewind(size_type n)
- {
- if (n > nReadPos)
- return false;
- nReadPos -= n;
- return true;
- }
- void setstate(short bits, const char* psz)
- {
- state |= bits;
- if (state & exceptmask)
- throw std::ios_base::failure(psz);
- }
- bool eof() const { return size() == 0; }
- bool fail() const { return state & (ios::badbit | ios::failbit); }
- bool good() const { return !eof() && (state == 0); }
- void clear(short n) { state = n; }
- short exceptions() { return exceptmask; }
- short exceptions(short mask) { short prev = exceptmask; exceptmask = mask; setstate(0, "CDataStream"); return prev; }
- CDataStream* rdbuf() { return this; }
- int in_avail() { return size(); }
- void SetType(int n) { nType = n; }
- int GetType() { return nType; }
- void SetVersion(int n) { nVersion = n; }
- int GetVersion() { return nVersion; }
- void ReadVersion() { *this >> nVersion; }
- void WriteVersion() { *this << nVersion; }
- CDataStream& read(char* pch, int nSize)
- {
- assert(nSize >= 0);
- unsigned int nReadPosNext = nReadPos + nSize;
- if (nReadPosNext >= vch.size())
- {
- if (nReadPosNext > vch.size())
- {
- setstate(ios::failbit, "CDataStream::read() : end of data");
- memset(pch, 0, nSize);
- nSize = vch.size() - nReadPos;
- }
- memcpy(pch, &vch[nReadPos], nSize);
- nReadPos = 0;
- vch.clear();
- return (*this);
- }
- memcpy(pch, &vch[nReadPos], nSize);
- nReadPos = nReadPosNext;
- return (*this);
- }
- CDataStream& ignore(int nSize)
- {
- assert(nSize >= 0);
- unsigned int nReadPosNext = nReadPos + nSize;
- if (nReadPosNext >= vch.size())
- {
- if (nReadPosNext > vch.size())
- {
- setstate(ios::failbit, "CDataStream::ignore() : end of data");
- nSize = vch.size() - nReadPos;
- }
- nReadPos = 0;
- vch.clear();
- return (*this);
- }
- nReadPos = nReadPosNext;
- return (*this);
- }
- CDataStream& write(const char* pch, int nSize)
- {
- assert(nSize >= 0);
- vch.insert(vch.end(), pch, pch + nSize);
- return (*this);
- }
- template<typename Stream>
- void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const
- {
- if (!vch.empty())
- s.write((char*)&vch[0], vch.size() * sizeof(vch[0]));
- }
- template<typename T>
- unsigned int GetSerializeSize(const T& obj)
- {
- return ::GetSerializeSize(obj, nType, nVersion);
- }
- template<typename T>
- CDataStream& operator<<(const T& obj)
- {
- ::Serialize(*this, obj, nType, nVersion);
- return (*this);
- }
- template<typename T>
- CDataStream& operator>>(T& obj)
- {
- ::Unserialize(*this, obj, nType, nVersion);
- return (*this);
- }
- };
- #ifdef TESTCDATASTREAM
- #include <iostream>
- int main(int argc, char *argv[])
- {
- vector<unsigned char> vch(0xcc, 250);
- printf("CDataStream:\n");
- for (int n = 1000; n <= 4500000; n *= 2)
- {
- CDataStream ss;
- time_t nStart = time(NULL);
- for (int i = 0; i < n; i++)
- ss.write((char*)&vch[0], vch.size());
- printf("n=%-10d %d seconds\n", n, time(NULL) - nStart);
- }
- printf("stringstream:\n");
- for (int n = 1000; n <= 4500000; n *= 2)
- {
- stringstream ss;
- time_t nStart = time(NULL);
- for (int i = 0; i < n; i++)
- ss.write((char*)&vch[0], vch.size());
- printf("n=%-10d %d seconds\n", n, time(NULL) - nStart);
- }
- }
- #endif
- class CAutoFile
- {
- protected:
- FILE* file;
- short state;
- short exceptmask;
- public:
- int nType;
- int nVersion;
- typedef FILE element_type;
- CAutoFile(FILE* filenew=NULL, int nTypeIn=SER_DISK, int nVersionIn=VERSION)
- {
- file = filenew;
- nType = nTypeIn;
- nVersion = nVersionIn;
- state = 0;
- exceptmask = ios::badbit | ios::failbit;
- }
- ~CAutoFile()
- {
- fclose();
- }
- void fclose()
- {
- if (file != NULL && file != stdin && file != stdout && file != stderr)
- ::fclose(file);
- file = NULL;
- }
- FILE* release() { FILE* ret = file; file = NULL; return ret; }
- operator FILE*() { return file; }
- FILE* operator->() { return file; }
- FILE& operator*() { return *file; }
- FILE** operator&() { return &file; }
- FILE* operator=(FILE* pnew) { return file = pnew; }
- bool operator!() { return (file == NULL); }
- void setstate(short bits, const char* psz)
- {
- state |= bits;
- if (state & exceptmask)
- throw std::ios_base::failure(psz);
- }
- bool fail() const { return state & (ios::badbit | ios::failbit); }
- bool good() const { return state == 0; }
- void clear(short n = 0) { state = n; }
- short exceptions() { return exceptmask; }
- short exceptions(short mask) { short prev = exceptmask; exceptmask = mask; setstate(0, "CAutoFile"); return prev; }
- void SetType(int n) { nType = n; }
- int GetType() { return nType; }
- void SetVersion(int n) { nVersion = n; }
- int GetVersion() { return nVersion; }
- void ReadVersion() { *this >> nVersion; }
- void WriteVersion() { *this << nVersion; }
- CAutoFile& read(char* pch, int nSize)
- {
- if (!file)
- throw std::ios_base::failure("CAutoFile::read : file handle is NULL");
- if (fread(pch, 1, nSize, file) != nSize)
- setstate(ios::failbit, feof(file) ? "CAutoFile::read : end of file" : "CAutoFile::read : fread failed");
- return (*this);
- }
- CAutoFile& write(const char* pch, int nSize)
- {
- if (!file)
- throw std::ios_base::failure("CAutoFile::write : file handle is NULL");
- if (fwrite(pch, 1, nSize, file) != nSize)
- setstate(ios::failbit, "CAutoFile::write : write failed");
- return (*this);
- }
- template<typename T>
- unsigned int GetSerializeSize(const T& obj)
- {
- return ::GetSerializeSize(obj, nType, nVersion);
- }
- template<typename T>
- CAutoFile& operator<<(const T& obj)
- {
- if (!file)
- throw std::ios_base::failure("CAutoFile::operator<< : file handle is NULL");
- ::Serialize(*this, obj, nType, nVersion);
- return (*this);
- }
- template<typename T>
- CAutoFile& operator>>(T& obj)
- {
- if (!file)
- throw std::ios_base::failure("CAutoFile::operator>> : file handle is NULL");
- ::Unserialize(*this, obj, nType, nVersion);
- return (*this);
- }
- };
- #include "headers.h"
- #ifdef _MSC_VER
- #include <crtdbg.h>
- #endif
- DEFINE_EVENT_TYPE(wxEVT_CROSSTHREADCALL)
- DEFINE_EVENT_TYPE(wxEVT_REPLY1)
- DEFINE_EVENT_TYPE(wxEVT_REPLY2)
- DEFINE_EVENT_TYPE(wxEVT_REPLY3)
- DEFINE_EVENT_TYPE(wxEVT_TABLEADDED)
- DEFINE_EVENT_TYPE(wxEVT_TABLEUPDATED)
- DEFINE_EVENT_TYPE(wxEVT_TABLEDELETED)
- CMainFrame* pframeMain = NULL;
- map<string, string> mapAddressBook;
- void ThreadRequestProductDetails(void* parg);
- void ThreadRandSendTest(void* parg);
- bool fRandSendTest = false;
- void RandSend();
- void HandleCtrlA(wxKeyEvent& event)
- {
- wxTextCtrl* textCtrl = (wxTextCtrl*)event.GetEventObject();
- if (event.GetModifiers() == wxMOD_CONTROL && event.GetKeyCode() == 'A')
- textCtrl->SetSelection(-1, -1);
- event.Skip();
- }
- bool Is24HourTime()
- {
- return true;
- }
- string DateStr(int64 nTime)
- {
- return (string)wxDateTime((time_t)nTime).FormatDate();
- }
- string DateTimeStr(int64 nTime)
- {
- wxDateTime datetime((time_t)nTime);
- if (Is24HourTime())
- return (string)datetime.Format("%x %H:%M");
- else
- return (string)datetime.Format("%x ") + itostr((datetime.GetHour() + 11) % 12 + 1) + (string)datetime.Format(":%M %p");
- }
- wxString GetItemText(wxListCtrl* listCtrl, int nIndex, int nColumn)
- {
- wxListItem item;
- item.m_itemId = nIndex;
- item.m_col = nColumn;
- item.m_mask = wxLIST_MASK_TEXT;
- if (!listCtrl->GetItem(item))
- return "";
- return item.GetText();
- }
- int InsertLine(wxListCtrl* listCtrl, const wxString& str0, const wxString& str1)
- {
- int nIndex = listCtrl->InsertItem(listCtrl->GetItemCount(), str0);
- listCtrl->SetItem(nIndex, 1, str1);
- return nIndex;
- }
- int InsertLine(wxListCtrl* listCtrl, const wxString& str0, const wxString& str1, const wxString& str2, const wxString& str3, const wxString& str4)
- {
- int nIndex = listCtrl->InsertItem(listCtrl->GetItemCount(), str0);
- listCtrl->SetItem(nIndex, 1, str1);
- listCtrl->SetItem(nIndex, 2, str2);
- listCtrl->SetItem(nIndex, 3, str3);
- listCtrl->SetItem(nIndex, 4, str4);
- return nIndex;
- }
- int InsertLine(wxListCtrl* listCtrl, void* pdata, const wxString& str0, const wxString& str1, const wxString& str2, const wxString& str3, const wxString& str4)
- {
- int nIndex = listCtrl->InsertItem(listCtrl->GetItemCount(), str0);
- listCtrl->SetItemPtrData(nIndex, (wxUIntPtr)pdata);
- listCtrl->SetItem(nIndex, 1, str1);
- listCtrl->SetItem(nIndex, 2, str2);
- listCtrl->SetItem(nIndex, 3, str3);
- listCtrl->SetItem(nIndex, 4, str4);
- return nIndex;
- }
- void SetSelection(wxListCtrl* listCtrl, int nIndex)
- {
- int nSize = listCtrl->GetItemCount();
- long nState = (wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED);
- for (int i = 0; i < nSize; i++)
- listCtrl->SetItemState(i, (i == nIndex ? nState : 0), nState);
- }
- int GetSelection(wxListCtrl* listCtrl)
- {
- int nSize = listCtrl->GetItemCount();
- for (int i = 0; i < nSize; i++)
- if (listCtrl->GetItemState(i, wxLIST_STATE_FOCUSED))
- return i;
- return -1;
- }
- string HtmlEscape(const char* psz, bool fMultiLine=false)
- {
- int len = 0;
- for (const char* p = psz; *p; p++)
- {
- if (*p == '<') len += 4;
- else if (*p == '>') len += 4;
- else if (*p == '&') len += 5;
- else if (*p == '"') len += 6;
- else if (*p == ' ' && p > psz && p[-1] == ' ' && p[1] == ' ') len += 6;
- else if (*p == '\n' && fMultiLine) len += 5;
- else
- len++;
- }
- string str;
- str.reserve(len);
- for (const char* p = psz; *p; p++)
- {
- if (*p == '<') str += "<";
- else if (*p == '>') str += ">";
- else if (*p == '&') str += "&";
- else if (*p == '"') str += """;
- else if (*p == ' ' && p > psz && p[-1] == ' ' && p[1] == ' ') str += " ";
- else if (*p == '\n' && fMultiLine) str += "<br>\n";
- else
- str += *p;
- }
- return str;
- }
- string HtmlEscape(const string& str, bool fMultiLine=false)
- {
- return HtmlEscape(str.c_str(), fMultiLine);
- }
- void AddToMyProducts(CProduct product)
- {
- CProduct& productInsert = mapMyProducts[product.GetHash()];
- productInsert = product;
- InsertLine(pframeMain->m_listCtrlProductsSent, &productInsert,
- product.mapValue["category"],
- product.mapValue["title"].substr(0, 100),
- product.mapValue["description"].substr(0, 100),
- product.mapValue["price"],
- "");
- }
- set<void*> setCallbackAvailable;
- CCriticalSection cs_setCallbackAvailable;
- void AddCallbackAvailable(void* p)
- {
- CRITICAL_BLOCK(cs_setCallbackAvailable)
- setCallbackAvailable.insert(p);
- }
- void RemoveCallbackAvailable(void* p)
- {
- CRITICAL_BLOCK(cs_setCallbackAvailable)
- setCallbackAvailable.erase(p);
- }
- bool IsCallbackAvailable(void* p)
- {
- CRITICAL_BLOCK(cs_setCallbackAvailable)
- return setCallbackAvailable.count(p);
- return false;
- }
- template<typename T>
- void AddPendingCustomEvent(wxEvtHandler* pevthandler, int nEventID, const T pbeginIn, const T pendIn)
- {
- if (!pevthandler)
- return;
- const char* pbegin = (pendIn != pbeginIn) ? &pbeginIn[0] : NULL;
- const char* pend = pbegin + (pendIn - pbeginIn) * sizeof(pbeginIn[0]);
- wxCommandEvent event(nEventID);
- wxString strData(wxChar(0), (pend - pbegin) / sizeof(wxChar) + 1);
- memcpy(&strData[0], pbegin, pend - pbegin);
- event.SetString(strData);
- event.SetInt(pend - pbegin);
- pevthandler->AddPendingEvent(event);
- }
- template<class T>
- void AddPendingCustomEvent(wxEvtHandler* pevthandler, int nEventID, const T& obj)
- {
- CDataStream ss;
- ss << obj;
- AddPendingCustomEvent(pevthandler, nEventID, ss.begin(), ss.end());
- }
- void AddPendingReplyEvent1(void* pevthandler, CDataStream& vRecv)
- {
- if (IsCallbackAvailable(pevthandler))
- AddPendingCustomEvent((wxEvtHandler*)pevthandler, wxEVT_REPLY1, vRecv.begin(), vRecv.end());
- }
- void AddPendingReplyEvent2(void* pevthandler, CDataStream& vRecv)
- {
- if (IsCallbackAvailable(pevthandler))
- AddPendingCustomEvent((wxEvtHandler*)pevthandler, wxEVT_REPLY2, vRecv.begin(), vRecv.end());
- }
- void AddPendingReplyEvent3(void* pevthandler, CDataStream& vRecv)
- {
- if (IsCallbackAvailable(pevthandler))
- AddPendingCustomEvent((wxEvtHandler*)pevthandler, wxEVT_REPLY3, vRecv.begin(), vRecv.end());
- }
- CDataStream GetStreamFromEvent(const wxCommandEvent& event)
- {
- wxString strData = event.GetString();
- return CDataStream(strData.begin(), strData.begin() + event.GetInt(), SER_NETWORK);
- }
- CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent)
- {
- Connect(wxEVT_CROSSTHREADCALL, wxCommandEventHandler(CMainFrame::OnCrossThreadCall), NULL, this);
- fRefreshListCtrl = false;
- fRefreshListCtrlRunning = false;
- fOnSetFocusAddress = false;
- pindexBestLast = NULL;
- m_choiceFilter->SetSelection(0);
- m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + " ");
- m_listCtrl->SetFocus();
- SetIcon(wxICON(bitcoin));
- m_menuOptions->Check(wxID_OPTIONSGENERATEBITCOINS, fGenerateBitcoins);
- m_toolBar->ClearTools();
- wxBitmap bmpSend(wxT("send20"), wxBITMAP_TYPE_RESOURCE);
- bmpSend.SetMask(new wxMask(wxBitmap(wxT("send20mask"), wxBITMAP_TYPE_RESOURCE)));
- m_toolBar->AddTool(wxID_BUTTONSEND, wxT("&Send Coins"), bmpSend, wxNullBitmap, wxITEM_NORMAL, wxEmptyString, wxEmptyString);
- wxBitmap bmpAddressBook(wxT("addressbook20"), wxBITMAP_TYPE_RESOURCE);
- bmpAddressBook.SetMask(new wxMask(wxBitmap(wxT("addressbook20mask"), wxBITMAP_TYPE_RESOURCE)));
- m_toolBar->AddTool(wxID_BUTTONRECEIVE, wxT("&Address Book"), bmpAddressBook, wxNullBitmap, wxITEM_NORMAL, wxEmptyString, wxEmptyString);
- m_toolBar->Realize();
- int nDateWidth = DateTimeStr(1229413914).size() * 6 + 8;
- m_listCtrl->InsertColumn(0, "", wxLIST_FORMAT_LEFT, 0);
- m_listCtrl->InsertColumn(1, "", wxLIST_FORMAT_LEFT, 0);
- m_listCtrl->InsertColumn(2, "Status", wxLIST_FORMAT_LEFT, 90);
- m_listCtrl->InsertColumn(3, "Date", wxLIST_FORMAT_LEFT, nDateWidth);
- m_listCtrl->InsertColumn(4, "Description", wxLIST_FORMAT_LEFT, 409 - nDateWidth);
- m_listCtrl->InsertColumn(5, "Debit", wxLIST_FORMAT_RIGHT, 79);
- m_listCtrl->InsertColumn(6, "Credit", wxLIST_FORMAT_RIGHT, 79);
- int pnWidths[3] = { -100, 81, 286 };
- m_statusBar->SetFieldsCount(3, pnWidths);
- vector<unsigned char> vchPubKey;
- if (CWalletDB("r").ReadDefaultKey(vchPubKey))
- m_textCtrlAddress->SetValue(PubKeyToAddress(vchPubKey));
- RefreshListCtrl();
- }
- CMainFrame::~CMainFrame()
- {
- pframeMain = NULL;
- }
- void Shutdown(void* parg)
- {
- static CCriticalSection cs_Shutdown;
- CRITICAL_BLOCK(cs_Shutdown)
- {
- fShutdown = true;
- nTransactionsUpdated++;
- DBFlush(false);
- StopNode();
- DBFlush(true);
- printf("Bitcoin exiting\n");
- exit(0);
- }
- }
- void CMainFrame::OnClose(wxCloseEvent& event)
- {
- Destroy();
- _beginthread(Shutdown, 0, NULL);
- }
- void CMainFrame::OnMouseEvents(wxMouseEvent& event)
- {
- RandAddSeed();
- RAND_add(&event.m_x, sizeof(event.m_x), 0.25);
- RAND_add(&event.m_y, sizeof(event.m_y), 0.25);
- }
- void CMainFrame::OnListColBeginDrag(wxListEvent& event)
- {
- if (event.GetColumn() <= 1 && !fDebug)
- event.Veto();
- }
- void CMainFrame::InsertLine(bool fNew, int nIndex, uint256 hashKey, string strSort, const wxString& str2, const wxString& str3, const wxString& str4, const wxString& str5, const wxString& str6)
- {
- string str0 = strSort;
- long nData = *(long*)&hashKey;
- if (fNew)
- {
- nIndex = m_listCtrl->InsertItem(0, str0);
- }
- else
- {
- if (nIndex == -1)
- {
- while ((nIndex = m_listCtrl->FindItem(nIndex, nData)) != -1)
- if (GetItemText(m_listCtrl, nIndex, 1) == hashKey.ToString())
- break;
- if (nIndex == -1)
- {
- printf("CMainFrame::InsertLine : Couldn't find item to be updated\n");
- return;
- }
- }
- if (GetItemText(m_listCtrl, nIndex, 0) != str0)
- {
- m_listCtrl->DeleteItem(nIndex);
- nIndex = m_listCtrl->InsertItem(0, str0);
- }
- }
- m_listCtrl->SetItem(nIndex, 1, hashKey.ToString());
- m_listCtrl->SetItem(nIndex, 2, str2);
- m_listCtrl->SetItem(nIndex, 3, str3);
- m_listCtrl->SetItem(nIndex, 4, str4);
- m_listCtrl->SetItem(nIndex, 5, str5);
- m_listCtrl->SetItem(nIndex, 6, str6);
- m_listCtrl->SetItemData(nIndex, nData);
- }
- string FormatTxStatus(const CWalletTx& wtx)
- {
- int nDepth = wtx.GetDepthInMainChain();
- if (!wtx.IsFinal())
- return strprintf("Open for %d blocks", nBestHeight - wtx.nLockTime);
- else if (nDepth < 6)
- return strprintf("%d/unconfirmed", nDepth);
- else
- return strprintf("%d blocks", nDepth);
- }
- void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
- {
- int64 nTime = wtx.nTimeDisplayed = wtx.GetTxTime();
- int64 nCredit = wtx.GetCredit();
- int64 nDebit = wtx.GetDebit();
- int64 nNet = nCredit - nDebit;
- uint256 hash = wtx.GetHash();
- string strStatus = FormatTxStatus(wtx);
- map<string, string> mapValue = wtx.mapValue;
- CBlockIndex* pindex = NULL;
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(wtx.hashBlock);
- if (mi != mapBlockIndex.end())
- pindex = (*mi).second;
- string strSort = strprintf("%010d-%01d-%010u",
- (pindex ? pindex->nHeight : INT_MAX),
- (wtx.IsCoinBase() ? 1 : 0),
- wtx.nTimeReceived);
- if (nNet > 0 || wtx.IsCoinBase())
- {
- string strDescription;
- if (wtx.IsCoinBase())
- {
- strDescription = "Generated";
- if (nCredit == 0)
- {
- int64 nUnmatured = 0;
- foreach(const CTxOut& txout, wtx.vout)
- nUnmatured += txout.GetCredit();
- if (wtx.IsInMainChain())
- strDescription += strprintf(" (%s matures in %d blocks)", FormatMoney(nUnmatured).c_str(), wtx.GetBlocksToMaturity());
- else
- strDescription += " (not accepted)";
- }
- }
- else if (!mapValue["from"].empty() || !mapValue["message"].empty())
- {
- if (!mapValue["from"].empty())
- strDescription += "From: " + mapValue["from"];
- if (!mapValue["message"].empty())
- {
- if (!strDescription.empty())
- strDescription += " - ";
- strDescription += mapValue["message"];
- }
- }
- else
- {
- foreach(const CTxOut& txout, wtx.vout)
- {
- if (txout.IsMine())
- {
- vector<unsigned char> vchPubKey;
- if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey))
- {
- string strAddress = PubKeyToAddress(vchPubKey);
- if (mapAddressBook.count(strAddress))
- {
- strDescription += "Received with: ";
- if (!mapAddressBook[strAddress].empty())
- strDescription += mapAddressBook[strAddress] + " ";
- strDescription += strAddress;
- }
- }
- break;
- }
- }
- }
- string strDescription2;
- foreach(int c, strDescription)
- if (c >= ' ')
- strDescription2 += c;
- InsertLine(fNew, nIndex, hash, strSort,
- strStatus,
- nTime ? DateTimeStr(nTime) : "",
- strDescription2,
- "",
- FormatMoney(nNet, true));
- }
- else
- {
- bool fAllFromMe = true;
- foreach(const CTxIn& txin, wtx.vin)
- fAllFromMe = fAllFromMe && txin.IsMine();
- bool fAllToMe = true;
- foreach(const CTxOut& txout, wtx.vout)
- fAllToMe = fAllToMe && txout.IsMine();
- if (fAllFromMe && fAllToMe)
- {
- int64 nValue = wtx.vout[0].nValue;
- InsertLine(fNew, nIndex, hash, strSort,
- strStatus,
- nTime ? DateTimeStr(nTime) : "",
- "Payment to yourself",
- FormatMoney(nNet - nValue, true),
- FormatMoney(nValue, true));
- }
- else if (fAllFromMe)
- {
- int64 nTxFee = nDebit - wtx.GetValueOut();
- for (int nOut = 0; nOut < wtx.vout.size(); nOut++)
- {
- const CTxOut& txout = wtx.vout[nOut];
- if (txout.IsMine())
- continue;
- string strAddress;
- if (!mapValue["to"].empty())
- {
- strAddress = mapValue["to"];
- }
- else
- {
- uint160 hash160;
- if (ExtractHash160(txout.scriptPubKey, hash160))
- strAddress = Hash160ToAddress(hash160);
- }
- string strDescription = "To: ";
- if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
- strDescription += mapAddressBook[strAddress] + " ";
- strDescription += strAddress;
- if (!mapValue["message"].empty())
- {
- if (!strDescription.empty())
- strDescription += " - ";
- strDescription += mapValue["message"];
- }
- string strDescription2;
- foreach(int c, strDescription)
- if (c >= ' ')
- strDescription2 += c;
- int64 nValue = txout.nValue;
- if (nOut == 0 && nTxFee > 0)
- nValue += nTxFee;
- InsertLine(fNew, nIndex, hash, strprintf("%s-%d", strSort.c_str(), nOut),
- strStatus,
- nTime ? DateTimeStr(nTime) : "",
- strDescription2,
- FormatMoney(-nValue, true),
- "");
- }
- }
- else
- {
- bool fAllMine = true;
- foreach(const CTxOut& txout, wtx.vout)
- fAllMine = fAllMine && txout.IsMine();
- foreach(const CTxIn& txin, wtx.vin)
- fAllMine = fAllMine && txin.IsMine();
- InsertLine(fNew, nIndex, hash, strSort,
- strStatus,
- nTime ? DateTimeStr(nTime) : "",
- "",
- FormatMoney(nNet, true),
- "");
- }
- }
- }
- void CMainFrame::RefreshStatus()
- {
- static int nLastTop;
- int nTop = m_listCtrl->GetTopItem();
- if (nTop == nLastTop && pindexBestLast == pindexBest)
- return;
- TRY_CRITICAL_BLOCK(cs_mapWallet)
- {
- int nStart = nTop;
- int nEnd = min(nStart + 100, m_listCtrl->GetItemCount());
- if (pindexBestLast == pindexBest)
- {
- if (nStart >= nLastTop && nStart < nLastTop + 100)
- nStart = nLastTop + 100;
- if (nEnd >= nLastTop && nEnd < nLastTop + 100)
- nEnd = nLastTop;
- }
- nLastTop = nTop;
- pindexBestLast = pindexBest;
- for (int nIndex = nStart; nIndex < nEnd; nIndex++)
- {
- uint256 hash((string)GetItemText(m_listCtrl, nIndex, 1));
- map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
- if (mi == mapWallet.end())
- {
- printf("CMainFrame::RefreshStatus() : tx not found in mapWallet\n");
- continue;
- }
- const CWalletTx& wtx = (*mi).second;
- if (wtx.IsCoinBase() || wtx.GetTxTime() != wtx.nTimeDisplayed)
- InsertTransaction(wtx, false, nIndex);
- else
- m_listCtrl->SetItem(nIndex, 2, FormatTxStatus(wtx));
- }
- }
- }
- void CMainFrame::RefreshListCtrl()
- {
- fRefreshListCtrl = true;
- ::wxWakeUpIdle();
- }
- void CMainFrame::OnIdle(wxIdleEvent& event)
- {
- if (fRefreshListCtrl)
- {
- bool fEntered = false;
- vector<pair<unsigned int, uint256> > vSorted;
- TRY_CRITICAL_BLOCK(cs_mapWallet)
- {
- printf("RefreshListCtrl starting\n");
- fEntered = true;
- fRefreshListCtrl = false;
- vWalletUpdated.clear();
- vSorted.reserve(mapWallet.size());
- for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
- {
- const CWalletTx& wtx = (*it).second;
- unsigned int nTime = UINT_MAX - wtx.GetTxTime();
- vSorted.push_back(make_pair(nTime, (*it).first));
- }
- m_listCtrl->DeleteAllItems();
- }
- if (!fEntered)
- return;
- sort(vSorted.begin(), vSorted.end());
- for (int i = 0; i < vSorted.size();)
- {
- if (fShutdown)
- return;
- bool fEntered = false;
- TRY_CRITICAL_BLOCK(cs_mapWallet)
- {
- fEntered = true;
- uint256& hash = vSorted[i++].second;
- map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
- if (mi != mapWallet.end())
- InsertTransaction((*mi).second, true);
- }
- if (!fEntered || i == 100 || i % 500 == 0)
- wxYield();
- }
- printf("RefreshListCtrl done\n");
- }
- else
- {
- static int64 nLastTime;
- if (GetTime() > nLastTime + 30)
- {
- TRY_CRITICAL_BLOCK(cs_mapWallet)
- {
- nLastTime = GetTime();
- for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
- {
- CWalletTx& wtx = (*it).second;
- if (wtx.nTimeDisplayed && wtx.nTimeDisplayed != wtx.GetTxTime())
- InsertTransaction(wtx, false);
- }
- }
- }
- }
- }
- void CMainFrame::OnPaint(wxPaintEvent& event)
- {
- event.Skip();
- }
- void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
- {
- if (!vWalletUpdated.empty())
- {
- TRY_CRITICAL_BLOCK(cs_mapWallet)
- {
- pair<uint256, bool> item;
- foreach(item, vWalletUpdated)
- {
- bool fNew = item.second;
- map<uint256, CWalletTx>::iterator mi = mapWallet.find(item.first);
- if (mi != mapWallet.end())
- {
- printf("vWalletUpdated: %s %s\n", (*mi).second.GetHash().ToString().substr(0,6).c_str(), fNew ? "new" : "");
- InsertTransaction((*mi).second, fNew);
- }
- }
- m_listCtrl->ScrollList(0, INT_MAX);
- vWalletUpdated.clear();
- }
- }
- RefreshStatus();
- string strGen = "";
- if (fGenerateBitcoins)
- strGen = " Generating";
- if (fGenerateBitcoins && vNodes.empty())
- strGen = "(not connected)";
- m_statusBar->SetStatusText(strGen, 1);
- string strStatus = strprintf(" %d connections %d blocks %d transactions", vNodes.size(), nBestHeight + 1, m_listCtrl->GetItemCount());
- m_statusBar->SetStatusText(strStatus, 2);
- TRY_CRITICAL_BLOCK(cs_mapWallet)
- m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + " ");
- m_listCtrl->OnPaint(event);
- }
- void CrossThreadCall(wxCommandEvent& event)
- {
- if (pframeMain)
- pframeMain->GetEventHandler()->AddPendingEvent(event);
- }
- void CrossThreadCall(int nID, void* pdata)
- {
- wxCommandEvent event;
- event.SetInt(nID);
- event.SetClientData(pdata);
- if (pframeMain)
- pframeMain->GetEventHandler()->AddPendingEvent(event);
- }
- void CMainFrame::OnCrossThreadCall(wxCommandEvent& event)
- {
- void* pdata = event.GetClientData();
- switch (event.GetInt())
- {
- case UICALL_ADDORDER:
- {
- break;
- }
- case UICALL_UPDATEORDER:
- {
- break;
- }
- }
- }
- void CMainFrame::OnMenuFileExit(wxCommandEvent& event)
- {
- Close(true);
- }
- void CMainFrame::OnMenuOptionsGenerate(wxCommandEvent& event)
- {
- fGenerateBitcoins = event.IsChecked();
- nTransactionsUpdated++;
- CWalletDB().WriteSetting("fGenerateBitcoins", fGenerateBitcoins);
- if (fGenerateBitcoins)
- if (_beginthread(ThreadBitcoinMiner, 0, NULL) == -1)
- printf("Error: _beginthread(ThreadBitcoinMiner) failed\n");
- Refresh();
- wxPaintEvent eventPaint;
- AddPendingEvent(eventPaint);
- }
- void CMainFrame::OnMenuOptionsOptions(wxCommandEvent& event)
- {
- COptionsDialog dialog(this);
- dialog.ShowModal();
- }
- void CMainFrame::OnMenuHelpAbout(wxCommandEvent& event)
- {
- CAboutDialog dialog(this);
- dialog.ShowModal();
- }
- void CMainFrame::OnButtonSend(wxCommandEvent& event)
- {
- if (fRandSendTest)
- {
- RandSend();
- return;
- }
- CSendDialog dialog(this);
- dialog.ShowModal();
- }
- void CMainFrame::OnButtonAddressBook(wxCommandEvent& event)
- {
- CAddressBookDialog dialogAddr(this, "", false);
- if (dialogAddr.ShowModal() == 2)
- {
- CSendDialog dialogSend(this, dialogAddr.GetAddress());
- dialogSend.ShowModal();
- }
- }
- void CMainFrame::OnSetFocusAddress(wxFocusEvent& event)
- {
- m_textCtrlAddress->SetSelection(-1, -1);
- fOnSetFocusAddress = true;
- event.Skip();
- }
- void CMainFrame::OnMouseEventsAddress(wxMouseEvent& event)
- {
- if (fOnSetFocusAddress)
- m_textCtrlAddress->SetSelection(-1, -1);
- fOnSetFocusAddress = false;
- event.Skip();
- }
- void CMainFrame::OnButtonCopy(wxCommandEvent& event)
- {
- if (wxTheClipboard->Open())
- {
- wxTheClipboard->SetData(new wxTextDataObject(m_textCtrlAddress->GetValue()));
- wxTheClipboard->Close();
- }
- }
- void CMainFrame::OnButtonChange(wxCommandEvent& event)
- {
- CYourAddressDialog dialog(this, string(m_textCtrlAddress->GetValue()));
- if (!dialog.ShowModal())
- return;
- string strAddress = (string)dialog.GetAddress();
- if (strAddress != m_textCtrlAddress->GetValue())
- {
- uint160 hash160;
- if (!AddressToHash160(strAddress, hash160))
- return;
- if (!mapPubKeys.count(hash160))
- return;
- CWalletDB().WriteDefaultKey(mapPubKeys[hash160]);
- m_textCtrlAddress->SetValue(strAddress);
- }
- }
- void CMainFrame::OnListItemActivatedAllTransactions(wxListEvent& event)
- {
- uint256 hash((string)GetItemText(m_listCtrl, event.GetIndex(), 1));
- CWalletTx wtx;
- CRITICAL_BLOCK(cs_mapWallet)
- {
- map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
- if (mi == mapWallet.end())
- {
- printf("CMainFrame::OnListItemActivatedAllTransactions() : tx not found in mapWallet\n");
- return;
- }
- wtx = (*mi).second;
- }
- CTxDetailsDialog dialog(this, wtx);
- dialog.ShowModal();
- }
- void CMainFrame::OnListItemActivatedProductsSent(wxListEvent& event)
- {
- CProduct& product = *(CProduct*)event.GetItem().GetData();
- CEditProductDialog* pdialog = new CEditProductDialog(this);
- pdialog->SetProduct(product);
- pdialog->Show();
- }
- void CMainFrame::OnListItemActivatedOrdersSent(wxListEvent& event)
- {
- CWalletTx& order = *(CWalletTx*)event.GetItem().GetData();
- CViewOrderDialog* pdialog = new CViewOrderDialog(this, order, false);
- pdialog->Show();
- }
- void CMainFrame::OnListItemActivatedOrdersReceived(wxListEvent& event)
- {
- CWalletTx& order = *(CWalletTx*)event.GetItem().GetData();
- CViewOrderDialog* pdialog = new CViewOrderDialog(this, order, true);
- pdialog->Show();
- }
- CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetailsDialogBase(parent)
- {
- string strHTML;
- strHTML.reserve(4000);
- int64 nTime = wtx.GetTxTime();
- int64 nCredit = wtx.GetCredit();
- int64 nDebit = wtx.GetDebit();
- int64 nNet = nCredit - nDebit;
- strHTML += "<b>Status:</b> " + FormatTxStatus(wtx) + "<br>";
- strHTML += "<b>Date:</b> " + (nTime ? DateTimeStr(nTime) : "") + "<br>";
- if (wtx.IsCoinBase())
- {
- strHTML += "<b>Source:</b> Generated<br>";
- }
- else if (!wtx.mapValue["from"].empty())
- {
- if (!wtx.mapValue["from"].empty())
- strHTML += "<b>From:</b> " + HtmlEscape(wtx.mapValue["from"]) + "<br>";
- }
- else
- {
- foreach(const CTxOut& txout, wtx.vout)
- {
- if (txout.IsMine())
- {
- vector<unsigned char> vchPubKey;
- if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey))
- {
- string strAddress = PubKeyToAddress(vchPubKey);
- if (mapAddressBook.count(strAddress))
- {
- strHTML += "<b>Received with:</b> ";
- if (!mapAddressBook[strAddress].empty())
- strHTML += mapAddressBook[strAddress] + " ";
- strHTML += HtmlEscape(strAddress);
- strHTML += "<br>";
- }
- }
- break;
- }
- }
- }
- string strAddress;
- if (!wtx.mapValue["to"].empty())
- {
- strAddress = wtx.mapValue["to"];
- strHTML += "<b>To:</b> ";
- if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
- strHTML += mapAddressBook[strAddress] + " ";
- strHTML += HtmlEscape(strAddress) + "<br>";
- }
- if (wtx.IsCoinBase() && nCredit == 0)
- {/
- int64 nUnmatured = 0;
- foreach(const CTxOut& txout, wtx.vout)
- nUnmatured += txout.GetCredit();
- if (wtx.IsInMainChain())
- strHTML += strprintf("<b>Credit:</b> (%s matures in %d blocks)<br>", FormatMoney(nUnmatured).c_str(), wtx.GetBlocksToMaturity());
- else
- strHTML += "<b>Credit:</b> (not accepted)<br>";
- }
- else if (nNet > 0)
- {
- strHTML += "<b>Credit:</b> " + FormatMoney(nNet) + "<br>";
- }
- else
- {
- bool fAllFromMe = true;
- foreach(const CTxIn& txin, wtx.vin)
- fAllFromMe = fAllFromMe && txin.IsMine();
- bool fAllToMe = true;
- foreach(const CTxOut& txout, wtx.vout)
- fAllToMe = fAllToMe && txout.IsMine();
- if (fAllFromMe)
- {
- foreach(const CTxOut& txout, wtx.vout)
- {
- if (txout.IsMine())
- continue;
- string strAddress;
- if (!wtx.mapValue["to"].empty())
- {
- strAddress = wtx.mapValue["to"];
- }
- else
- {
- uint160 hash160;
- if (ExtractHash160(txout.scriptPubKey, hash160))
- strAddress = Hash160ToAddress(hash160);
- }
- strHTML += "<b>Debit:</b> " + FormatMoney(-txout.nValue) + " ";
- strHTML += "(to ";
- if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
- strHTML += mapAddressBook[strAddress] + " ";
- strHTML += strAddress;
- strHTML += ")<br>";
- }
- if (fAllToMe)
- {
- int64 nValue = wtx.vout[0].nValue;
- strHTML += "<b>Debit:</b> " + FormatMoney(-nValue) + "<br>";
- strHTML += "<b>Credit:</b> " + FormatMoney(nValue) + "<br>";
- }
- int64 nTxFee = nDebit - wtx.GetValueOut();
- if (nTxFee > 0)
- strHTML += "<b>Transaction fee:</b> " + FormatMoney(-nTxFee) + "<br>";
- }
- else
- {
- foreach(const CTxIn& txin, wtx.vin)
- if (txin.IsMine())
- strHTML += "<b>Debit:</b> " + FormatMoney(-txin.GetDebit()) + "<br>";
- foreach(const CTxOut& txout, wtx.vout)
- if (txout.IsMine())
- strHTML += "<b>Credit:</b> " + FormatMoney(txout.GetCredit()) + "<br>";
- }
- }
- strHTML += "<b>Net amount:</b> " + FormatMoney(nNet, true) + "<br>";
- if (!wtx.mapValue["message"].empty())
- strHTML += "<br><b>Message:</b><br>" + HtmlEscape(wtx.mapValue["message"], true) + "<br>";
- if (fDebug)
- {
- strHTML += "<hr><br>debug print<br><br>";
- foreach(const CTxIn& txin, wtx.vin)
- if (txin.IsMine())
- strHTML += "<b>Debit:</b> " + FormatMoney(-txin.GetDebit()) + "<br>";
- foreach(const CTxOut& txout, wtx.vout)
- if (txout.IsMine())
- strHTML += "<b>Credit:</b> " + FormatMoney(txout.GetCredit()) + "<br>";
- strHTML += "<b>Inputs:</b><br>";
- CRITICAL_BLOCK(cs_mapWallet)
- {
- foreach(const CTxIn& txin, wtx.vin)
- {
- COutPoint prevout = txin.prevout;
- map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
- if (mi != mapWallet.end())
- {
- const CWalletTx& prev = (*mi).second;
- if (prevout.n < prev.vout.size())
- {
- strHTML += HtmlEscape(prev.ToString(), true);
- strHTML += " " + FormatTxStatus(prev) + ", ";
- strHTML = strHTML + "IsMine=" + (prev.vout[prevout.n].IsMine() ? "true" : "false") + "<br>";
- }
- }
- }
- }
- strHTML += "<br><hr><br><b>Transaction:</b><br>";
- strHTML += HtmlEscape(wtx.ToString(), true);
- }
- string(strHTML.begin(), strHTML.end()).swap(strHTML);
- m_htmlWin->SetPage(strHTML);
- m_buttonOK->SetFocus();
- }
- void CTxDetailsDialog::OnButtonOK(wxCommandEvent& event)
- {
- Close();
- }
- COptionsDialog::COptionsDialog(wxWindow* parent) : COptionsDialogBase(parent)
- {
- m_textCtrlTransactionFee->SetValue(FormatMoney(nTransactionFee));
- m_buttonOK->SetFocus();
- }
- void COptionsDialog::OnKillFocusTransactionFee(wxFocusEvent& event)
- {
- int64 nTmp = nTransactionFee;
- ParseMoney(m_textCtrlTransactionFee->GetValue(), nTmp);
- m_textCtrlTransactionFee->SetValue(FormatMoney(nTmp));
- }
- void COptionsDialog::OnButtonOK(wxCommandEvent& event)
- {
- int64 nPrevTransactionFee = nTransactionFee;
- if (ParseMoney(m_textCtrlTransactionFee->GetValue(), nTransactionFee) && nTransactionFee != nPrevTransactionFee)
- CWalletDB().WriteSetting("nTransactionFee", nTransactionFee);
- Close();
- }
- void COptionsDialog::OnButtonCancel(wxCommandEvent& event)
- {
- Close();
- }
- CAboutDialog::CAboutDialog(wxWindow* parent) : CAboutDialogBase(parent)
- {
- m_staticTextVersion->SetLabel(strprintf("version 0.%d.%d Alpha", VERSION/100, VERSION%100));
- wxString str = m_staticTextMain->GetLabel();
- if (str.Find('Â') != wxNOT_FOUND)
- str.Remove(str.Find('Â'), 1);
- m_staticTextMain->SetLabel(str);
- }
- void CAboutDialog::OnButtonOK(wxCommandEvent& event)
- {
- Close();
- }
- CSendDialog::CSendDialog(wxWindow* parent, const wxString& strAddress) : CSendDialogBase(parent)
- {
- m_textCtrlAddress->SetValue(strAddress);
- m_choiceTransferType->SetSelection(0);
- m_bitmapCheckMark->Show(false);
- wxBitmap bmpSend(wxT("send16"), wxBITMAP_TYPE_RESOURCE);
- bmpSend.SetMask(new wxMask(wxBitmap(wxT("send16masknoshadow"), wxBITMAP_TYPE_RESOURCE)));
- wxIcon iconSend;
- iconSend.CopyFromBitmap(bmpSend);
- SetIcon(iconSend);
- wxCommandEvent event;
- OnTextAddress(event);
- m_buttonPaste->MoveAfterInTabOrder(m_buttonCancel);
- m_buttonAddress->MoveAfterInTabOrder(m_buttonPaste);
- this->Layout();
- }
- void CSendDialog::OnTextAddress(wxCommandEvent& event)
- {
- bool fBitcoinAddress = IsValidBitcoinAddress(m_textCtrlAddress->GetValue());
- m_bitmapCheckMark->Show(fBitcoinAddress);
- bool fEnable = !fBitcoinAddress;
- m_staticTextFrom->Enable(fEnable);
- m_textCtrlFrom->Enable(fEnable);
- m_staticTextMessage->Enable(fEnable);
- m_textCtrlMessage->Enable(fEnable);
- m_textCtrlMessage->SetBackgroundColour(wxSystemSettings::GetColour(fEnable ? wxSYS_COLOUR_WINDOW : wxSYS_COLOUR_BTNFACE));
- }
- void CSendDialog::OnKillFocusAmount(wxFocusEvent& event)
- {
- if (m_textCtrlAmount->GetValue().Trim().empty())
- return;
- int64 nTmp;
- if (ParseMoney(m_textCtrlAmount->GetValue(), nTmp))
- m_textCtrlAmount->SetValue(FormatMoney(nTmp));
- }
- void CSendDialog::OnButtonAddressBook(wxCommandEvent& event)
- {
- CAddressBookDialog dialog(this, m_textCtrlAddress->GetValue(), true);
- if (dialog.ShowModal())
- m_textCtrlAddress->SetValue(dialog.GetAddress());
- }
- void CSendDialog::OnButtonPaste(wxCommandEvent& event)
- {
- if (wxTheClipboard->Open())
- {
- if (wxTheClipboard->IsSupported(wxDF_TEXT))
- {
- wxTextDataObject data;
- wxTheClipboard->GetData(data);
- m_textCtrlAddress->SetValue(data.GetText());
- }
- wxTheClipboard->Close();
- }
- }
- void CSendDialog::OnButtonSend(wxCommandEvent& event)
- {
- CWalletTx wtx;
- string strAddress = (string)m_textCtrlAddress->GetValue();
- int64 nValue = 0;
- if (!ParseMoney(m_textCtrlAmount->GetValue(), nValue) || nValue <= 0)
- {
- wxMessageBox("Error in amount ");
- return;
- }
- if (nValue > GetBalance())
- {
- wxMessageBox("Amount exceeds your balance ");
- return;
- }
- if (nValue + nTransactionFee > GetBalance())
- {
- wxMessageBox(string("Total exceeds your balance when the ") + FormatMoney(nTransactionFee) + " transaction fee is included ");
- return;
- }
- uint160 hash160;
- bool fBitcoinAddress = AddressToHash160(strAddress, hash160);
- if (fBitcoinAddress)
- {
- CScript scriptPubKey;
- scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG;
- if (!SendMoney(scriptPubKey, nValue, wtx))
- return;
- wxMessageBox("Payment sent ", "Sending...");
- }
- else
- {
- CAddress addr(strAddress.c_str());
- if (addr.ip == 0)
- {
- wxMessageBox("Invalid address ");
- return;
- }
- wtx.mapValue["to"] = strAddress;
- wtx.mapValue["from"] = m_textCtrlFrom->GetValue();
- wtx.mapValue["message"] = m_textCtrlMessage->GetValue();
- CSendingDialog* pdialog = new CSendingDialog(this, addr, nValue, wtx);
- if (!pdialog->ShowModal())
- return;
- }
- if (!mapAddressBook.count(strAddress))
- SetAddressBookName(strAddress, "");
- EndModal(true);
- }
- void CSendDialog::OnButtonCancel(wxCommandEvent& event)
- {
- EndModal(false);
- }
- CSendingDialog::CSendingDialog(wxWindow* parent, const CAddress& addrIn, int64 nPriceIn, const CWalletTx& wtxIn) : CSendingDialogBase(NULL)
- {
- addr = addrIn;
- nPrice = nPriceIn;
- wtx = wtxIn;
- start = wxDateTime::UNow();
- strStatus = "";
- fCanCancel = true;
- fAbort = false;
- fSuccess = false;
- fUIDone = false;
- fWorkDone = false;
- SetTitle(strprintf("Sending %s to %s...", FormatMoney(nPrice).c_str(), wtx.mapValue["to"].c_str()));
- m_textCtrlStatus->SetValue("");
- _beginthread(SendingDialogStartTransfer, 0, this);
- }
- CSendingDialog::~CSendingDialog()
- {
- printf("~CSendingDialog()\n");
- }
- void CSendingDialog::Close()
- {
- if (IsModal())
- EndModal(fSuccess);
- else
- Show(false);
- if (fWorkDone)
- Destroy();
- else
- fUIDone = true;
- }
- void CSendingDialog::OnClose(wxCloseEvent& event)
- {
- if (!event.CanVeto() || fWorkDone || fAbort || !fCanCancel)
- {
- Close();
- }
- else
- {
- event.Veto();
- wxCommandEvent cmdevent;
- OnButtonCancel(cmdevent);
- }
- }
- void CSendingDialog::OnButtonOK(wxCommandEvent& event)
- {
- if (fWorkDone)
- Close();
- }
- void CSendingDialog::OnButtonCancel(wxCommandEvent& event)
- {
- if (fCanCancel)
- fAbort = true;
- }
- void CSendingDialog::OnPaint(wxPaintEvent& event)
- {
- if (strStatus.size() > 130)
- m_textCtrlStatus->SetValue(string("\n") + strStatus);
- else
- m_textCtrlStatus->SetValue(string("\n\n") + strStatus);
- m_staticTextSending->SetFocus();
- if (!fCanCancel)
- m_buttonCancel->Enable(false);
- if (fWorkDone)
- {
- m_buttonOK->Enable(true);
- m_buttonOK->SetFocus();
- m_buttonCancel->Enable(false);
- }
- if (fAbort && fCanCancel && IsShown())
- {
- strStatus = "CANCELLED";
- m_buttonOK->Enable(true);
- m_buttonOK->SetFocus();
- m_buttonCancel->Enable(false);
- m_buttonCancel->SetLabel("Cancelled");
- Close();
- wxMessageBox("Transfer cancelled ", "Sending...", wxOK, this);
- }
- event.Skip();
- if (fRandSendTest && fWorkDone && fSuccess)
- {
- Close();
- Sleep(1000);
- RandSend();
- }
- }
- void CSendingDialog::Repaint()
- {
- Refresh();
- wxPaintEvent event;
- AddPendingEvent(event);
- }
- bool CSendingDialog::Status()
- {
- if (fUIDone)
- {
- Destroy();
- return false;
- }
- if (fAbort && fCanCancel)
- {
- strStatus = "CANCELLED";
- Repaint();
- fWorkDone = true;
- return false;
- }
- return true;
- }
- bool CSendingDialog::Status(const string& str)
- {
- if (!Status())
- return false;
- strStatus = str;
- Repaint();
- return true;
- }
- bool CSendingDialog::Error(const string& str)
- {
- fCanCancel = false;
- fWorkDone = true;
- Status(string("Error: ") + str);
- return false;
- }
- void SendingDialogStartTransfer(void* parg)
- {
- ((CSendingDialog*)parg)->StartTransfer();
- }
- void CSendingDialog::StartTransfer()
- {
- if (nPrice + nTransactionFee > GetBalance())
- {
- Error("You don't have enough money");
- return;
- }
- if (!Status("Connecting..."))
- return;
- CNode* pnode = ConnectNode(addr, 5 * 60);
- if (!pnode)
- {
- Error("Unable to connect");
- return;
- }
- if (!Status("Requesting public key..."))
- return;
- pnode->PushRequest("checkorder", wtx, SendingDialogOnReply2, this);
- }
- void SendingDialogOnReply2(void* parg, CDataStream& vRecv)
- {
- ((CSendingDialog*)parg)->OnReply2(vRecv);
- }
- void CSendingDialog::OnReply2(CDataStream& vRecv)
- {
- if (!Status("Received public key..."))
- return;
- CScript scriptPubKey;
- int nRet;
- try
- {
- vRecv >> nRet;
- if (nRet > 0)
- {
- string strMessage;
- vRecv >> strMessage;
- Error("Transfer was not accepted");
- return;
- }
- vRecv >> scriptPubKey;
- }
- catch (...)
- {
- Error("Invalid response received");
- return;
- }
- CNode* pnode = ConnectNode(addr, 5 * 60);
- if (!pnode)
- {
- Error("Lost connection");
- return;
- }
- while (wxDateTime::UNow() < start + wxTimeSpan(0, 0, 0, 2 * 1000))
- {
- Sleep(200);
- if (!Status())
- return;
- }
- CRITICAL_BLOCK(cs_main)
- {
- if (!Status("Creating transaction..."))
- return;
- if (nPrice + nTransactionFee > GetBalance())
- {
- Error("You don't have enough money");
- return;
- }
- int64 nFeeRequired;
- if (!CreateTransaction(scriptPubKey, nPrice, wtx, nFeeRequired))
- {
- if (nPrice + nFeeRequired > GetBalance())
- Error(strprintf("This is an oversized transaction that requires a transaction fee of %s", FormatMoney(nFeeRequired).c_str()));
- else
- Error("Transaction creation failed");
- return;
- }
- Sleep(50);
- if (!Status())
- return;
- fCanCancel = false;
- if (fAbort)
- {
- fCanCancel = true;
- if (!Status())
- return;
- fCanCancel = false;
- }
- if (!Status("Sending payment..."))
- return;
- if (!CommitTransactionSpent(wtx))
- {
- Error("Error finalizing payment");
- return;
- }
- pnode->PushRequest("submitorder", wtx, SendingDialogOnReply3, this);
- if (!wtx.AcceptTransaction())
- printf("ERROR: CSendingDialog : wtxNew.AcceptTransaction() %s failed\n", wtx.GetHash().ToString().c_str());
- wtx.RelayWalletTransaction();
- Status("Waiting for confirmation...");
- MainFrameRepaint();
- }
- }
- void SendingDialogOnReply3(void* parg, CDataStream& vRecv)
- {
- ((CSendingDialog*)parg)->OnReply3(vRecv);
- }
- void CSendingDialog::OnReply3(CDataStream& vRecv)
- {
- int nRet;
- try
- {
- vRecv >> nRet;
- if (nRet > 0)
- {
- Error("The payment was sent, but the recipient was unable to verify it.\n"
- "The transaction is recorded and will credit to the recipient if it is valid,\n"
- "but without comment information.");
- return;
- }
- }
- catch (...)
- {
- Error("Payment was sent, but an invalid response was received");
- return;
- }
- fSuccess = true;
- fWorkDone = true;
- Status("Payment completed");
- }
- CYourAddressDialog::CYourAddressDialog(wxWindow* parent, const string& strInitSelected) : CYourAddressDialogBase(parent)
- {
- m_listCtrl->InsertColumn(0, "Name", wxLIST_FORMAT_LEFT, 200);
- m_listCtrl->InsertColumn(1, "Bitcoin Address", wxLIST_FORMAT_LEFT, 350);
- m_listCtrl->SetFocus();
- CRITICAL_BLOCK(cs_mapKeys)
- {
- foreach(const PAIRTYPE(string, string)& item, mapAddressBook)
- {
- string strAddress = item.first;
- string strName = item.second;
- uint160 hash160;
- bool fMine = (AddressToHash160(strAddress, hash160) && mapPubKeys.count(hash160));
- if (fMine)
- {
- int nIndex = InsertLine(m_listCtrl, strName, strAddress);
- if (strAddress == strInitSelected)
- m_listCtrl->SetItemState(nIndex, wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED, wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED);
- }
- }
- }
- }
- wxString CYourAddressDialog::GetAddress()
- {
- int nIndex = GetSelection(m_listCtrl);
- if (nIndex == -1)
- return "";
- return GetItemText(m_listCtrl, nIndex, 1);
- }
- void CYourAddressDialog::OnListEndLabelEdit(wxListEvent& event)
- {
- if (event.IsEditCancelled())
- return;
- string strAddress = (string)GetItemText(m_listCtrl, event.GetIndex(), 1);
- SetAddressBookName(strAddress, string(event.GetText()));
- pframeMain->RefreshListCtrl();
- }
- void CYourAddressDialog::OnListItemSelected(wxListEvent& event)
- {
- }
- void CYourAddressDialog::OnListItemActivated(wxListEvent& event)
- {
- EndModal(true);
- }
- void CYourAddressDialog::OnButtonRename(wxCommandEvent& event)
- {
- int nIndex = GetSelection(m_listCtrl);
- if (nIndex == -1)
- return;
- string strName = (string)m_listCtrl->GetItemText(nIndex);
- string strAddress = (string)GetItemText(m_listCtrl, nIndex, 1);
- CGetTextFromUserDialog dialog(this, "Rename Bitcoin Address", "New Name", strName);
- if (!dialog.ShowModal())
- return;
- strName = dialog.GetValue();
- SetAddressBookName(strAddress, strName);
- m_listCtrl->SetItemText(nIndex, strName);
- pframeMain->RefreshListCtrl();
- }
- void CYourAddressDialog::OnButtonNew(wxCommandEvent& event)
- {
- CGetTextFromUserDialog dialog(this, "New Bitcoin Address", "Name", "");
- if (!dialog.ShowModal())
- return;
- string strName = dialog.GetValue();
- string strAddress = PubKeyToAddress(GenerateNewKey());
- SetAddressBookName(strAddress, strName);
- int nIndex = InsertLine(m_listCtrl, strName, strAddress);
- SetSelection(m_listCtrl, nIndex);
- m_listCtrl->SetFocus();
- }
- void CYourAddressDialog::OnButtonCopy(wxCommandEvent& event)
- {
- if (wxTheClipboard->Open())
- {
- wxTheClipboard->SetData(new wxTextDataObject(GetAddress()));
- wxTheClipboard->Close();
- }
- }
- void CYourAddressDialog::OnButtonOK(wxCommandEvent& event)
- {
- EndModal(true);
- }
- void CYourAddressDialog::OnButtonCancel(wxCommandEvent& event)
- {
- EndModal(false);
- }
- void CYourAddressDialog::OnClose(wxCloseEvent& event)
- {
- EndModal(false);
- }
- CAddressBookDialog::CAddressBookDialog(wxWindow* parent, const wxString& strInitSelected, bool fSendingIn) : CAddressBookDialogBase(parent)
- {
- fSending = fSendingIn;
- if (!fSending)
- m_buttonCancel->Show(false);
- m_listCtrl->InsertColumn(0, "Name", wxLIST_FORMAT_LEFT, 200);
- m_listCtrl->InsertColumn(1, "Address", wxLIST_FORMAT_LEFT, 350);
- m_listCtrl->SetFocus();
- wxBitmap bmpAddressBook(wxT("addressbook16"), wxBITMAP_TYPE_RESOURCE);
- bmpAddressBook.SetMask(new wxMask(wxBitmap(wxT("addressbook16mask"), wxBITMAP_TYPE_RESOURCE)));
- wxIcon iconAddressBook;
- iconAddressBook.CopyFromBitmap(bmpAddressBook);
- SetIcon(iconAddressBook);
- CRITICAL_BLOCK(cs_mapKeys)
- {
- foreach(const PAIRTYPE(string, string)& item, mapAddressBook)
- {
- string strAddress = item.first;
- string strName = item.second;
- uint160 hash160;
- bool fMine = (AddressToHash160(strAddress, hash160) && mapPubKeys.count(hash160));
- if (!fMine)
- {
- int nIndex = InsertLine(m_listCtrl, strName, strAddress);
- if (strAddress == strInitSelected)
- m_listCtrl->SetItemState(nIndex, wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED, wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED);
- }
- }
- }
- }
- wxString CAddressBookDialog::GetAddress()
- {
- int nIndex = GetSelection(m_listCtrl);
- if (nIndex == -1)
- return "";
- return GetItemText(m_listCtrl, nIndex, 1);
- }
- void CAddressBookDialog::OnListEndLabelEdit(wxListEvent& event)
- {
- if (event.IsEditCancelled())
- return;
- string strAddress = (string)GetItemText(m_listCtrl, event.GetIndex(), 1);
- SetAddressBookName(strAddress, string(event.GetText()));
- pframeMain->RefreshListCtrl();
- }
- void CAddressBookDialog::OnListItemSelected(wxListEvent& event)
- {
- }
- void CAddressBookDialog::OnListItemActivated(wxListEvent& event)
- {
- if (fSending)
- {
- EndModal(GetAddress() != "" ? 2 : 0);
- }
- else
- {
- wxCommandEvent event;
- OnButtonEdit(event);
- }
- }
- void CAddressBookDialog::OnButtonEdit(wxCommandEvent& event)
- {
- int nIndex = GetSelection(m_listCtrl);
- if (nIndex == -1)
- return;
- string strName = (string)m_listCtrl->GetItemText(nIndex);
- string strAddress = (string)GetItemText(m_listCtrl, nIndex, 1);
- string strAddressOrg = strAddress;
- CGetTextFromUserDialog dialog(this, "Edit Address", "Name", strName, "Address", strAddress);
- if (!dialog.ShowModal())
- return;
- strName = dialog.GetValue1();
- strAddress = dialog.GetValue2();
- if (strAddress != strAddressOrg)
- CWalletDB().EraseName(strAddressOrg);
- SetAddressBookName(strAddress, strName);
- m_listCtrl->SetItem(nIndex, 1, strAddress);
- m_listCtrl->SetItemText(nIndex, strName);
- pframeMain->RefreshListCtrl();
- }
- void CAddressBookDialog::OnButtonNew(wxCommandEvent& event)
- {
- CGetTextFromUserDialog dialog(this, "New Address", "Name", "", "Address", "");
- if (!dialog.ShowModal())
- return;
- string strName = dialog.GetValue1();
- string strAddress = dialog.GetValue2();
- SetAddressBookName(strAddress, strName);
- int nIndex = InsertLine(m_listCtrl, strName, strAddress);
- SetSelection(m_listCtrl, nIndex);
- m_listCtrl->SetFocus();
- }
- void CAddressBookDialog::OnButtonDelete(wxCommandEvent& event)
- {
- for (int nIndex = m_listCtrl->GetItemCount()-1; nIndex >= 0; nIndex--)
- {
- if (m_listCtrl->GetItemState(nIndex, wxLIST_STATE_SELECTED))
- {
- string strAddress = (string)GetItemText(m_listCtrl, nIndex, 1);
- CWalletDB().EraseName(strAddress);
- m_listCtrl->DeleteItem(nIndex);
- }
- }
- pframeMain->RefreshListCtrl();
- }
- void CAddressBookDialog::OnButtonCopy(wxCommandEvent& event)
- {
- if (wxTheClipboard->Open())
- {
- wxTheClipboard->SetData(new wxTextDataObject(GetAddress()));
- wxTheClipboard->Close();
- }
- }
- void CAddressBookDialog::OnButtonOK(wxCommandEvent& event)
- {
- EndModal(GetAddress() != "" ? 1 : 0);
- }
- void CAddressBookDialog::OnButtonCancel(wxCommandEvent& event)
- {
- EndModal(0);
- }
- void CAddressBookDialog::OnClose(wxCloseEvent& event)
- {
- EndModal(0);
- }
- bool CompareIntStringPairBestFirst(const pair<int, string>& item1, const pair<int, string>& item2)
- {
- return (item1.first > item2.first);
- }
- CProductsDialog::CProductsDialog(wxWindow* parent) : CProductsDialogBase(parent)
- {
- m_listCtrl->InsertColumn(0, "Title", wxLIST_FORMAT_LEFT, 200);
- m_listCtrl->InsertColumn(1, "Price", wxLIST_FORMAT_LEFT, 80);
- m_listCtrl->InsertColumn(2, "Seller", wxLIST_FORMAT_LEFT, 80);
- m_listCtrl->InsertColumn(3, "Stars", wxLIST_FORMAT_LEFT, 50);
- m_listCtrl->InsertColumn(4, "Power", wxLIST_FORMAT_LEFT, 50);
- map<string, int> mapTopCategories;
- CRITICAL_BLOCK(cs_mapProducts)
- for (map<uint256, CProduct>::iterator mi = mapProducts.begin(); mi != mapProducts.end(); ++mi)
- mapTopCategories[(*mi).second.mapValue["category"]]++;
- vector<pair<int, string> > vTopCategories;
- for (map<string, int>::iterator mi = mapTopCategories.begin(); mi != mapTopCategories.end(); ++mi)
- vTopCategories.push_back(make_pair((*mi).second, (*mi).first));
- sort(vTopCategories.begin(), vTopCategories.end(), CompareIntStringPairBestFirst);
- int nLimit = 250;
- for (vector<pair<int, string> >::iterator it = vTopCategories.begin(); it != vTopCategories.end() && nLimit-- > 0; ++it)
- m_comboBoxCategory->Append((*it).second);
- }
- void CProductsDialog::OnCombobox(wxCommandEvent& event)
- {
- OnButtonSearch(event);
- }
- bool CompareProductsBestFirst(const CProduct* p1, const CProduct* p2)
- {
- return (p1->nAtoms > p2->nAtoms);
- }
- void CProductsDialog::OnButtonSearch(wxCommandEvent& event)
- {
- string strCategory = (string)m_comboBoxCategory->GetValue();
- string strSearch = (string)m_textCtrlSearch->GetValue();
- vector<CProduct*> vProductsFound;
- CRITICAL_BLOCK(cs_mapProducts)
- {
- for (map<uint256, CProduct>::iterator mi = mapProducts.begin(); mi != mapProducts.end(); ++mi)
- {
- CProduct& product = (*mi).second;
- if (product.mapValue["category"].find(strCategory) != -1)
- {
- if (product.mapValue["title"].find(strSearch) != -1 ||
- product.mapValue["description"].find(strSearch) != -1 ||
- product.mapValue["seller"].find(strSearch) != -1)
- {
- vProductsFound.push_back(&product);
- }
- }
- }
- }
- sort(vProductsFound.begin(), vProductsFound.end(), CompareProductsBestFirst);
- foreach(CProduct* pproduct, vProductsFound)
- {
- InsertLine(m_listCtrl,
- pproduct->mapValue["title"],
- pproduct->mapValue["price"],
- pproduct->mapValue["seller"],
- pproduct->mapValue["stars"],
- itostr(pproduct->nAtoms));
- }
- }
- void CProductsDialog::OnListItemActivated(wxListEvent& event)
- {
- CViewProductDialog* pdialog = new CViewProductDialog(this, m_vProduct[event.GetIndex()]);
- pdialog->Show();
- }
- CEditProductDialog::CEditProductDialog(wxWindow* parent) : CEditProductDialogBase(parent)
- {
- m_textCtrlLabel[0 ] = m_textCtrlLabel0;
- m_textCtrlLabel[1 ] = m_textCtrlLabel1;
- m_textCtrlLabel[2 ] = m_textCtrlLabel2;
- m_textCtrlLabel[3 ] = m_textCtrlLabel3;
- m_textCtrlLabel[4 ] = m_textCtrlLabel4;
- m_textCtrlLabel[5 ] = m_textCtrlLabel5;
- m_textCtrlLabel[6 ] = m_textCtrlLabel6;
- m_textCtrlLabel[7 ] = m_textCtrlLabel7;
- m_textCtrlLabel[8 ] = m_textCtrlLabel8;
- m_textCtrlLabel[9 ] = m_textCtrlLabel9;
- m_textCtrlLabel[10] = m_textCtrlLabel10;
- m_textCtrlLabel[11] = m_textCtrlLabel11;
- m_textCtrlLabel[12] = m_textCtrlLabel12;
- m_textCtrlLabel[13] = m_textCtrlLabel13;
- m_textCtrlLabel[14] = m_textCtrlLabel14;
- m_textCtrlLabel[15] = m_textCtrlLabel15;
- m_textCtrlLabel[16] = m_textCtrlLabel16;
- m_textCtrlLabel[17] = m_textCtrlLabel17;
- m_textCtrlLabel[18] = m_textCtrlLabel18;
- m_textCtrlLabel[19] = m_textCtrlLabel19;
- m_textCtrlField[0 ] = m_textCtrlField0;
- m_textCtrlField[1 ] = m_textCtrlField1;
- m_textCtrlField[2 ] = m_textCtrlField2;
- m_textCtrlField[3 ] = m_textCtrlField3;
- m_textCtrlField[4 ] = m_textCtrlField4;
- m_textCtrlField[5 ] = m_textCtrlField5;
- m_textCtrlField[6 ] = m_textCtrlField6;
- m_textCtrlField[7 ] = m_textCtrlField7;
- m_textCtrlField[8 ] = m_textCtrlField8;
- m_textCtrlField[9 ] = m_textCtrlField9;
- m_textCtrlField[10] = m_textCtrlField10;
- m_textCtrlField[11] = m_textCtrlField11;
- m_textCtrlField[12] = m_textCtrlField12;
- m_textCtrlField[13] = m_textCtrlField13;
- m_textCtrlField[14] = m_textCtrlField14;
- m_textCtrlField[15] = m_textCtrlField15;
- m_textCtrlField[16] = m_textCtrlField16;
- m_textCtrlField[17] = m_textCtrlField17;
- m_textCtrlField[18] = m_textCtrlField18;
- m_textCtrlField[19] = m_textCtrlField19;
- m_buttonDel[0 ] = m_buttonDel0;
- m_buttonDel[1 ] = m_buttonDel1;
- m_buttonDel[2 ] = m_buttonDel2;
- m_buttonDel[3 ] = m_buttonDel3;
- m_buttonDel[4 ] = m_buttonDel4;
- m_buttonDel[5 ] = m_buttonDel5;
- m_buttonDel[6 ] = m_buttonDel6;
- m_buttonDel[7 ] = m_buttonDel7;
- m_buttonDel[8 ] = m_buttonDel8;
- m_buttonDel[9 ] = m_buttonDel9;
- m_buttonDel[10] = m_buttonDel10;
- m_buttonDel[11] = m_buttonDel11;
- m_buttonDel[12] = m_buttonDel12;
- m_buttonDel[13] = m_buttonDel13;
- m_buttonDel[14] = m_buttonDel14;
- m_buttonDel[15] = m_buttonDel15;
- m_buttonDel[16] = m_buttonDel16;
- m_buttonDel[17] = m_buttonDel17;
- m_buttonDel[18] = m_buttonDel18;
- m_buttonDel[19] = m_buttonDel19;
- for (int i = 1; i < FIELDS_MAX; i++)
- ShowLine(i, false);
- LayoutAll();
- }
- void CEditProductDialog::LayoutAll()
- {
- m_scrolledWindow->Layout();
- m_scrolledWindow->GetSizer()->Fit(m_scrolledWindow);
- this->Layout();
- }
- void CEditProductDialog::ShowLine(int i, bool fShow)
- {
- m_textCtrlLabel[i]->Show(fShow);
- m_textCtrlField[i]->Show(fShow);
- m_buttonDel[i]->Show(fShow);
- }
- void CEditProductDialog::OnButtonDel0(wxCommandEvent& event) { OnButtonDel(event, 0); }
- void CEditProductDialog::OnButtonDel1(wxCommandEvent& event) { OnButtonDel(event, 1); }
- void CEditProductDialog::OnButtonDel2(wxCommandEvent& event) { OnButtonDel(event, 2); }
- void CEditProductDialog::OnButtonDel3(wxCommandEvent& event) { OnButtonDel(event, 3); }
- void CEditProductDialog::OnButtonDel4(wxCommandEvent& event) { OnButtonDel(event, 4); }
- void CEditProductDialog::OnButtonDel5(wxCommandEvent& event) { OnButtonDel(event, 5); }
- void CEditProductDialog::OnButtonDel6(wxCommandEvent& event) { OnButtonDel(event, 6); }
- void CEditProductDialog::OnButtonDel7(wxCommandEvent& event) { OnButtonDel(event, 7); }
- void CEditProductDialog::OnButtonDel8(wxCommandEvent& event) { OnButtonDel(event, 8); }
- void CEditProductDialog::OnButtonDel9(wxCommandEvent& event) { OnButtonDel(event, 9); }
- void CEditProductDialog::OnButtonDel10(wxCommandEvent& event) { OnButtonDel(event, 10); }
- void CEditProductDialog::OnButtonDel11(wxCommandEvent& event) { OnButtonDel(event, 11); }
- void CEditProductDialog::OnButtonDel12(wxCommandEvent& event) { OnButtonDel(event, 12); }
- void CEditProductDialog::OnButtonDel13(wxCommandEvent& event) { OnButtonDel(event, 13); }
- void CEditProductDialog::OnButtonDel14(wxCommandEvent& event) { OnButtonDel(event, 14); }
- void CEditProductDialog::OnButtonDel15(wxCommandEvent& event) { OnButtonDel(event, 15); }
- void CEditProductDialog::OnButtonDel16(wxCommandEvent& event) { OnButtonDel(event, 16); }
- void CEditProductDialog::OnButtonDel17(wxCommandEvent& event) { OnButtonDel(event, 17); }
- void CEditProductDialog::OnButtonDel18(wxCommandEvent& event) { OnButtonDel(event, 18); }
- void CEditProductDialog::OnButtonDel19(wxCommandEvent& event) { OnButtonDel(event, 19); }
- void CEditProductDialog::OnButtonDel(wxCommandEvent& event, int n)
- {
- Freeze();
- int x, y;
- m_scrolledWindow->GetViewStart(&x, &y);
- int i;
- for (i = n; i < FIELDS_MAX-1; i++)
- {
- m_textCtrlLabel[i]->SetValue(m_textCtrlLabel[i+1]->GetValue());
- m_textCtrlField[i]->SetValue(m_textCtrlField[i+1]->GetValue());
- if (!m_buttonDel[i+1]->IsShown())
- break;
- }
- m_textCtrlLabel[i]->SetValue("");
- m_textCtrlField[i]->SetValue("");
- ShowLine(i, false);
- m_buttonAddField->Enable(true);
- LayoutAll();
- m_scrolledWindow->Scroll(0, y);
- Thaw();
- }
- void CEditProductDialog::OnButtonAddField(wxCommandEvent& event)
- {
- for (int i = 0; i < FIELDS_MAX; i++)
- {
- if (!m_buttonDel[i]->IsShown())
- {
- Freeze();
- ShowLine(i, true);
- if (i == FIELDS_MAX-1)
- m_buttonAddField->Enable(false);
- LayoutAll();
- m_scrolledWindow->Scroll(0, 99999);
- Thaw();
- break;
- }
- }
- }
- void CEditProductDialog::OnButtonSend(wxCommandEvent& event)
- {
- CProduct product;
- GetProduct(product);
- product.vchPubKeyFrom = keyUser.GetPubKey();
- if (!keyUser.Sign(product.GetSigHash(), product.vchSig))
- {
- wxMessageBox("Error digitally signing the product ");
- return;
- }
- AddToMyProducts(product);
- product.mapDetails.clear();
- product.vOrderForm.clear();
- if (!keyUser.Sign(product.GetSigHash(), product.vchSig))
- {
- wxMessageBox("Error digitally signing the product ");
- return;
- }
- if (!product.CheckProduct())
- {
- wxMessageBox("Errors found in product ");
- return;
- }
- AdvertStartPublish(pnodeLocalHost, MSG_PRODUCT, 0, product);
- Destroy();
- }
- void CEditProductDialog::OnButtonPreview(wxCommandEvent& event)
- {
- CProduct product;
- GetProduct(product);
- CViewProductDialog* pdialog = new CViewProductDialog(this, product);
- pdialog->Show();
- }
- void CEditProductDialog::OnButtonCancel(wxCommandEvent& event)
- {
- Destroy();
- }
- void CEditProductDialog::SetProduct(const CProduct& productIn)
- {
- CProduct product = productIn;
- m_comboBoxCategory->SetValue(product.mapValue["category"]);
- m_textCtrlTitle->SetValue(product.mapValue["title"]);
- m_textCtrlPrice->SetValue(product.mapValue["price"]);
- m_textCtrlDescription->SetValue(product.mapValue["description"]);
- m_textCtrlInstructions->SetValue(product.mapValue["instructions"]);
- for (int i = 0; i < FIELDS_MAX; i++)
- {
- bool fUsed = i < product.vOrderForm.size();
- m_buttonDel[i]->Show(fUsed);
- m_textCtrlLabel[i]->Show(fUsed);
- m_textCtrlField[i]->Show(fUsed);
- if (!fUsed)
- continue;
- m_textCtrlLabel[i]->SetValue(product.vOrderForm[i].first);
- string strControl = product.vOrderForm[i].second;
- if (strControl.substr(0, 5) == "text=")
- m_textCtrlField[i]->SetValue("");
- else if (strControl.substr(0, 7) == "choice=")
- m_textCtrlField[i]->SetValue(strControl.substr(7));
- else
- m_textCtrlField[i]->SetValue(strControl);
- }
- }
- void CEditProductDialog::GetProduct(CProduct& product)
- {
- product.mapValue["category"] = m_comboBoxCategory->GetValue().Trim();
- product.mapValue["title"] = m_textCtrlTitle->GetValue().Trim();
- product.mapValue["price"] = m_textCtrlPrice->GetValue().Trim();
- product.mapValue["description"] = m_textCtrlDescription->GetValue().Trim();
- product.mapValue["instructions"] = m_textCtrlInstructions->GetValue().Trim();
- for (int i = 0; i < FIELDS_MAX; i++)
- {
- if (m_buttonDel[i]->IsShown())
- {
- string strLabel = (string)m_textCtrlLabel[i]->GetValue().Trim();
- string strControl = (string)m_textCtrlField[i]->GetValue();
- if (strControl.empty())
- strControl = "text=";
- else
- strControl = "choice=" + strControl;
- product.vOrderForm.push_back(make_pair(strLabel, strControl));
- }
- }
- }
- CViewProductDialog::CViewProductDialog(wxWindow* parent, const CProduct& productIn) : CViewProductDialogBase(parent)
- {
- Connect(wxEVT_REPLY1, wxCommandEventHandler(CViewProductDialog::OnReply1), NULL, this);
- AddCallbackAvailable(GetEventHandler());
- product = productIn;
- UpdateProductDisplay(false);
- m_buttonBack->Enable(false);
- m_buttonNext->Enable(!product.vOrderForm.empty());
- m_htmlWinReviews->Show(true);
- m_scrolledWindow->Show(false);
- this->Layout();
- _beginthread(ThreadRequestProductDetails, 0, new pair<CProduct, wxEvtHandler*>(product, GetEventHandler()));
- }
- CViewProductDialog::~CViewProductDialog()
- {
- RemoveCallbackAvailable(GetEventHandler());
- }
- void ThreadRequestProductDetails(void* parg)
- {
- pair<CProduct, wxEvtHandler*>* pitem = (pair<CProduct, wxEvtHandler*>*)parg;
- CProduct product = pitem->first;
- wxEvtHandler* pevthandler = pitem->second;
- delete pitem;
- CNode* pnode = ConnectNode(product.addr, 5 * 60);
- if (!pnode)
- {
- CDataStream ssEmpty;
- AddPendingReplyEvent1(pevthandler, ssEmpty);
- return;
- }
- pnode->PushRequest("getdetails", product.GetHash(), AddPendingReplyEvent1, (void*)pevthandler);
- }
- void CViewProductDialog::OnReply1(wxCommandEvent& event)
- {
- CDataStream ss = GetStreamFromEvent(event);
- if (ss.empty())
- {
- product.mapValue["description"] = "-- CAN'T CONNECT TO SELLER --\n";
- UpdateProductDisplay(true);
- return;
- }
- int nRet;
- CProduct product2;
- try
- {
- ss >> nRet;
- if (nRet > 0)
- throw false;
- ss >> product2;
- if (product2.GetHash() != product.GetHash())
- throw false;
- if (!product2.CheckSignature())
- throw false;
- }
- catch (...)
- {
- product.mapValue["description"] = "-- INVALID RESPONSE --\n";
- UpdateProductDisplay(true);
- return;
- }
- product = product2;
- UpdateProductDisplay(true);
- }
- bool CompareReviewsBestFirst(const CReview* p1, const CReview* p2)
- {
- return (p1->nAtoms > p2->nAtoms);
- }
- void CViewProductDialog::UpdateProductDisplay(bool fDetails)
- {
- string strHTML;
- strHTML.reserve(4000);
- strHTML += "<html>\n"
- "<head>\n"
- "<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n"
- "</head>\n"
- "<body>\n";
- strHTML += "<b>Category:</b> " + HtmlEscape(product.mapValue["category"]) + "<br>\n";
- strHTML += "<b>Title:</b> " + HtmlEscape(product.mapValue["title"]) + "<br>\n";
- strHTML += "<b>Price:</b> " + HtmlEscape(product.mapValue["price"]) + "<br>\n";
- if (!fDetails)
- strHTML += "<b>Loading details...</b><br>\n<br>\n";
- else
- strHTML += HtmlEscape(product.mapValue["description"], true) + "<br>\n<br>\n";
- strHTML += "<b>Reviews:</b><br>\n<br>\n";
- if (!product.vchPubKeyFrom.empty())
- {
- CReviewDB reviewdb("r");
- vector<CReview> vReviews;
- reviewdb.ReadReviews(product.GetUserHash(), vReviews);
- vector<CReview*> vSortedReviews;
- vSortedReviews.reserve(vReviews.size());
- for (vector<CReview>::reverse_iterator it = vReviews.rbegin(); it != vReviews.rend(); ++it)
- {
- CReview& review = *it;
- CUser user;
- reviewdb.ReadUser(review.GetUserHash(), user);
- review.nAtoms = user.GetAtomCount();
- vSortedReviews.push_back(&review);
- }
- reviewdb.Close();
- stable_sort(vSortedReviews.begin(), vSortedReviews.end(), CompareReviewsBestFirst);
- foreach(CReview* preview, vSortedReviews)
- {
- CReview& review = *preview;
- int nStars = atoi(review.mapValue["stars"].c_str());
- if (nStars < 1 || nStars > 5)
- continue;
- strHTML += "<b>" + itostr(nStars) + (nStars == 1 ? " star" : " stars") + "</b>";
- strHTML += " ";
- strHTML += DateStr(atoi64(review.mapValue["date"])) + "<br>\n";
- strHTML += HtmlEscape(review.mapValue["review"], true);
- strHTML += "<br>\n<br>\n";
- }
- }
- strHTML += "</body>\n</html>\n";
- string(strHTML.begin(), strHTML.end()).swap(strHTML);
- m_htmlWinReviews->SetPage(strHTML);
- if (product.vOrderForm.empty())
- return;
- m_staticTextInstructions->SetLabel(product.mapValue["instructions"]);
- for (int i = 0; i < FIELDS_MAX; i++)
- {
- m_staticTextLabel[i] = NULL;
- m_textCtrlField[i] = NULL;
- m_choiceField[i] = NULL;
- }
- wxBoxSizer* bSizer21 = (wxBoxSizer*)m_scrolledWindow->GetSizer();
- wxFlexGridSizer* fgSizer;
- fgSizer = new wxFlexGridSizer(0, 2, 0, 0);
- fgSizer->AddGrowableCol(1);
- fgSizer->SetFlexibleDirection(wxBOTH);
- fgSizer->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
- wxWindow* windowLast = NULL;
- for (int i = 0; i < product.vOrderForm.size(); i++)
- {
- string strLabel = product.vOrderForm[i].first;
- string strControl = product.vOrderForm[i].second;
- if (strLabel.size() < 20)
- strLabel.insert(strLabel.begin(), 20 - strLabel.size(), ' ');
- m_staticTextLabel[i] = new wxStaticText(m_scrolledWindow, wxID_ANY, strLabel, wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT);
- m_staticTextLabel[i]->Wrap(-1);
- fgSizer->Add(m_staticTextLabel[i], 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5);
- if (strControl.substr(0, 5) == "text=")
- {
- m_textCtrlField[i] = new wxTextCtrl(m_scrolledWindow, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);
- fgSizer->Add(m_textCtrlField[i], 1, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5);
- windowLast = m_textCtrlField[i];
- }
- else if (strControl.substr(0, 7) == "choice=")
- {
- vector<string> vChoices;
- ParseString(strControl.substr(7), ',', vChoices);
- wxArrayString arraystring;
- foreach(const string& str, vChoices)
- arraystring.Add(str);
- m_choiceField[i] = new wxChoice(m_scrolledWindow, wxID_ANY, wxDefaultPosition, wxDefaultSize, arraystring, 0);
- fgSizer->Add(m_choiceField[i], 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
- windowLast = m_choiceField[i];
- }
- else
- {
- m_textCtrlField[i] = new wxTextCtrl(m_scrolledWindow, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);
- fgSizer->Add(m_textCtrlField[i], 1, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5);
- m_staticTextLabel[i]->Show(false);
- m_textCtrlField[i]->Show(false);
- }
- }
- bSizer21->Insert(2, fgSizer, 0, wxEXPAND|wxRIGHT|wxLEFT, 5);
- m_scrolledWindow->Layout();
- bSizer21->Fit(m_scrolledWindow);
- this->Layout();
- m_buttonSubmitForm->MoveAfterInTabOrder(windowLast);
- m_buttonCancelForm->MoveAfterInTabOrder(m_buttonSubmitForm);
- this->Layout();
- }
- void CViewProductDialog::GetOrder(CWalletTx& wtx)
- {
- wtx.SetNull();
- for (int i = 0; i < product.vOrderForm.size(); i++)
- {
- string strValue;
- if (m_textCtrlField[i])
- strValue = m_textCtrlField[i]->GetValue().Trim();
- else
- strValue = m_choiceField[i]->GetStringSelection();
- wtx.vOrderForm.push_back(make_pair(m_staticTextLabel[i]->GetLabel(), strValue));
- }
- }
- void CViewProductDialog::OnButtonSubmitForm(wxCommandEvent& event)
- {
- m_buttonSubmitForm->Enable(false);
- m_buttonCancelForm->Enable(false);
- CWalletTx wtx;
- GetOrder(wtx);
- CSendingDialog* pdialog = new CSendingDialog(this, product.addr, atoi64(product.mapValue["price"]), wtx);
- if (!pdialog->ShowModal())
- {
- m_buttonSubmitForm->Enable(true);
- m_buttonCancelForm->Enable(true);
- return;
- }
- }
- void CViewProductDialog::OnButtonCancelForm(wxCommandEvent& event)
- {
- Destroy();
- }
- void CViewProductDialog::OnButtonBack(wxCommandEvent& event)
- {
- Freeze();
- m_htmlWinReviews->Show(true);
- m_scrolledWindow->Show(false);
- m_buttonBack->Enable(false);
- m_buttonNext->Enable(!product.vOrderForm.empty());
- this->Layout();
- Thaw();
- }
- void CViewProductDialog::OnButtonNext(wxCommandEvent& event)
- {
- if (!product.vOrderForm.empty())
- {
- Freeze();
- m_htmlWinReviews->Show(false);
- m_scrolledWindow->Show(true);
- m_buttonBack->Enable(true);
- m_buttonNext->Enable(false);
- this->Layout();
- Thaw();
- }
- }
- void CViewProductDialog::OnButtonCancel(wxCommandEvent& event)
- {
- Destroy();
- }
- CViewOrderDialog::CViewOrderDialog(wxWindow* parent, CWalletTx order, bool fReceived) : CViewOrderDialogBase(parent)
- {
- int64 nPrice = (fReceived ? order.GetCredit() : order.GetDebit());
- string strHTML;
- strHTML.reserve(4000);
- strHTML += "<html>\n"
- "<head>\n"
- "<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n"
- "</head>\n"
- "<body>\n";
- strHTML += "<b>Time:</b> " + HtmlEscape(DateTimeStr(order.nTimeReceived)) + "<br>\n";
- strHTML += "<b>Price:</b> " + HtmlEscape(FormatMoney(nPrice)) + "<br>\n";
- strHTML += "<b>Status:</b> " + HtmlEscape(FormatTxStatus(order)) + "<br>\n";
- strHTML += "<table>\n";
- for (int i = 0; i < order.vOrderForm.size(); i++)
- {
- strHTML += " <tr><td><b>" + HtmlEscape(order.vOrderForm[i].first) + ":</b></td>";
- strHTML += "<td>" + HtmlEscape(order.vOrderForm[i].second) + "</td></tr>\n";
- }
- strHTML += "</table>\n";
- strHTML += "</body>\n</html>\n";
- string(strHTML.begin(), strHTML.end()).swap(strHTML);
- m_htmlWin->SetPage(strHTML);
- }
- void CViewOrderDialog::OnButtonOK(wxCommandEvent& event)
- {
- Destroy();
- }
- CEditReviewDialog::CEditReviewDialog(wxWindow* parent) : CEditReviewDialogBase(parent)
- {
- }
- void CEditReviewDialog::OnButtonSubmit(wxCommandEvent& event)
- {
- if (m_choiceStars->GetSelection() == -1)
- {
- wxMessageBox("Please select a rating ");
- return;
- }
- CReview review;
- GetReview(review);
- review.vchPubKeyFrom = keyUser.GetPubKey();
- if (!keyUser.Sign(review.GetSigHash(), review.vchSig))
- {
- wxMessageBox("Unable to digitally sign the review ");
- return;
- }
- if (!review.AcceptReview())
- {
- wxMessageBox("Save failed ");
- return;
- }
- RelayMessage(CInv(MSG_REVIEW, review.GetHash()), review);
- Destroy();
- }
- void CEditReviewDialog::OnButtonCancel(wxCommandEvent& event)
- {
- Destroy();
- }
- void CEditReviewDialog::GetReview(CReview& review)
- {
- review.mapValue["time"] = i64tostr(GetAdjustedTime());
- review.mapValue["stars"] = itostr(m_choiceStars->GetSelection()+1);
- review.mapValue["review"] = m_textCtrlReview->GetValue();
- }
- class CMyApp: public wxApp
- {
- public:
- CMyApp(){};
- ~CMyApp(){};
- bool OnInit();
- bool OnInit2();
- int OnExit();
- virtual bool OnExceptionInMainLoop();
- virtual void OnUnhandledException();
- virtual void OnFatalException();
- };
- IMPLEMENT_APP(CMyApp)
- bool CMyApp::OnInit()
- {
- try
- {
- return OnInit2();
- }
- catch (std::exception& e) {
- PrintException(&e, "OnInit()");
- } catch (...) {
- PrintException(NULL, "OnInit()");
- }
- return false;
- }
- map<string, string> ParseParameters(int argc, char* argv[])
- {
- map<string, string> mapArgs;
- for (int i = 0; i < argc; i++)
- {
- char psz[10000];
- strcpy(psz, argv[i]);
- char* pszValue = "";
- if (strchr(psz, '='))
- {
- pszValue = strchr(psz, '=');
- *pszValue++ = '\0';
- }
- strlwr(psz);
- if (psz[0] == '-')
- psz[0] = '/';
- mapArgs[psz] = pszValue;
- }
- return mapArgs;
- }
- bool CMyApp::OnInit2()
- {
- #ifdef _MSC_VER
- _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
- _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
- #endif
- printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
- printf("Bitcoin CMyApp::OnInit()\n");
- wxString strMutexName = wxString("Bitcoin.") + getenv("HOMEPATH");
- for (int i = 0; i < strMutexName.size(); i++)
- if (!isalnum(strMutexName[i]))
- strMutexName[i] = '.';
- wxSingleInstanceChecker* psingleinstancechecker = new wxSingleInstanceChecker(strMutexName);
- if (psingleinstancechecker->IsAnotherRunning())
- {
- printf("Existing instance found\n");
- unsigned int nStart = GetTime();
- loop
- {
- HWND hwndPrev = FindWindow("wxWindowClassNR", "Bitcoin");
- if (hwndPrev)
- {
- if (IsIconic(hwndPrev))
- ShowWindow(hwndPrev, SW_RESTORE);
- SetForegroundWindow(hwndPrev);
- return false;
- }
- if (GetTime() > nStart + 60)
- return false;
- delete psingleinstancechecker;
- Sleep(1000);
- psingleinstancechecker = new wxSingleInstanceChecker(strMutexName);
- if (!psingleinstancechecker->IsAnotherRunning())
- break;
- }
- }
- wxImage::AddHandler(new wxPNGHandler);
- map<string, string> mapArgs = ParseParameters(argc, argv);
- if (mapArgs.count("/datadir"))
- strSetDataDir = mapArgs["/datadir"];
- if (mapArgs.count("/proxy"))
- addrProxy = CAddress(mapArgs["/proxy"].c_str());
- if (mapArgs.count("/debug"))
- fDebug = true;
- if (mapArgs.count("/dropmessages"))
- {
- nDropMessagesTest = atoi(mapArgs["/dropmessages"]);
- if (nDropMessagesTest == 0)
- nDropMessagesTest = 20;
- }
- if (mapArgs.count("/loadblockindextest"))
- {
- CTxDB txdb("r");
- txdb.LoadBlockIndex();
- PrintBlockTree();
- ExitProcess(0);
- }
- string strErrors;
- int64 nStart, nEnd;
- printf("Loading addresses...\n");
- QueryPerformanceCounter((LARGE_INTEGER*)&nStart);
- if (!LoadAddresses())
- strErrors += "Error loading addr.dat \n";
- QueryPerformanceCounter((LARGE_INTEGER*)&nEnd);
- printf(" addresses %20I64d\n", nEnd - nStart);
- printf("Loading block index...\n");
- QueryPerformanceCounter((LARGE_INTEGER*)&nStart);
- if (!LoadBlockIndex())
- strErrors += "Error loading blkindex.dat \n";
- QueryPerformanceCounter((LARGE_INTEGER*)&nEnd);
- printf(" block index %20I64d\n", nEnd - nStart);
- printf("Loading wallet...\n");
- QueryPerformanceCounter((LARGE_INTEGER*)&nStart);
- if (!LoadWallet())
- strErrors += "Error loading wallet.dat \n";
- QueryPerformanceCounter((LARGE_INTEGER*)&nEnd);
- printf(" wallet %20I64d\n", nEnd - nStart);
- printf("Done loading\n");
- printf("mapBlockIndex.size() = %d\n", mapBlockIndex.size());
- printf("nBestHeight = %d\n", nBestHeight);
- printf("mapKeys.size() = %d\n", mapKeys.size());
- printf("mapPubKeys.size() = %d\n", mapPubKeys.size());
- printf("mapWallet.size() = %d\n", mapWallet.size());
- printf("mapAddressBook.size() = %d\n", mapAddressBook.size());
- if (!strErrors.empty())
- {
- wxMessageBox(strErrors);
- OnExit();
- return false;
- }
- ReacceptWalletTransactions();
- if (mapArgs.count("/printblockindex") || mapArgs.count("/printblocktree"))
- {
- PrintBlockTree();
- OnExit();
- return false;
- }
- if (mapArgs.count("/gen"))
- {
- if (mapArgs["/gen"].empty())
- fGenerateBitcoins = true;
- else
- fGenerateBitcoins = atoi(mapArgs["/gen"].c_str());
- }
- {
- pframeMain = new CMainFrame(NULL);
- pframeMain->Show();
- if (!StartNode(strErrors))
- wxMessageBox(strErrors);
- if (fGenerateBitcoins)
- if (_beginthread(ThreadBitcoinMiner, 0, NULL) == -1)
- printf("Error: _beginthread(ThreadBitcoinMiner) failed\n");
- if (argc >= 2 && stricmp(argv[1], "/send") == 0)
- {
- int64 nValue = 1;
- if (argc >= 3)
- ParseMoney(argv[2], nValue);
- string strAddress;
- if (argc >= 4)
- strAddress = argv[3];
- CAddress addr(strAddress.c_str());
- CWalletTx wtx;
- wtx.mapValue["to"] = strAddress;
- wtx.mapValue["from"] = addrLocalHost.ToString();
- wtx.mapValue["message"] = "command line send";
- CSendingDialog* pdialog = new CSendingDialog(pframeMain, addr, nValue, wtx);
- if (!pdialog->ShowModal())
- return false;
- }
- if (mapArgs.count("/randsendtest"))
- {
- if (!mapArgs["/randsendtest"].empty())
- _beginthread(ThreadRandSendTest, 0, new string(mapArgs["/randsendtest"]));
- else
- fRandSendTest = true;
- fDebug = true;
- }
- }
- return true;
- }
- int CMyApp::OnExit()
- {
- Shutdown(NULL);
- return wxApp::OnExit();
- }
- bool CMyApp::OnExceptionInMainLoop()
- {
- try
- {
- throw;
- }
- catch (std::exception& e)
- {
- PrintException(&e, "CMyApp::OnExceptionInMainLoop()");
- wxLogWarning(_T("Exception %s %s"), typeid(e).name(), e.what());
- Sleep(1000);
- throw;
- }
- catch (...)
- {
- PrintException(NULL, "CMyApp::OnExceptionInMainLoop()");
- wxLogWarning(_T("Unknown exception"));
- Sleep(1000);
- throw;
- }
- return true;
- }
- void CMyApp::OnUnhandledException()
- {
- try
- {
- throw;
- }
- catch (std::exception& e)
- {
- PrintException(&e, "CMyApp::OnUnhandledException()");
- wxLogWarning(_T("Exception %s %s"), typeid(e).name(), e.what());
- Sleep(1000);
- throw;
- }
- catch (...)
- {
- PrintException(NULL, "CMyApp::OnUnhandledException()");
- wxLogWarning(_T("Unknown exception"));
- Sleep(1000);
- throw;
- }
- }
- void CMyApp::OnFatalException()
- {
- wxMessageBox("Program has crashed and will terminate. ", "", wxOK | wxICON_ERROR);
- }
- void MainFrameRepaint()
- {
- if (pframeMain)
- {
- printf("MainFrameRepaint()\n");
- wxPaintEvent event;
- pframeMain->Refresh();
- pframeMain->AddPendingEvent(event);
- }
- }
- void ThreadRandSendTest(void* parg)
- {
- string strAddress = *(string*)parg;
- uint160 hash160;
- if (!AddressToHash160(strAddress, hash160))
- {
- wxMessageBox(strprintf("ThreadRandSendTest: Bitcoin address '%s' not valid ", strAddress.c_str()));
- return;
- }
- loop
- {
- Sleep(GetRand(30) * 1000 + 100);
- CWalletTx wtx;
- wtx.mapValue["to"] = strAddress;
- wtx.mapValue["from"] = addrLocalHost.ToString();
- static int nRep;
- wtx.mapValue["message"] = strprintf("randsendtest %d\n", ++nRep);
- int64 nValue = (GetRand(9) + 1) * 100 * CENT;
- if (GetBalance() < nValue)
- {
- wxMessageBox("Out of money ");
- return;
- }
- nValue += (nRep % 100) * CENT;
- CScript scriptPubKey;
- scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG;
- if (!SendMoney(scriptPubKey, nValue, wtx))
- return;
- }
- }
- void RandSend()
- {
- CWalletTx wtx;
- while (vNodes.empty())
- Sleep(1000);
- CAddress addr;
- CRITICAL_BLOCK(cs_vNodes)
- addr = vNodes[GetRand(vNodes.size())]->addr;
- wtx.mapValue["to"] = addr.ToString();
- wtx.mapValue["from"] = addrLocalHost.ToString();
- static int nRep;
- wtx.mapValue["message"] = strprintf("randsendtest %d\n", ++nRep);
- int64 nValue = (GetRand(999) + 1) * CENT;
- if (GetBalance() < nValue)
- {
- wxMessageBox("Out of money ");
- return;
- }
- CSendingDialog* pdialog = new CSendingDialog(pframeMain, addr, nValue, wtx);
- if (!pdialog->Show())
- wxMessageBox("ShowModal Failed ");
- }
- DECLARE_EVENT_TYPE(wxEVT_CROSSTHREADCALL, -1)
- DECLARE_EVENT_TYPE(wxEVT_REPLY1, -1)
- DECLARE_EVENT_TYPE(wxEVT_REPLY2, -1)
- DECLARE_EVENT_TYPE(wxEVT_REPLY3, -1)
- DECLARE_EVENT_TYPE(wxEVT_TABLEADDED, -1)
- DECLARE_EVENT_TYPE(wxEVT_TABLEUPDATED, -1)
- DECLARE_EVENT_TYPE(wxEVT_TABLEDELETED, -1)
- enum
- {
- UICALL_ADDORDER = 1,
- UICALL_UPDATEORDER,
- };
- extern void HandleCtrlA(wxKeyEvent& event);
- extern string DateTimeStr(int64 nTime);
- extern string FormatTxStatus(const CWalletTx& wtx);
- extern void CrossThreadCall(int nID, void* pdata);
- extern void MainFrameRepaint();
- class CMainFrame : public CMainFrameBase
- {
- protected:
- void OnClose(wxCloseEvent& event);
- void OnMouseEvents(wxMouseEvent& event);
- void OnKeyDown(wxKeyEvent& event) { HandleCtrlA(event); }
- void OnIdle(wxIdleEvent& event);
- void OnPaint(wxPaintEvent& event);
- void OnPaintListCtrl(wxPaintEvent& event);
- void OnMenuFileExit(wxCommandEvent& event);
- void OnMenuOptionsGenerate(wxCommandEvent& event);
- void OnMenuOptionsOptions(wxCommandEvent& event);
- void OnMenuHelpAbout(wxCommandEvent& event);
- void OnButtonSend(wxCommandEvent& event);
- void OnButtonAddressBook(wxCommandEvent& event);
- void OnSetFocusAddress(wxFocusEvent& event);
- void OnMouseEventsAddress(wxMouseEvent& event);
- void OnButtonCopy(wxCommandEvent& event);
- void OnButtonChange(wxCommandEvent& event);
- void OnListColBeginDrag(wxListEvent& event);
- void OnListItemActivatedAllTransactions(wxListEvent& event);
- void OnListItemActivatedProductsSent(wxListEvent& event);
- void OnListItemActivatedOrdersSent(wxListEvent& event);
- void OnListItemActivatedOrdersReceived(wxListEvent& event);
- public:
- CMainFrame(wxWindow* parent);
- ~CMainFrame();
- bool fRefreshListCtrl;
- bool fRefreshListCtrlRunning;
- bool fOnSetFocusAddress;
- CBlockIndex* pindexBestLast;
- set<uint256> setUnmaturedDisplayed;
- void OnCrossThreadCall(wxCommandEvent& event);
- 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);
- void InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex=-1);
- void RefreshListCtrl();
- void RefreshStatus();
- };
- class CTxDetailsDialog : public CTxDetailsDialogBase
- {
- protected:
- void OnButtonOK(wxCommandEvent& event);
- public:
- CTxDetailsDialog(wxWindow* parent, CWalletTx wtx);
- CWalletTx wtx;
- };
- class COptionsDialog : public COptionsDialogBase
- {
- protected:
- void OnKillFocusTransactionFee(wxFocusEvent& event);
- void OnButtonOK(wxCommandEvent& event);
- void OnButtonCancel(wxCommandEvent& event);
- public:
- COptionsDialog(wxWindow* parent);
- };
- class CAboutDialog : public CAboutDialogBase
- {
- protected:
- void OnButtonOK(wxCommandEvent& event);
- public:
- CAboutDialog(wxWindow* parent);
- };
- class CSendDialog : public CSendDialogBase
- {
- protected:
- void OnKeyDown(wxKeyEvent& event) { HandleCtrlA(event); }
- void OnTextAddress(wxCommandEvent& event);
- void OnKillFocusAmount(wxFocusEvent& event);
- void OnButtonAddressBook(wxCommandEvent& event);
- void OnButtonPaste(wxCommandEvent& event);
- void OnButtonSend(wxCommandEvent& event);
- void OnButtonCancel(wxCommandEvent& event);
- public:
- CSendDialog(wxWindow* parent, const wxString& strAddress="");
- };
- class CSendingDialog : public CSendingDialogBase
- {
- public:
- void OnClose(wxCloseEvent& event);
- void OnButtonOK(wxCommandEvent& event);
- void OnButtonCancel(wxCommandEvent& event);
- void OnPaint(wxPaintEvent& event);
- public:
- CSendingDialog(wxWindow* parent, const CAddress& addrIn, int64 nPriceIn, const CWalletTx& wtxIn);
- ~CSendingDialog();
- CAddress addr;
- int64 nPrice;
- CWalletTx wtx;
- wxDateTime start;
- string strStatus;
- bool fCanCancel;
- bool fAbort;
- bool fSuccess;
- bool fUIDone;
- bool fWorkDone;
- void Close();
- void Repaint();
- bool Status();
- bool Status(const string& str);
- bool Error(const string& str);
- void StartTransfer();
- void OnReply2(CDataStream& vRecv);
- void OnReply3(CDataStream& vRecv);
- };
- void SendingDialogStartTransfer(void* parg);
- void SendingDialogOnReply2(void* parg, CDataStream& vRecv);
- void SendingDialogOnReply3(void* parg, CDataStream& vRecv);
- class CYourAddressDialog : public CYourAddressDialogBase
- {
- protected:
- void OnListEndLabelEdit(wxListEvent& event);
- void OnListItemSelected(wxListEvent& event);
- void OnListItemActivated(wxListEvent& event);
- void OnButtonRename(wxCommandEvent& event);
- void OnButtonNew(wxCommandEvent& event);
- void OnButtonCopy(wxCommandEvent& event);
- void OnButtonOK(wxCommandEvent& event);
- void OnButtonCancel(wxCommandEvent& event);
- void OnClose(wxCloseEvent& event);
- public:
- CYourAddressDialog(wxWindow* parent);
- CYourAddressDialog(wxWindow* parent, const string& strInitSelected);
- wxString GetAddress();
- };
- class CAddressBookDialog : public CAddressBookDialogBase
- {
- protected:
- void OnListEndLabelEdit(wxListEvent& event);
- void OnListItemSelected(wxListEvent& event);
- void OnListItemActivated(wxListEvent& event);
- void OnButtonEdit(wxCommandEvent& event);
- void OnButtonDelete(wxCommandEvent& event);
- void OnButtonNew(wxCommandEvent& event);
- void OnButtonCopy(wxCommandEvent& event);
- void OnButtonOK(wxCommandEvent& event);
- void OnButtonCancel(wxCommandEvent& event);
- void OnClose(wxCloseEvent& event);
- public:
- CAddressBookDialog(wxWindow* parent, const wxString& strInitSelected, bool fSendingIn);
- bool fSending;
- wxString GetAddress();
- };
- class CProductsDialog : public CProductsDialogBase
- {
- protected:
- void OnKeyDown(wxKeyEvent& event) { HandleCtrlA(event); }
- void OnCombobox(wxCommandEvent& event);
- void OnButtonSearch(wxCommandEvent& event);
- void OnListItemActivated(wxListEvent& event);
- public:
- CProductsDialog(wxWindow* parent);
- vector<CProduct> m_vProduct;
- };
- class CEditProductDialog : public CEditProductDialogBase
- {
- protected:
- void OnKeyDown(wxKeyEvent& event) { HandleCtrlA(event); }
- void OnButtonDel0(wxCommandEvent& event);
- void OnButtonDel1(wxCommandEvent& event);
- void OnButtonDel2(wxCommandEvent& event);
- void OnButtonDel3(wxCommandEvent& event);
- void OnButtonDel4(wxCommandEvent& event);
- void OnButtonDel5(wxCommandEvent& event);
- void OnButtonDel6(wxCommandEvent& event);
- void OnButtonDel7(wxCommandEvent& event);
- void OnButtonDel8(wxCommandEvent& event);
- void OnButtonDel9(wxCommandEvent& event);
- void OnButtonDel10(wxCommandEvent& event);
- void OnButtonDel11(wxCommandEvent& event);
- void OnButtonDel12(wxCommandEvent& event);
- void OnButtonDel13(wxCommandEvent& event);
- void OnButtonDel14(wxCommandEvent& event);
- void OnButtonDel15(wxCommandEvent& event);
- void OnButtonDel16(wxCommandEvent& event);
- void OnButtonDel17(wxCommandEvent& event);
- void OnButtonDel18(wxCommandEvent& event);
- void OnButtonDel19(wxCommandEvent& event);
- void OnButtonAddField(wxCommandEvent& event);
- void OnButtonSend(wxCommandEvent& event);
- void OnButtonPreview(wxCommandEvent& event);
- void OnButtonCancel(wxCommandEvent& event);
- public:
- CEditProductDialog(wxWindow* parent);
- enum { FIELDS_MAX = 20 };
- wxTextCtrl* m_textCtrlLabel[FIELDS_MAX];
- wxTextCtrl* m_textCtrlField[FIELDS_MAX];
- wxButton* m_buttonDel[FIELDS_MAX];
- void LayoutAll();
- void ShowLine(int i, bool fShow=true);
- void OnButtonDel(wxCommandEvent& event, int n);
- void SetProduct(const CProduct& productIn);
- void GetProduct(CProduct& product);
- };
- class CViewProductDialog : public CViewProductDialogBase
- {
- protected:
- void OnButtonSubmitForm(wxCommandEvent& event);
- void OnButtonCancelForm(wxCommandEvent& event);
- void OnButtonBack(wxCommandEvent& event);
- void OnButtonNext(wxCommandEvent& event);
- void OnButtonCancel(wxCommandEvent& event);
- public:
- CViewProductDialog(wxWindow* parent, const CProduct& productIn);
- ~CViewProductDialog();
- CProduct product;
- enum { FIELDS_MAX = 20 };
- wxStaticText* m_staticTextLabel[FIELDS_MAX];
- wxTextCtrl* m_textCtrlField[FIELDS_MAX];
- wxChoice* m_choiceField[FIELDS_MAX];
- void GetOrder(CWalletTx& order);
- void UpdateProductDisplay(bool fDetails);
- void OnReply1(wxCommandEvent& event);
- };
- class CViewOrderDialog : public CViewOrderDialogBase
- {
- protected:
- void OnButtonOK(wxCommandEvent& event);
- public:
- CViewOrderDialog(wxWindow* parent, CWalletTx order, bool fReceived);
- bool fReceived;
- };
- class CEditReviewDialog : public CEditReviewDialogBase
- {
- protected:
- void OnKeyDown(wxKeyEvent& event) { HandleCtrlA(event); }
- void OnButtonSubmit(wxCommandEvent& event);
- void OnButtonCancel(wxCommandEvent& event);
- public:
- CEditReviewDialog(wxWindow* parent);
- void GetReview(CReview& review);
- };
- class CGetTextFromUserDialog : public CGetTextFromUserDialogBase
- {
- protected:
- void OnButtonOK(wxCommandEvent& event) { EndModal(true); }
- void OnButtonCancel(wxCommandEvent& event) { EndModal(false); }
- void OnClose(wxCloseEvent& event) { EndModal(false); }
- void OnKeyDown(wxKeyEvent& event)
- {
- if (event.GetKeyCode() == '\r' || event.GetKeyCode() == WXK_NUMPAD_ENTER)
- EndModal(true);
- else
- HandleCtrlA(event);
- }
- public:
- CGetTextFromUserDialog(wxWindow* parent,
- const string& strCaption,
- const string& strMessage1,
- const string& strValue1="",
- const string& strMessage2="",
- const string& strValue2="") : CGetTextFromUserDialogBase(parent, wxID_ANY, strCaption)
- {
- m_staticTextMessage1->SetLabel(strMessage1);
- m_textCtrl1->SetValue(strValue1);
- if (!strMessage2.empty())
- {
- m_staticTextMessage2->Show(true);
- m_staticTextMessage2->SetLabel(strMessage2);
- m_textCtrl2->Show(true);
- m_textCtrl2->SetValue(strValue2);
- SetSize(wxDefaultCoord, 180);
- }
- }
- string GetValue() { return (string)m_textCtrl1->GetValue(); }
- string GetValue1() { return (string)m_textCtrl1->GetValue(); }
- string GetValue2() { return (string)m_textCtrl2->GetValue(); }
- };
- #include <limits.h>
- #include <string>
- #if defined(_MSC_VER) || defined(__BORLANDC__)
- typedef __int64 int64;
- typedef unsigned __int64 uint64;
- #else
- typedef long long int64;
- typedef unsigned long long uint64;
- #endif
- #if defined(_MSC_VER) && _MSC_VER < 1300
- #define for if (false) ; else for
- #endif
- inline int Testuint256AdHoc(vector<string> vArg);
- template<unsigned int BITS>
- class base_uint
- {
- protected:
- enum { WIDTH=BITS/32 };
- unsigned int pn[WIDTH];
- public:
- bool operator!() const
- {
- for (int i = 0; i < WIDTH; i++)
- if (pn[i] != 0)
- return false;
- return true;
- }
- const base_uint operator~() const
- {
- base_uint ret;
- for (int i = 0; i < WIDTH; i++)
- ret.pn[i] = ~pn[i];
- return ret;
- }
- const base_uint operator-() const
- {
- base_uint ret;
- for (int i = 0; i < WIDTH; i++)
- ret.pn[i] = ~pn[i];
- ret++;
- return ret;
- }
- base_uint& operator=(uint64 b)
- {
- pn[0] = (unsigned int)b;
- pn[1] = (unsigned int)(b >> 32);
- for (int i = 2; i < WIDTH; i++)
- pn[i] = 0;
- return *this;
- }
- base_uint& operator^=(const base_uint& b)
- {
- for (int i = 0; i < WIDTH; i++)
- pn[i] ^= b.pn[i];
- return *this;
- }
- base_uint& operator&=(const base_uint& b)
- {
- for (int i = 0; i < WIDTH; i++)
- pn[i] &= b.pn[i];
- return *this;
- }
- base_uint& operator|=(const base_uint& b)
- {
- for (int i = 0; i < WIDTH; i++)
- pn[i] |= b.pn[i];
- return *this;
- }
- base_uint& operator^=(uint64 b)
- {
- pn[0] ^= (unsigned int)b;
- pn[1] ^= (unsigned int)(b >> 32);
- return *this;
- }
- base_uint& operator&=(uint64 b)
- {
- pn[0] &= (unsigned int)b;
- pn[1] &= (unsigned int)(b >> 32);
- return *this;
- }
- base_uint& operator|=(uint64 b)
- {
- pn[0] |= (unsigned int)b;
- pn[1] |= (unsigned int)(b >> 32);
- return *this;
- }
- base_uint& operator<<=(unsigned int shift)
- {
- base_uint a(*this);
- for (int i = 0; i < WIDTH; i++)
- pn[i] = 0;
- int k = shift / 32;
- shift = shift % 32;
- for (int i = 0; i < WIDTH; i++)
- {
- if (i+k+1 < WIDTH && shift != 0)
- pn[i+k+1] |= (a.pn[i] >> (32-shift));
- if (i+k < WIDTH)
- pn[i+k] |= (a.pn[i] << shift);
- }
- return *this;
- }
- base_uint& operator>>=(unsigned int shift)
- {
- base_uint a(*this);
- for (int i = 0; i < WIDTH; i++)
- pn[i] = 0;
- int k = shift / 32;
- shift = shift % 32;
- for (int i = 0; i < WIDTH; i++)
- {
- if (i-k-1 >= 0 && shift != 0)
- pn[i-k-1] |= (a.pn[i] << (32-shift));
- if (i-k >= 0)
- pn[i-k] |= (a.pn[i] >> shift);
- }
- return *this;
- }
- base_uint& operator+=(const base_uint& b)
- {
- uint64 carry = 0;
- for (int i = 0; i < WIDTH; i++)
- {
- uint64 n = carry + pn[i] + b.pn[i];
- pn[i] = n & 0xffffffff;
- carry = n >> 32;
- }
- return *this;
- }
- base_uint& operator-=(const base_uint& b)
- {
- *this += -b;
- return *this;
- }
- base_uint& operator+=(uint64 b64)
- {
- base_uint b;
- b = b64;
- *this += b;
- return *this;
- }
- base_uint& operator-=(uint64 b64)
- {
- base_uint b;
- b = b64;
- *this += -b;
- return *this;
- }
- base_uint& operator++()
- {
- int i = 0;
- while (++pn[i] == 0 && i < WIDTH-1)
- i++;
- return *this;
- }
- const base_uint operator++(int)
- {
- const base_uint ret = *this;
- ++(*this);
- return ret;
- }
- base_uint& operator--()
- {
- int i = 0;
- while (--pn[i] == -1 && i < WIDTH-1)
- i++;
- return *this;
- }
- const base_uint operator--(int)
- {
- const base_uint ret = *this;
- --(*this);
- return ret;
- }
- friend inline bool operator<(const base_uint& a, const base_uint& b)
- {
- for (int i = base_uint::WIDTH-1; i >= 0; i--)
- {
- if (a.pn[i] < b.pn[i])
- return true;
- else if (a.pn[i] > b.pn[i])
- return false;
- }
- return false;
- }
- friend inline bool operator<=(const base_uint& a, const base_uint& b)
- {
- for (int i = base_uint::WIDTH-1; i >= 0; i--)
- {
- if (a.pn[i] < b.pn[i])
- return true;
- else if (a.pn[i] > b.pn[i])
- return false;
- }
- return true;
- }
- friend inline bool operator>(const base_uint& a, const base_uint& b)
- {
- for (int i = base_uint::WIDTH-1; i >= 0; i--)
- {
- if (a.pn[i] > b.pn[i])
- return true;
- else if (a.pn[i] < b.pn[i])
- return false;
- }
- return false;
- }
- friend inline bool operator>=(const base_uint& a, const base_uint& b)
- {
- for (int i = base_uint::WIDTH-1; i >= 0; i--)
- {
- if (a.pn[i] > b.pn[i])
- return true;
- else if (a.pn[i] < b.pn[i])
- return false;
- }
- return true;
- }
- friend inline bool operator==(const base_uint& a, const base_uint& b)
- {
- for (int i = 0; i < base_uint::WIDTH; i++)
- if (a.pn[i] != b.pn[i])
- return false;
- return true;
- }
- friend inline bool operator==(const base_uint& a, uint64 b)
- {
- if (a.pn[0] != (unsigned int)b)
- return false;
- if (a.pn[1] != (unsigned int)(b >> 32))
- return false;
- for (int i = 2; i < base_uint::WIDTH; i++)
- if (a.pn[i] != 0)
- return false;
- return true;
- }
- friend inline bool operator!=(const base_uint& a, const base_uint& b)
- {
- return (!(a == b));
- }
- friend inline bool operator!=(const base_uint& a, uint64 b)
- {
- return (!(a == b));
- }
- std::string GetHex() const
- {
- char psz[sizeof(pn)*2 + 1];
- for (int i = 0; i < sizeof(pn); i++)
- sprintf(psz + i*2, "%02x", ((unsigned char*)pn)[sizeof(pn) - i - 1]);
- return string(psz, psz + sizeof(pn)*2);
- }
- void SetHex(const std::string& str)
- {
- for (int i = 0; i < WIDTH; i++)
- pn[i] = 0;
- const char* psz = str.c_str();
- while (isspace(*psz))
- psz++;
- if (psz[0] == '0' && tolower(psz[1]) == 'x')
- psz += 2;
- while (isspace(*psz))
- psz++;
- 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 };
- const char* pbegin = psz;
- while (phexdigit[*psz] || *psz == '0')
- psz++;
- psz--;
- unsigned char* p1 = (unsigned char*)pn;
- unsigned char* pend = p1 + WIDTH * 4;
- while (psz >= pbegin && p1 < pend)
- {
- *p1 = phexdigit[(unsigned char)*psz--];
- if (psz >= pbegin)
- {
- *p1 |= (phexdigit[(unsigned char)*psz--] << 4);
- p1++;
- }
- }
- }
- std::string ToString() const
- {
- return (GetHex());
- }
- unsigned char* begin()
- {
- return (unsigned char*)&pn[0];
- }
- unsigned char* end()
- {
- return (unsigned char*)&pn[WIDTH];
- }
- unsigned int size()
- {
- return sizeof(pn);
- }
- unsigned int GetSerializeSize(int nType=0, int nVersion=VERSION) const
- {
- return sizeof(pn);
- }
- template<typename Stream>
- void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const
- {
- s.write((char*)pn, sizeof(pn));
- }
- template<typename Stream>
- void Unserialize(Stream& s, int nType=0, int nVersion=VERSION)
- {
- s.read((char*)pn, sizeof(pn));
- }
- friend class uint160;
- friend class uint256;
- friend inline int Testuint256AdHoc(vector<string> vArg);
- };
- typedef base_uint<160> base_uint160;
- typedef base_uint<256> base_uint256;
- class uint160 : public base_uint160
- {
- public:
- typedef base_uint160 basetype;
- uint160()
- {
- }
- uint160(const basetype& b)
- {
- for (int i = 0; i < WIDTH; i++)
- pn[i] = b.pn[i];
- }
- uint160& operator=(const basetype& b)
- {
- for (int i = 0; i < WIDTH; i++)
- pn[i] = b.pn[i];
- return *this;
- }
- uint160(uint64 b)
- {
- pn[0] = (unsigned int)b;
- pn[1] = (unsigned int)(b >> 32);
- for (int i = 2; i < WIDTH; i++)
- pn[i] = 0;
- }
- uint160& operator=(uint64 b)
- {
- pn[0] = (unsigned int)b;
- pn[1] = (unsigned int)(b >> 32);
- for (int i = 2; i < WIDTH; i++)
- pn[i] = 0;
- return *this;
- }
- explicit uint160(const std::string& str)
- {
- SetHex(str);
- }
- explicit uint160(const std::vector<unsigned char>& vch)
- {
- if (vch.size() == sizeof(pn))
- memcpy(pn, &vch[0], sizeof(pn));
- else
- *this = 0;
- }
- };
- inline bool operator==(const uint160& a, uint64 b) { return (base_uint160)a == b; }
- inline bool operator!=(const uint160& a, uint64 b) { return (base_uint160)a != b; }
- inline const uint160 operator<<(const base_uint160& a, unsigned int shift) { return uint160(a) <<= shift; }
- inline const uint160 operator>>(const base_uint160& a, unsigned int shift) { return uint160(a) >>= shift; }
- inline const uint160 operator<<(const uint160& a, unsigned int shift) { return uint160(a) <<= shift; }
- inline const uint160 operator>>(const uint160& a, unsigned int shift) { return uint160(a) >>= shift; }
- inline const uint160 operator^(const base_uint160& a, const base_uint160& b) { return uint160(a) ^= b; }
- inline const uint160 operator&(const base_uint160& a, const base_uint160& b) { return uint160(a) &= b; }
- inline const uint160 operator|(const base_uint160& a, const base_uint160& b) { return uint160(a) |= b; }
- inline const uint160 operator+(const base_uint160& a, const base_uint160& b) { return uint160(a) += b; }
- inline const uint160 operator-(const base_uint160& a, const base_uint160& b) { return uint160(a) -= b; }
- inline bool operator<(const base_uint160& a, const uint160& b) { return (base_uint160)a < (base_uint160)b; }
- inline bool operator<=(const base_uint160& a, const uint160& b) { return (base_uint160)a <= (base_uint160)b; }
- inline bool operator>(const base_uint160& a, const uint160& b) { return (base_uint160)a > (base_uint160)b; }
- inline bool operator>=(const base_uint160& a, const uint160& b) { return (base_uint160)a >= (base_uint160)b; }
- inline bool operator==(const base_uint160& a, const uint160& b) { return (base_uint160)a == (base_uint160)b; }
- inline bool operator!=(const base_uint160& a, const uint160& b) { return (base_uint160)a != (base_uint160)b; }
- inline const uint160 operator^(const base_uint160& a, const uint160& b) { return (base_uint160)a ^ (base_uint160)b; }
- inline const uint160 operator&(const base_uint160& a, const uint160& b) { return (base_uint160)a & (base_uint160)b; }
- inline const uint160 operator|(const base_uint160& a, const uint160& b) { return (base_uint160)a | (base_uint160)b; }
- inline const uint160 operator+(const base_uint160& a, const uint160& b) { return (base_uint160)a + (base_uint160)b; }
- inline const uint160 operator-(const base_uint160& a, const uint160& b) { return (base_uint160)a - (base_uint160)b; }
- inline bool operator<(const uint160& a, const base_uint160& b) { return (base_uint160)a < (base_uint160)b; }
- inline bool operator<=(const uint160& a, const base_uint160& b) { return (base_uint160)a <= (base_uint160)b; }
- inline bool operator>(const uint160& a, const base_uint160& b) { return (base_uint160)a > (base_uint160)b; }
- inline bool operator>=(const uint160& a, const base_uint160& b) { return (base_uint160)a >= (base_uint160)b; }
- inline bool operator==(const uint160& a, const base_uint160& b) { return (base_uint160)a == (base_uint160)b; }
- inline bool operator!=(const uint160& a, const base_uint160& b) { return (base_uint160)a != (base_uint160)b; }
- inline const uint160 operator^(const uint160& a, const base_uint160& b) { return (base_uint160)a ^ (base_uint160)b; }
- inline const uint160 operator&(const uint160& a, const base_uint160& b) { return (base_uint160)a & (base_uint160)b; }
- inline const uint160 operator|(const uint160& a, const base_uint160& b) { return (base_uint160)a | (base_uint160)b; }
- inline const uint160 operator+(const uint160& a, const base_uint160& b) { return (base_uint160)a + (base_uint160)b; }
- inline const uint160 operator-(const uint160& a, const base_uint160& b) { return (base_uint160)a - (base_uint160)b; }
- inline bool operator<(const uint160& a, const uint160& b) { return (base_uint160)a < (base_uint160)b; }
- inline bool operator<=(const uint160& a, const uint160& b) { return (base_uint160)a <= (base_uint160)b; }
- inline bool operator>(const uint160& a, const uint160& b) { return (base_uint160)a > (base_uint160)b; }
- inline bool operator>=(const uint160& a, const uint160& b) { return (base_uint160)a >= (base_uint160)b; }
- inline bool operator==(const uint160& a, const uint160& b) { return (base_uint160)a == (base_uint160)b; }
- inline bool operator!=(const uint160& a, const uint160& b) { return (base_uint160)a != (base_uint160)b; }
- inline const uint160 operator^(const uint160& a, const uint160& b) { return (base_uint160)a ^ (base_uint160)b; }
- inline const uint160 operator&(const uint160& a, const uint160& b) { return (base_uint160)a & (base_uint160)b; }
- inline const uint160 operator|(const uint160& a, const uint160& b) { return (base_uint160)a | (base_uint160)b; }
- inline const uint160 operator+(const uint160& a, const uint160& b) { return (base_uint160)a + (base_uint160)b; }
- inline const uint160 operator-(const uint160& a, const uint160& b) { return (base_uint160)a - (base_uint160)b; }
- class uint256 : public base_uint256
- {
- public:
- typedef base_uint256 basetype;
- uint256()
- {
- }
- uint256(const basetype& b)
- {
- for (int i = 0; i < WIDTH; i++)
- pn[i] = b.pn[i];
- }
- uint256& operator=(const basetype& b)
- {
- for (int i = 0; i < WIDTH; i++)
- pn[i] = b.pn[i];
- return *this;
- }
- uint256(uint64 b)
- {
- pn[0] = (unsigned int)b;
- pn[1] = (unsigned int)(b >> 32);
- for (int i = 2; i < WIDTH; i++)
- pn[i] = 0;
- }
- uint256& operator=(uint64 b)
- {
- pn[0] = (unsigned int)b;
- pn[1] = (unsigned int)(b >> 32);
- for (int i = 2; i < WIDTH; i++)
- pn[i] = 0;
- return *this;
- }
- explicit uint256(const std::string& str)
- {
- SetHex(str);
- }
- explicit uint256(const std::vector<unsigned char>& vch)
- {
- if (vch.size() == sizeof(pn))
- memcpy(pn, &vch[0], sizeof(pn));
- else
- *this = 0;
- }
- };
- inline bool operator==(const uint256& a, uint64 b) { return (base_uint256)a == b; }
- inline bool operator!=(const uint256& a, uint64 b) { return (base_uint256)a != b; }
- inline const uint256 operator<<(const base_uint256& a, unsigned int shift) { return uint256(a) <<= shift; }
- inline const uint256 operator>>(const base_uint256& a, unsigned int shift) { return uint256(a) >>= shift; }
- inline const uint256 operator<<(const uint256& a, unsigned int shift) { return uint256(a) <<= shift; }
- inline const uint256 operator>>(const uint256& a, unsigned int shift) { return uint256(a) >>= shift; }
- inline const uint256 operator^(const base_uint256& a, const base_uint256& b) { return uint256(a) ^= b; }
- inline const uint256 operator&(const base_uint256& a, const base_uint256& b) { return uint256(a) &= b; }
- inline const uint256 operator|(const base_uint256& a, const base_uint256& b) { return uint256(a) |= b; }
- inline const uint256 operator+(const base_uint256& a, const base_uint256& b) { return uint256(a) += b; }
- inline const uint256 operator-(const base_uint256& a, const base_uint256& b) { return uint256(a) -= b; }
- inline bool operator<(const base_uint256& a, const uint256& b) { return (base_uint256)a < (base_uint256)b; }
- inline bool operator<=(const base_uint256& a, const uint256& b) { return (base_uint256)a <= (base_uint256)b; }
- inline bool operator>(const base_uint256& a, const uint256& b) { return (base_uint256)a > (base_uint256)b; }
- inline bool operator>=(const base_uint256& a, const uint256& b) { return (base_uint256)a >= (base_uint256)b; }
- inline bool operator==(const base_uint256& a, const uint256& b) { return (base_uint256)a == (base_uint256)b; }
- inline bool operator!=(const base_uint256& a, const uint256& b) { return (base_uint256)a != (base_uint256)b; }
- inline const uint256 operator^(const base_uint256& a, const uint256& b) { return (base_uint256)a ^ (base_uint256)b; }
- inline const uint256 operator&(const base_uint256& a, const uint256& b) { return (base_uint256)a & (base_uint256)b; }
- inline const uint256 operator|(const base_uint256& a, const uint256& b) { return (base_uint256)a | (base_uint256)b; }
- inline const uint256 operator+(const base_uint256& a, const uint256& b) { return (base_uint256)a + (base_uint256)b; }
- inline const uint256 operator-(const base_uint256& a, const uint256& b) { return (base_uint256)a - (base_uint256)b; }
- inline bool operator<(const uint256& a, const base_uint256& b) { return (base_uint256)a < (base_uint256)b; }
- inline bool operator<=(const uint256& a, const base_uint256& b) { return (base_uint256)a <= (base_uint256)b; }
- inline bool operator>(const uint256& a, const base_uint256& b) { return (base_uint256)a > (base_uint256)b; }
- inline bool operator>=(const uint256& a, const base_uint256& b) { return (base_uint256)a >= (base_uint256)b; }
- inline bool operator==(const uint256& a, const base_uint256& b) { return (base_uint256)a == (base_uint256)b; }
- inline bool operator!=(const uint256& a, const base_uint256& b) { return (base_uint256)a != (base_uint256)b; }
- inline const uint256 operator^(const uint256& a, const base_uint256& b) { return (base_uint256)a ^ (base_uint256)b; }
- inline const uint256 operator&(const uint256& a, const base_uint256& b) { return (base_uint256)a & (base_uint256)b; }
- inline const uint256 operator|(const uint256& a, const base_uint256& b) { return (base_uint256)a | (base_uint256)b; }
- inline const uint256 operator+(const uint256& a, const base_uint256& b) { return (base_uint256)a + (base_uint256)b; }
- inline const uint256 operator-(const uint256& a, const base_uint256& b) { return (base_uint256)a - (base_uint256)b; }
- inline bool operator<(const uint256& a, const uint256& b) { return (base_uint256)a < (base_uint256)b; }
- inline bool operator<=(const uint256& a, const uint256& b) { return (base_uint256)a <= (base_uint256)b; }
- inline bool operator>(const uint256& a, const uint256& b) { return (base_uint256)a > (base_uint256)b; }
- inline bool operator>=(const uint256& a, const uint256& b) { return (base_uint256)a >= (base_uint256)b; }
- inline bool operator==(const uint256& a, const uint256& b) { return (base_uint256)a == (base_uint256)b; }
- inline bool operator!=(const uint256& a, const uint256& b) { return (base_uint256)a != (base_uint256)b; }
- inline const uint256 operator^(const uint256& a, const uint256& b) { return (base_uint256)a ^ (base_uint256)b; }
- inline const uint256 operator&(const uint256& a, const uint256& b) { return (base_uint256)a & (base_uint256)b; }
- inline const uint256 operator|(const uint256& a, const uint256& b) { return (base_uint256)a | (base_uint256)b; }
- inline const uint256 operator+(const uint256& a, const uint256& b) { return (base_uint256)a + (base_uint256)b; }
- inline const uint256 operator-(const uint256& a, const uint256& b) { return (base_uint256)a - (base_uint256)b; }
- inline int Testuint256AdHoc(vector<string> vArg)
- {
- uint256 g(0);
- printf("%s\n", g.ToString().c_str());
- g--; printf("g--\n");
- printf("%s\n", g.ToString().c_str());
- g--; printf("g--\n");
- printf("%s\n", g.ToString().c_str());
- g++; printf("g++\n");
- printf("%s\n", g.ToString().c_str());
- g++; printf("g++\n");
- printf("%s\n", g.ToString().c_str());
- g++; printf("g++\n");
- printf("%s\n", g.ToString().c_str());
- g++; printf("g++\n");
- printf("%s\n", g.ToString().c_str());
- uint256 a(7);
- printf("a=7\n");
- printf("%s\n", a.ToString().c_str());
- uint256 b;
- printf("b undefined\n");
- printf("%s\n", b.ToString().c_str());
- int c = 3;
- a = c;
- a.pn[3] = 15;
- printf("%s\n", a.ToString().c_str());
- uint256 k(c);
- a = 5;
- a.pn[3] = 15;
- printf("%s\n", a.ToString().c_str());
- b = 1;
- b <<= 52;
- a |= b;
- a ^= 0x500;
- printf("a %s\n", a.ToString().c_str());
- a = a | b | (uint256)0x1000;
- printf("a %s\n", a.ToString().c_str());
- printf("b %s\n", b.ToString().c_str());
- a = 0xfffffffe;
- a.pn[4] = 9;
- printf("%s\n", a.ToString().c_str());
- a++;
- printf("%s\n", a.ToString().c_str());
- a++;
- printf("%s\n", a.ToString().c_str());
- a++;
- printf("%s\n", a.ToString().c_str());
- a++;
- printf("%s\n", a.ToString().c_str());
- a--;
- printf("%s\n", a.ToString().c_str());
- a--;
- printf("%s\n", a.ToString().c_str());
- a--;
- printf("%s\n", a.ToString().c_str());
- uint256 d = a--;
- printf("%s\n", d.ToString().c_str());
- printf("%s\n", a.ToString().c_str());
- a--;
- printf("%s\n", a.ToString().c_str());
- a--;
- printf("%s\n", a.ToString().c_str());
- d = a;
- printf("%s\n", d.ToString().c_str());
- for (int i = uint256::WIDTH-1; i >= 0; i--) printf("%08x", d.pn[i]); printf("\n");
- uint256 neg = d;
- neg = ~neg;
- printf("%s\n", neg.ToString().c_str());
- uint256 e = uint256("0xABCDEF123abcdef12345678909832180000011111111");
- printf("\n");
- printf("%s\n", e.ToString().c_str());
- printf("\n");
- uint256 x1 = uint256("0xABCDEF123abcdef12345678909832180000011111111");
- uint256 x2;
- printf("%s\n", x1.ToString().c_str());
- for (int i = 0; i < 270; i += 4)
- {
- x2 = x1 << i;
- printf("%s\n", x2.ToString().c_str());
- }
- printf("\n");
- printf("%s\n", x1.ToString().c_str());
- for (int i = 0; i < 270; i += 4)
- {
- x2 = x1;
- x2 >>= i;
- printf("%s\n", x2.ToString().c_str());
- }
- for (int i = 0; i < 100; i++)
- {
- uint256 k = (~uint256(0) >> i);
- printf("%s\n", k.ToString().c_str());
- }
- for (int i = 0; i < 100; i++)
- {
- uint256 k = (~uint256(0) << i);
- printf("%s\n", k.ToString().c_str());
- }
- return (0);
- }
- #include "headers.h"
- bool fDebug = false;
- static HANDLE* lock_cs;
- void win32_locking_callback(int mode, int type, const char* file, int line)
- {
- if (mode & CRYPTO_LOCK)
- WaitForSingleObject(lock_cs[type], INFINITE);
- else
- ReleaseMutex(lock_cs[type]);
- }
- class CInit
- {
- public:
- CInit()
- {
- lock_cs = (HANDLE*)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(HANDLE));
- for (int i = 0; i < CRYPTO_num_locks(); i++)
- lock_cs[i] = CreateMutex(NULL,FALSE,NULL);
- CRYPTO_set_locking_callback(win32_locking_callback);
- RAND_screen();
- RandAddSeed(true);
- }
- ~CInit()
- {
- CRYPTO_set_locking_callback(NULL);
- for (int i =0 ; i < CRYPTO_num_locks(); i++)
- CloseHandle(lock_cs[i]);
- OPENSSL_free(lock_cs);
- }
- }
- instance_of_cinit;
- void RandAddSeed(bool fPerfmon)
- {
- LARGE_INTEGER PerformanceCount;
- QueryPerformanceCounter(&PerformanceCount);
- RAND_add(&PerformanceCount, sizeof(PerformanceCount), 1.5);
- memset(&PerformanceCount, 0, sizeof(PerformanceCount));
- static int64 nLastPerfmon;
- if (fPerfmon || GetTime() > nLastPerfmon + 5 * 60)
- {
- nLastPerfmon = GetTime();
- unsigned char pdata[250000];
- memset(pdata, 0, sizeof(pdata));
- unsigned long nSize = sizeof(pdata);
- long ret = RegQueryValueEx(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize);
- RegCloseKey(HKEY_PERFORMANCE_DATA);
- if (ret == ERROR_SUCCESS)
- {
- uint256 hash;
- SHA256(pdata, nSize, (unsigned char*)&hash);
- RAND_add(&hash, sizeof(hash), min(nSize/500.0, (double)sizeof(hash)));
- hash = 0;
- memset(pdata, 0, nSize);
- printf("RandAddSeed() got %d bytes of performance data\n", nSize);
- }
- }
- }
- int my_snprintf(char* buffer, size_t limit, const char* format, ...)
- { if (limit == 0)
- return 0;
- va_list arg_ptr;
- va_start(arg_ptr, format);
- int ret = _vsnprintf(buffer, limit, format, arg_ptr);
- va_end(arg_ptr);
- if (ret < 0 || ret >= limit)
- {
- ret = limit - 1;
- buffer[limit-1] = 0;
- }
- return ret;
- }
- string strprintf(const char* format, ...)
- {
- char buffer[50000];
- char* p = buffer;
- int limit = sizeof(buffer);
- int ret;
- loop
- {
- va_list arg_ptr;
- va_start(arg_ptr, format);
- ret = _vsnprintf(p, limit, format, arg_ptr);
- va_end(arg_ptr);
- if (ret >= 0 && ret < limit)
- break;
- if (p != buffer)
- delete p;
- limit *= 2;
- p = new char[limit];
- if (p == NULL)
- throw std::bad_alloc();
- }
- #ifdef _MSC_VER
- if (p == buffer)
- return string(p, p+ret);
- #endif
- string str(p, p+ret);
- if (p != buffer)
- delete p;
- return str;
- }
- bool error(const char* format, ...)
- {
- char buffer[50000];
- int limit = sizeof(buffer);
- va_list arg_ptr;
- va_start(arg_ptr, format);
- int ret = _vsnprintf(buffer, limit, format, arg_ptr);
- va_end(arg_ptr);
- if (ret < 0 || ret >= limit)
- {
- ret = limit - 1;
- buffer[limit-1] = 0;
- }
- printf("ERROR: %s\n", buffer);
- return false;
- }
- void PrintException(std::exception* pex, const char* pszThread)
- {
- char pszModule[260];
- pszModule[0] = '\0';
- GetModuleFileName(NULL, pszModule, sizeof(pszModule));
- _strlwr(pszModule);
- char pszMessage[1000];
- if (pex)
- snprintf(pszMessage, sizeof(pszMessage),
- "EXCEPTION: %s \n%s \n%s in %s \n", typeid(*pex).name(), pex->what(), pszModule, pszThread);
- else
- snprintf(pszMessage, sizeof(pszMessage),
- "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread);
- printf("\n\n************************\n%s", pszMessage);
- if (wxTheApp)
- wxMessageBox(pszMessage, "Error", wxOK | wxICON_ERROR);
- throw;
- }
- void ParseString(const string& str, char c, vector<string>& v)
- {
- unsigned int i1 = 0;
- unsigned int i2;
- do
- {
- i2 = str.find(c, i1);
- v.push_back(str.substr(i1, i2-i1));
- i1 = i2+1;
- }
- while (i2 != str.npos);
- }
- string FormatMoney(int64 n, bool fPlus)
- {
- n /= CENT;
- string str = strprintf("%I64d.%02I64d", (n > 0 ? n : -n)/100, (n > 0 ? n : -n)%100);
- for (int i = 6; i < str.size(); i += 4)
- if (isdigit(str[str.size() - i - 1]))
- str.insert(str.size() - i, 1, ',');
- if (n < 0)
- str.insert((unsigned int)0, 1, '-');
- else if (fPlus && n > 0)
- str.insert((unsigned int)0, 1, '+');
- return str;
- }
- bool ParseMoney(const char* pszIn, int64& nRet)
- {
- string strWhole;
- int64 nCents = 0;
- const char* p = pszIn;
- while (isspace(*p))
- p++;
- for (; *p; p++)
- {
- if (*p == ',' && p > pszIn && isdigit(p[-1]) && isdigit(p[1]) && isdigit(p[2]) && isdigit(p[3]) && !isdigit(p[4]))
- continue;
- if (*p == '.')
- {
- p++;
- if (!isdigit(p[0]) || !isdigit(p[1]))
- return false;
- nCents = atoi64(p);
- if (nCents < 0 || nCents > 99)
- return false;
- p += 2;
- break;
- }
- if (isspace(*p))
- break;
- if (!isdigit(*p))
- return false;
- strWhole.insert(strWhole.end(), *p);
- }
- for (; *p; p++)
- if (!isspace(*p))
- return false;
- if (strWhole.size() > 17)
- return false;
- int64 nWhole = atoi64(strWhole);
- int64 nValue = nWhole * 100 + nCents;
- if (nValue / 100 != nWhole)
- return false;
- nValue *= CENT;
- nRet = nValue;
- return true;
- }
- bool FileExists(const char* psz)
- {
- #ifdef WIN32
- return GetFileAttributes(psz) != -1;
- #else
- return access(psz, 0) != -1;
- #endif
- }
- int GetFilesize(FILE* file)
- {
- int nSavePos = ftell(file);
- int nFilesize = -1;
- if (fseek(file, 0, SEEK_END) == 0)
- nFilesize = ftell(file);
- fseek(file, nSavePos, SEEK_SET);
- return nFilesize;
- }
- uint64 GetRand(uint64 nMax)
- {
- if (nMax == 0)
- return 0;
- uint64 nRange = (_UI64_MAX / nMax) * nMax;
- uint64 nRand = 0;
- do
- RAND_bytes((unsigned char*)&nRand, sizeof(nRand));
- while (nRand >= nRange);
- return (nRand % nMax);
- }
- int64 GetTime()
- {
- return time(NULL);
- }
- static int64 nTimeOffset = 0;
- int64 GetAdjustedTime()
- {
- return GetTime() + nTimeOffset;
- }
- void AddTimeData(unsigned int ip, int64 nTime)
- {
- int64 nOffsetSample = nTime - GetTime();
- static set<unsigned int> setKnown;
- if (!setKnown.insert(ip).second)
- return;
- static vector<int64> vTimeOffsets;
- if (vTimeOffsets.empty())
- vTimeOffsets.push_back(0);
- vTimeOffsets.push_back(nOffsetSample);
- printf("Added time data, samples %d, ip %08x, offset %+I64d (%+I64d minutes)\n", vTimeOffsets.size(), ip, vTimeOffsets.back(), vTimeOffsets.back()/60);
- if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
- {
- sort(vTimeOffsets.begin(), vTimeOffsets.end());
- int64 nMedian = vTimeOffsets[vTimeOffsets.size()/2];
- nTimeOffset = nMedian;
- if ((nMedian > 0 ? nMedian : -nMedian) > 5 * 60)
- {
- }
- foreach(int64 n, vTimeOffsets)
- printf("%+I64d ", n);
- printf("| nTimeOffset = %+I64d (%+I64d minutes)\n", nTimeOffset, nTimeOffset/60);
- }
- }
- #if defined(_MSC_VER) || defined(__BORLANDC__)
- typedef __int64 int64;
- typedef unsigned __int64 uint64;
- #else
- typedef long long int64;
- typedef unsigned long long uint64;
- #endif
- #if defined(_MSC_VER) && _MSC_VER < 1300
- #define for if (false) ; else for
- #endif
- #ifndef _MSC_VER
- #define __forceinline inline
- #endif
- #define foreach BOOST_FOREACH
- #define loop for (;;)
- #define BEGIN(a) ((char*)&(a))
- #define END(a) ((char*)&((&(a))[1]))
- #define UBEGIN(a) ((unsigned char*)&(a))
- #define UEND(a) ((unsigned char*)&((&(a))[1]))
- #define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0]))
- #ifdef _WINDOWS
- #define printf OutputDebugStringF
- #endif
- #ifdef snprintf
- #undef snprintf
- #endif
- #define snprintf my_snprintf
- #ifndef PRId64
- #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MSVCRT__)
- #define PRId64 "I64d"
- #define PRIu64 "I64u"
- #define PRIx64 "I64x"
- #else
- #define PRId64 "lld"
- #define PRIu64 "llu"
- #define PRIx64 "llx"
- #endif
- #endif
- #define PAIRTYPE(t1, t2) pair<t1, t2>
- template<typename T>
- inline T& REF(const T& val)
- {
- return (T&)val;
- }
- extern bool fDebug;
- void RandAddSeed(bool fPerfmon=false);
- int my_snprintf(char* buffer, size_t limit, const char* format, ...);
- string strprintf(const char* format, ...);
- bool error(const char* format, ...);
- void PrintException(std::exception* pex, const char* pszThread);
- void ParseString(const string& str, char c, vector<string>& v);
- string FormatMoney(int64 n, bool fPlus=false);
- bool ParseMoney(const char* pszIn, int64& nRet);
- bool FileExists(const char* psz);
- int GetFilesize(FILE* file);
- uint64 GetRand(uint64 nMax);
- int64 GetTime();
- int64 GetAdjustedTime();
- void AddTimeData(unsigned int ip, int64 nTime);
- class CCriticalSection
- {
- protected:
- CRITICAL_SECTION cs;
- public:
- char* pszFile;
- int nLine;
- explicit CCriticalSection() { InitializeCriticalSection(&cs); }
- ~CCriticalSection() { DeleteCriticalSection(&cs); }
- void Enter() { EnterCriticalSection(&cs); }
- void Leave() { LeaveCriticalSection(&cs); }
- bool TryEnter() { return TryEnterCriticalSection(&cs); }
- CRITICAL_SECTION* operator&() { return &cs; }
- };
- class CCriticalBlock
- {
- protected:
- CRITICAL_SECTION* pcs;
- public:
- CCriticalBlock(CRITICAL_SECTION& csIn) { pcs = &csIn; EnterCriticalSection(pcs); }
- CCriticalBlock(CCriticalSection& csIn) { pcs = &csIn; EnterCriticalSection(pcs); }
- ~CCriticalBlock() { LeaveCriticalSection(pcs); }
- };
- #define CRITICAL_BLOCK(cs) \
- for (bool fcriticalblockonce=true; fcriticalblockonce; assert(("break caught by CRITICAL_BLOCK!", !fcriticalblockonce)), fcriticalblockonce=false) \
- for (CCriticalBlock criticalblock(cs); fcriticalblockonce && (cs.pszFile=__FILE__, cs.nLine=__LINE__, true); fcriticalblockonce=false, cs.pszFile=NULL, cs.nLine=0)
- class CTryCriticalBlock
- {
- protected:
- CRITICAL_SECTION* pcs;
- public:
- CTryCriticalBlock(CRITICAL_SECTION& csIn) { pcs = (TryEnterCriticalSection(&csIn) ? &csIn : NULL); }
- CTryCriticalBlock(CCriticalSection& csIn) { pcs = (TryEnterCriticalSection(&csIn) ? &csIn : NULL); }
- ~CTryCriticalBlock() { if (pcs) LeaveCriticalSection(pcs); }
- bool Entered() { return pcs != NULL; }
- };
- #define TRY_CRITICAL_BLOCK(cs) \
- for (bool fcriticalblockonce=true; fcriticalblockonce; assert(("break caught by TRY_CRITICAL_BLOCK!", !fcriticalblockonce)), fcriticalblockonce=false) \
- for (CTryCriticalBlock criticalblock(cs); fcriticalblockonce && (fcriticalblockonce = criticalblock.Entered()) && (cs.pszFile=__FILE__, cs.nLine=__LINE__, true); fcriticalblockonce=false, cs.pszFile=NULL, cs.nLine=0)
- inline string i64tostr(int64 n)
- {
- return strprintf("%"PRId64, n);
- }
- inline string itostr(int n)
- {
- return strprintf("%d", n);
- }
- inline int64 atoi64(const char* psz)
- {
- #ifdef _MSC_VER
- return _atoi64(psz);
- #else
- return strtoll(psz, NULL, 10);
- #endif
- }
- inline int64 atoi64(const string& str)
- {
- #ifdef _MSC_VER
- return _atoi64(str.c_str());
- #else
- return strtoll(str.c_str(), NULL, 10);
- #endif
- }
- inline int atoi(const string& str)
- {
- return atoi(str.c_str());
- }
- inline int roundint(double d)
- {
- return (int)(d > 0 ? d + 0.5 : d - 0.5);
- }
- template<typename T>
- string HexStr(const T itbegin, const T itend, bool fSpaces=true)
- {
- const unsigned char* pbegin = (const unsigned char*)&itbegin[0];
- const unsigned char* pend = pbegin + (itend - itbegin) * sizeof(itbegin[0]);
- string str;
- for (const unsigned char* p = pbegin; p != pend; p++)
- str += strprintf((fSpaces && p != pend-1 ? "%02x " : "%02x"), *p);
- return str;
- }
- template<typename T>
- string HexNumStr(const T itbegin, const T itend, bool f0x=true)
- {
- const unsigned char* pbegin = (const unsigned char*)&itbegin[0];
- const unsigned char* pend = pbegin + (itend - itbegin) * sizeof(itbegin[0]);
- string str = (f0x ? "0x" : "");
- for (const unsigned char* p = pend-1; p >= pbegin; p--)
- str += strprintf("%02X", *p);
- return str;
- }
- template<typename T>
- void PrintHex(const T pbegin, const T pend, const char* pszFormat="%s", bool fSpaces=true)
- {
- printf(pszFormat, HexStr(pbegin, pend, fSpaces).c_str());
- }
- inline int OutputDebugStringF(const char* pszFormat, ...)
- {
- #ifdef __WXDEBUG__
- FILE* fileout = fopen("debug.log", "a");
- if (fileout)
- {
- va_list arg_ptr;
- va_start(arg_ptr, pszFormat);
- vfprintf(fileout, pszFormat, arg_ptr);
- va_end(arg_ptr);
- fclose(fileout);
- }
- static CCriticalSection cs_OutputDebugStringF;
- CRITICAL_BLOCK(cs_OutputDebugStringF)
- {
- static char pszBuffer[50000];
- static char* pend;
- if (pend == NULL)
- pend = pszBuffer;
- va_list arg_ptr;
- va_start(arg_ptr, pszFormat);
- int limit = END(pszBuffer) - pend - 2;
- int ret = _vsnprintf(pend, limit, pszFormat, arg_ptr);
- va_end(arg_ptr);
- if (ret < 0 || ret >= limit)
- {
- pend = END(pszBuffer) - 2;
- *pend++ = '\n';
- }
- else
- pend += ret;
- *pend = '\0';
- char* p1 = pszBuffer;
- char* p2;
- while (p2 = strchr(p1, '\n'))
- {
- p2++;
- char c = *p2;
- *p2 = '\0';
- OutputDebugString(p1);
- *p2 = c;
- p1 = p2;
- }
- if (p1 != pszBuffer)
- memmove(pszBuffer, p1, pend - p1 + 1);
- pend -= (p1 - pszBuffer);
- return ret;
- }
- #endif
- if (!wxTheApp)
- {
- va_list arg_ptr;
- va_start(arg_ptr, pszFormat);
- vprintf(pszFormat, arg_ptr);
- va_end(arg_ptr);
- }
- return 0;
- }
- inline void heapchk()
- {
- if (_heapchk() != _HEAPOK)
- DebugBreak();
- }
- #define IMPLEMENT_RANDOMIZE_STACK(ThreadFn) \
- { \
- static char nLoops; \
- if (nLoops <= 0) \
- nLoops = GetRand(50) + 1; \
- if (nLoops-- > 1) \
- { \
- ThreadFn; \
- return; \
- } \
- }
- #define CATCH_PRINT_EXCEPTION(pszFn) \
- catch (std::exception& e) { \
- PrintException(&e, (pszFn)); \
- } catch (...) { \
- PrintException(NULL, (pszFn)); \
- }
- template<typename T1>
- inline uint256 Hash(const T1 pbegin, const T1 pend)
- {
- uint256 hash1;
- SHA256((unsigned char*)&pbegin[0], (pend - pbegin) * sizeof(pbegin[0]), (unsigned char*)&hash1);
- uint256 hash2;
- SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
- return hash2;
- }
- template<typename T1, typename T2>
- inline uint256 Hash(const T1 p1begin, const T1 p1end,
- const T2 p2begin, const T2 p2end)
- {
- uint256 hash1;
- SHA256_CTX ctx;
- SHA256_Init(&ctx);
- SHA256_Update(&ctx, (unsigned char*)&p1begin[0], (p1end - p1begin) * sizeof(p1begin[0]));
- SHA256_Update(&ctx, (unsigned char*)&p2begin[0], (p2end - p2begin) * sizeof(p2begin[0]));
- SHA256_Final((unsigned char*)&hash1, &ctx);
- uint256 hash2;
- SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
- return hash2;
- }
- template<typename T1, typename T2, typename T3>
- inline uint256 Hash(const T1 p1begin, const T1 p1end,
- const T2 p2begin, const T2 p2end,
- const T3 p3begin, const T3 p3end)
- {
- uint256 hash1;
- SHA256_CTX ctx;
- SHA256_Init(&ctx);
- SHA256_Update(&ctx, (unsigned char*)&p1begin[0], (p1end - p1begin) * sizeof(p1begin[0]));
- SHA256_Update(&ctx, (unsigned char*)&p2begin[0], (p2end - p2begin) * sizeof(p2begin[0]));
- SHA256_Update(&ctx, (unsigned char*)&p3begin[0], (p3end - p3begin) * sizeof(p3begin[0]));
- SHA256_Final((unsigned char*)&hash1, &ctx);
- uint256 hash2;
- SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
- return hash2;
- }
- template<typename T>
- uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=VERSION)
- {
- CDataStream ss(nType, nVersion);
- ss.reserve(10000);
- ss << obj;
- return Hash(ss.begin(), ss.end());
- }
- inline uint160 Hash160(const vector<unsigned char>& vch)
- {
- uint256 hash1;
- SHA256(&vch[0], vch.size(), (unsigned char*)&hash1);
- uint160 hash2;
- RIPEMD160((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
- return hash2;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement