Browse Source

integrate a few extra .h files

pull/145/head
Wladimir J. van der Laan 13 years ago
parent
commit
2097c09a9b
  1. 10
      bitcoin.pro
  2. 5
      core/include/bignum.h
  3. 171
      core/include/key.h
  4. 2059
      core/include/main.h
  5. 1046
      core/include/net.h
  6. 3
      core/include/serialize.h
  7. 86
      core/include/strlcpy.h
  8. 2
      core/include/util.h
  9. 917
      core/src/util.cpp
  10. 2
      gui/include/bitcoinaddressvalidator.h
  11. 13
      gui/src/sendcoinsdialog.cpp

10
bitcoin.pro

@ -2,6 +2,7 @@ TEMPLATE = app
TARGET =
DEPENDPATH += .
INCLUDEPATH += gui/include core/include cryptopp/include
unix:LIBS += -lssl
# Input
HEADERS += gui/include/bitcoingui.h \
@ -29,7 +30,11 @@ HEADERS += gui/include/bitcoingui.h \
cryptopp/include/cryptopp/iterhash.h \
cryptopp/include/cryptopp/cryptlib.h \
cryptopp/include/cryptopp/cpu.h \
cryptopp/include/cryptopp/config.h
cryptopp/include/cryptopp/config.h \
core/include/strlcpy.h \
core/include/main.h \
core/include/net.h \
core/include/key.h
SOURCES += gui/src/bitcoin.cpp gui/src/bitcoingui.cpp \
gui/src/transactiontablemodel.cpp \
gui/src/addresstablemodel.cpp \
@ -41,7 +46,8 @@ SOURCES += gui/src/bitcoin.cpp gui/src/bitcoingui.cpp \
gui/src/editaddressdialog.cpp \
gui/src/bitcoinaddressvalidator.cpp \
cryptopp/src/sha.cpp \
cryptopp/src/cpu.cpp
cryptopp/src/cpu.cpp \
core/src/util.cpp
RESOURCES += \
gui/bitcoin.qrc

5
core/include/bignum.h

@ -7,11 +7,8 @@
#include <stdexcept>
#include <vector>
#include <openssl/bn.h>
#include <util.h>
#include "util.h"
class bignum_error : public std::runtime_error
{

171
core/include/key.h

@ -0,0 +1,171 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_KEY_H
#define BITCOIN_KEY_H
// secp160k1
// const unsigned int PRIVATE_KEY_SIZE = 192;
// const unsigned int PUBLIC_KEY_SIZE = 41;
// const unsigned int SIGNATURE_SIZE = 48;
//
// secp192k1
// const unsigned int PRIVATE_KEY_SIZE = 222;
// const unsigned int PUBLIC_KEY_SIZE = 49;
// const unsigned int SIGNATURE_SIZE = 57;
//
// secp224k1
// const unsigned int PRIVATE_KEY_SIZE = 250;
// const unsigned int PUBLIC_KEY_SIZE = 57;
// const unsigned int SIGNATURE_SIZE = 66;
//
// secp256k1:
// const unsigned int PRIVATE_KEY_SIZE = 279;
// const unsigned int PUBLIC_KEY_SIZE = 65;
// const unsigned int SIGNATURE_SIZE = 72;
//
// see www.keylength.com
// script supports up to 75 for single byte push
class key_error : public std::runtime_error
{
public:
explicit key_error(const std::string& str) : std::runtime_error(str) {}
};
// secure_allocator is defined in serialize.h
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
class CKey
{
protected:
EC_KEY* pkey;
bool fSet;
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");
fSet = false;
}
CKey(const CKey& b)
{
pkey = EC_KEY_dup(b.pkey);
if (pkey == NULL)
throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
fSet = b.fSet;
}
CKey& operator=(const CKey& b)
{
if (!EC_KEY_copy(pkey, b.pkey))
throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
fSet = b.fSet;
return (*this);
}
~CKey()
{
EC_KEY_free(pkey);
}
bool IsNull() const
{
return !fSet;
}
void MakeNewKey()
{
if (!EC_KEY_generate_key(pkey))
throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
fSet = true;
}
bool SetPrivKey(const CPrivKey& vchPrivKey)
{
const unsigned char* pbegin = &vchPrivKey[0];
if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
return false;
fSet = true;
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;
fSet = true;
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)
{
// -1 = error, 0 = bad sig, 1 = good
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);
}
};
#endif

2059
core/include/main.h

File diff suppressed because it is too large

1046
core/include/net.h

File diff suppressed because it is too large

3
core/include/serialize.h

@ -9,6 +9,9 @@
#include <map>
#include <set>
#include <cassert>
#include <climits>
#include <cstring>
#include <cstdio>
#include <boost/type_traits/is_fundamental.hpp>
#include <boost/tuple/tuple.hpp>

86
core/include/strlcpy.h

@ -0,0 +1,86 @@
/*
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef BITCOIN_STRLCPY_H
#define BITCOIN_STRLCPY_H
/*
* Copy src to string dst of size siz. At most siz-1 characters
* will be copied. Always NUL terminates (unless siz == 0).
* Returns strlen(src); if retval >= siz, truncation occurred.
*/
inline size_t strlcpy(char *dst, const char *src, size_t siz)
{
char *d = dst;
const char *s = src;
size_t n = siz;
/* Copy as many bytes as will fit */
if (n != 0)
{
while (--n != 0)
{
if ((*d++ = *s++) == '\0')
break;
}
}
/* Not enough room in dst, add NUL and traverse rest of src */
if (n == 0)
{
if (siz != 0)
*d = '\0'; /* NUL-terminate dst */
while (*s++)
;
}
return(s - src - 1); /* count does not include NUL */
}
/*
* Appends src to string dst of size siz (unlike strncat, siz is the
* full size of dst, not space left). At most siz-1 characters
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
* If retval >= siz, truncation occurred.
*/
inline size_t strlcat(char *dst, const char *src, size_t siz)
{
char *d = dst;
const char *s = src;
size_t n = siz;
size_t dlen;
/* Find the end of dst and adjust bytes left but don't go past end */
while (n-- != 0 && *d != '\0')
d++;
dlen = d - dst;
n = siz - dlen;
if (n == 0)
return(dlen + strlen(s));
while (*s != '\0')
{
if (n != 1)
{
*d++ = *s;
n--;
}
s++;
}
*d = '\0';
return(dlen + (s - src)); /* count does not include NUL */
}
#endif

2
core/include/util.h

@ -14,6 +14,7 @@
#include <vector>
#include <string>
#include <boost/foreach.hpp>
#include <boost/thread.hpp>
#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
#include <boost/date_time/gregorian/gregorian_types.hpp>
@ -37,7 +38,6 @@ typedef unsigned long long uint64;
#define __forceinline inline
#endif
//#define foreach BOOST_FOREACH
#define loop for (;;)
#define BEGIN(a) ((char*)&(a))
#define END(a) ((char*)&((&(a))[1]))

917
core/src/util.cpp

@ -0,0 +1,917 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
#define __STDC_LIMIT_MACROS // to enable UINT64_MAX from stdint.h
#include "util.h"
#include "main.h"
#include "strlcpy.h"
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <openssl/crypto.h>
#include <openssl/rand.h>
#include <stdint.h>
#include <climits>
using namespace std;
map<string, string> mapArgs;
map<string, vector<string> > mapMultiArgs;
bool fDebug = false;
bool fPrintToConsole = false;
bool fPrintToDebugger = false;
char pszSetDataDir[MAX_PATH] = "";
bool fRequestShutdown = false;
bool fShutdown = false;
bool fDaemon = false;
bool fServer = false;
bool fCommandLine = false;
string strMiscWarning;
bool fTestNet = false;
bool fNoListen = false;
bool fLogTimestamps = false;
// Workaround for "multiple definition of `_tls_used'"
// http://svn.boost.org/trac/boost/ticket/4258
extern "C" void tss_cleanup_implemented() { }
// Init openssl library multithreading support
static boost::interprocess::interprocess_mutex** ppmutexOpenSSL;
void locking_callback(int mode, int i, const char* file, int line)
{
if (mode & CRYPTO_LOCK)
ppmutexOpenSSL[i]->lock();
else
ppmutexOpenSSL[i]->unlock();
}
// Init
class CInit
{
public:
CInit()
{
// Init openssl library multithreading support
ppmutexOpenSSL = (boost::interprocess::interprocess_mutex**)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(boost::interprocess::interprocess_mutex*));
for (int i = 0; i < CRYPTO_num_locks(); i++)
ppmutexOpenSSL[i] = new boost::interprocess::interprocess_mutex();
CRYPTO_set_locking_callback(locking_callback);
#ifdef __WXMSW__
// Seed random number generator with screen scrape and other hardware sources
RAND_screen();
#endif
// Seed random number generator with performance counter
RandAddSeed();
}
~CInit()
{
// Shutdown openssl library multithreading support
CRYPTO_set_locking_callback(NULL);
for (int i = 0; i < CRYPTO_num_locks(); i++)
delete ppmutexOpenSSL[i];
OPENSSL_free(ppmutexOpenSSL);
}
}
instance_of_cinit;
void RandAddSeed()
{
// Seed with CPU performance counter
int64 nCounter = GetPerformanceCounter();
RAND_add(&nCounter, sizeof(nCounter), 1.5);
memset(&nCounter, 0, sizeof(nCounter));
}
void RandAddSeedPerfmon()
{
RandAddSeed();
// This can take up to 2 seconds, so only do it every 10 minutes
static int64 nLastPerfmon;
if (GetTime() < nLastPerfmon + 10 * 60)
return;
nLastPerfmon = GetTime();
#ifdef __WXMSW__
// Don't need this on Linux, OpenSSL automatically uses /dev/urandom
// Seed with the entire set of perfmon data
unsigned char pdata[250000];
memset(pdata, 0, sizeof(pdata));
unsigned long nSize = sizeof(pdata);
long ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize);
RegCloseKey(HKEY_PERFORMANCE_DATA);
if (ret == ERROR_SUCCESS)
{
RAND_add(pdata, nSize, nSize/100.0);
memset(pdata, 0, nSize);
printf("%s RandAddSeed() %d bytes\n", DateTimeStrFormat("%x %H:%M", GetTime()).c_str(), nSize);
}
#endif
}
uint64 GetRand(uint64 nMax)
{
if (nMax == 0)
return 0;
// The range of the random source must be a multiple of the modulus
// to give every possible output value an equal possibility
uint64 nRange = (UINT64_MAX / nMax) * nMax;
uint64 nRand = 0;
do
RAND_bytes((unsigned char*)&nRand, sizeof(nRand));
while (nRand >= nRange);
return (nRand % nMax);
}
int GetRandInt(int nMax)
{
return GetRand(nMax);
}
inline int OutputDebugStringF(const char* pszFormat, ...)
{
int ret = 0;
if (fPrintToConsole)
{
// print to console
va_list arg_ptr;
va_start(arg_ptr, pszFormat);
ret = vprintf(pszFormat, arg_ptr);
va_end(arg_ptr);
}
else
{
// print to debug.log
static FILE* fileout = NULL;
if (!fileout)
{
char pszFile[MAX_PATH+100];
GetDataDir(pszFile);
strlcat(pszFile, "/debug.log", sizeof(pszFile));
fileout = fopen(pszFile, "a");
if (fileout) setbuf(fileout, NULL); // unbuffered
}
if (fileout)
{
static bool fStartedNewLine = true;
// Debug print useful for profiling
if (fLogTimestamps && fStartedNewLine)
fprintf(fileout, "%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
if (pszFormat[strlen(pszFormat) - 1] == '\n')
fStartedNewLine = true;
else
fStartedNewLine = false;
va_list arg_ptr;
va_start(arg_ptr, pszFormat);
ret = vfprintf(fileout, pszFormat, arg_ptr);
va_end(arg_ptr);
}
}
#ifdef __WXMSW__
if (fPrintToDebugger)
{
static CCriticalSection cs_OutputDebugStringF;
// accumulate a line at a time
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';
OutputDebugStringA(p1);
*p2 = c;
p1 = p2;
}
if (p1 != pszBuffer)
memmove(pszBuffer, p1, pend - p1 + 1);
pend -= (p1 - pszBuffer);
}
}
#endif
return ret;
}
// Safer snprintf
// - prints up to limit-1 characters
// - output string is always null terminated even if limit reached
// - return value is the number of characters actually printed
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();
}
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 ParseString(const string& str, char c, vector<string>& v)
{
if (str.empty())
return;
string::size_type i1 = 0;
string::size_type i2;
loop
{
i2 = str.find(c, i1);
if (i2 == str.npos)
{
v.push_back(str.substr(i1));
return;
}
v.push_back(str.substr(i1, i2-i1));
i1 = i2+1;
}
}
string FormatMoney(int64 n, bool fPlus)
{
// Note: not using straight sprintf here because we do NOT want
// localized number formatting.
int64 n_abs = (n > 0 ? n : -n);
int64 quotient = n_abs/COIN;
int64 remainder = n_abs%COIN;
string str = strprintf("%"PRI64d".%08"PRI64d, quotient, remainder);
// Right-trim excess 0's before the decimal point:
int nTrim = 0;
for (int i = str.size()-1; (str[i] == '0' && isdigit(str[i-2])); --i)
++nTrim;
if (nTrim)
str.erase(str.size()-nTrim, nTrim);
// Insert thousands-separators:
size_t point = str.find(".");
for (int i = (str.size()-point)+3; 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 string& str, int64& nRet)
{
return ParseMoney(str.c_str(), nRet);
}
bool ParseMoney(const char* pszIn, int64& nRet)
{
string strWhole;
int64 nUnits = 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++;
int64 nMult = CENT*10;
while (isdigit(*p) && (nMult > 0))
{
nUnits += nMult * (*p++ - '0');
nMult /= 10;
}
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() > 14)
return false;
if (nUnits < 0 || nUnits > COIN)
return false;
int64 nWhole = atoi64(strWhole);
int64 nValue = nWhole*COIN + nUnits;
nRet = nValue;
return true;
}
vector<unsigned char> ParseHex(const char* psz)
{
static char phexdigit[256] =
{ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,
-1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, };
// convert hex dump to vector
vector<unsigned char> vch;
loop
{
while (isspace(*psz))
psz++;
char c = phexdigit[(unsigned char)*psz++];
if (c == (char)-1)
break;
unsigned char n = (c << 4);
c = phexdigit[(unsigned char)*psz++];
if (c == (char)-1)
break;
n |= c;
vch.push_back(n);
}
return vch;
}
vector<unsigned char> ParseHex(const string& str)
{
return ParseHex(str.c_str());
}
void ParseParameters(int argc, char* argv[])
{
mapArgs.clear();
mapMultiArgs.clear();
for (int i = 1; i < argc; i++)
{
char psz[10000];
strlcpy(psz, argv[i], sizeof(psz));
char* pszValue = (char*)"";
if (strchr(psz, '='))
{
pszValue = strchr(psz, '=');
*pszValue++ = '\0';
}
#ifdef __WXMSW__
_strlwr(psz);
if (psz[0] == '/')
psz[0] = '-';
#endif
if (psz[0] != '-')
break;
mapArgs[psz] = pszValue;
mapMultiArgs[psz].push_back(pszValue);
}
}
const char* wxGetTranslation(const char* pszEnglish)
{
#ifdef GUI
// Wrapper of wxGetTranslation returning the same const char* type as was passed in
static CCriticalSection cs;
CRITICAL_BLOCK(cs)
{
// Look in cache
static map<string, char*> mapCache;
map<string, char*>::iterator mi = mapCache.find(pszEnglish);
if (mi != mapCache.end())
return (*mi).second;
// wxWidgets translation
wxString strTranslated = wxGetTranslation(wxString(pszEnglish, wxConvUTF8));
// We don't cache unknown strings because caller might be passing in a
// dynamic string and we would keep allocating memory for each variation.
if (strcmp(pszEnglish, strTranslated.utf8_str()) == 0)
return pszEnglish;
// Add to cache, memory doesn't need to be freed. We only cache because
// we must pass back a pointer to permanently allocated memory.
char* pszCached = new char[strlen(strTranslated.utf8_str())+1];
strcpy(pszCached, strTranslated.utf8_str());
mapCache[pszEnglish] = pszCached;
return pszCached;
}
return NULL;
#else
return pszEnglish;
#endif
}
bool WildcardMatch(const char* psz, const char* mask)
{
loop
{
switch (*mask)
{
case '\0':
return (*psz == '\0');
case '*':
return WildcardMatch(psz, mask+1) || (*psz && WildcardMatch(psz+1, mask));
case '?':
if (*psz == '\0')
return false;
break;
default:
if (*psz != *mask)
return false;
break;
}
psz++;
mask++;
}
}
bool WildcardMatch(const string& str, const string& mask)
{
return WildcardMatch(str.c_str(), mask.c_str());
}
void FormatException(char* pszMessage, std::exception* pex, const char* pszThread)
{
#ifdef __WXMSW__
char pszModule[MAX_PATH];
pszModule[0] = '\0';
GetModuleFileNameA(NULL, pszModule, sizeof(pszModule));
#else
const char* pszModule = "bitcoin";
#endif
if (pex)
snprintf(pszMessage, 1000,
"EXCEPTION: %s \n%s \n%s in %s \n", typeid(*pex).name(), pex->what(), pszModule, pszThread);
else
snprintf(pszMessage, 1000,
"UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread);
}
void LogException(std::exception* pex, const char* pszThread)
{
char pszMessage[10000];
FormatException(pszMessage, pex, pszThread);
printf("\n%s", pszMessage);
}
void PrintException(std::exception* pex, const char* pszThread)
{
char pszMessage[10000];
FormatException(pszMessage, pex, pszThread);
printf("\n\n************************\n%s\n", pszMessage);
fprintf(stderr, "\n\n************************\n%s\n", pszMessage);
strMiscWarning = pszMessage;
#ifdef GUI
if (wxTheApp && !fDaemon)
MyMessageBox(pszMessage, "Bitcoin", wxOK | wxICON_ERROR);
#endif
throw;
}
void ThreadOneMessageBox(string strMessage)
{
// Skip message boxes if one is already open
static bool fMessageBoxOpen;
if (fMessageBoxOpen)
return;
fMessageBoxOpen = true;
ThreadSafeMessageBox(strMessage, "Bitcoin", wxOK | wxICON_EXCLAMATION);
fMessageBoxOpen = false;
}
void PrintExceptionContinue(std::exception* pex, const char* pszThread)
{
char pszMessage[10000];
FormatException(pszMessage, pex, pszThread);
printf("\n\n************************\n%s\n", pszMessage);
fprintf(stderr, "\n\n************************\n%s\n", pszMessage);
strMiscWarning = pszMessage;
#ifdef GUI
if (wxTheApp && !fDaemon)
boost::thread(boost::bind(ThreadOneMessageBox, string(pszMessage)));
#endif
}
#ifdef __WXMSW__
typedef WINSHELLAPI BOOL (WINAPI *PSHGETSPECIALFOLDERPATHA)(HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate);
string MyGetSpecialFolderPath(int nFolder, bool fCreate)
{
char pszPath[MAX_PATH+100] = "";
// SHGetSpecialFolderPath isn't always available on old Windows versions
HMODULE hShell32 = LoadLibraryA("shell32.dll");
if (hShell32)
{
PSHGETSPECIALFOLDERPATHA pSHGetSpecialFolderPath =
(PSHGETSPECIALFOLDERPATHA)GetProcAddress(hShell32, "SHGetSpecialFolderPathA");
if (pSHGetSpecialFolderPath)
(*pSHGetSpecialFolderPath)(NULL, pszPath, nFolder, fCreate);
FreeModule(hShell32);
}
// Backup option
if (pszPath[0] == '\0')
{
if (nFolder == CSIDL_STARTUP)
{
strcpy(pszPath, getenv("USERPROFILE"));
strcat(pszPath, "\\Start Menu\\Programs\\Startup");
}
else if (nFolder == CSIDL_APPDATA)
{
strcpy(pszPath, getenv("APPDATA"));
}
}
return pszPath;
}
#endif
string GetDefaultDataDir()
{
// Windows: C:\Documents and Settings\username\Application Data\Bitcoin
// Mac: ~/Library/Application Support/Bitcoin
// Unix: ~/.bitcoin
#ifdef __WXMSW__
// Windows
return MyGetSpecialFolderPath(CSIDL_APPDATA, true) + "\\Bitcoin";
#else
char* pszHome = getenv("HOME");
if (pszHome == NULL || strlen(pszHome) == 0)
pszHome = (char*)"/";
string strHome = pszHome;
if (strHome[strHome.size()-1] != '/')
strHome += '/';
#ifdef __WXMAC_OSX__
// Mac
strHome += "Library/Application Support/";
filesystem::create_directory(strHome.c_str());
return strHome + "Bitcoin";
#else
// Unix
return strHome + ".bitcoin";
#endif
#endif
}
void GetDataDir(char* pszDir)
{
// pszDir must be at least MAX_PATH length.
int nVariation;
if (pszSetDataDir[0] != 0)
{
strlcpy(pszDir, pszSetDataDir, MAX_PATH);
nVariation = 0;
}
else
{
// This can be called during exceptions by printf, so we cache the
// value so we don't have to do memory allocations after that.
static char pszCachedDir[MAX_PATH];
if (pszCachedDir[0] == 0)
strlcpy(pszCachedDir, GetDefaultDataDir().c_str(), sizeof(pszCachedDir));
strlcpy(pszDir, pszCachedDir, MAX_PATH);
nVariation = 1;
}
if (fTestNet)
{
char* p = pszDir + strlen(pszDir);
if (p > pszDir && p[-1] != '/' && p[-1] != '\\')
*p++ = '/';
strcpy(p, "testnet");
nVariation += 2;
}
static bool pfMkdir[4];
if (!pfMkdir[nVariation])
{
pfMkdir[nVariation] = true;
filesystem::create_directory(pszDir);
}
}
string GetDataDir()
{
char pszDir[MAX_PATH];
GetDataDir(pszDir);
return pszDir;
}
string GetConfigFile()
{
namespace fs = boost::filesystem;
fs::path pathConfig(GetArg("-conf", "bitcoin.conf"));
if (!pathConfig.is_complete())
pathConfig = fs::path(GetDataDir()) / pathConfig;
return pathConfig.string();
}
void ReadConfigFile(map<string, string>& mapSettingsRet,
map<string, vector<string> >& mapMultiSettingsRet)
{
namespace fs = boost::filesystem;
namespace pod = boost::program_options::detail;
fs::ifstream streamConfig(GetConfigFile());
if (!streamConfig.good())
return;
set<string> setOptions;
setOptions.insert("*");
for (pod::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
{
// Don't overwrite existing settings so command line settings override bitcoin.conf
string strKey = string("-") + it->string_key;
if (mapSettingsRet.count(strKey) == 0)
mapSettingsRet[strKey] = it->value[0];
mapMultiSettingsRet[strKey].push_back(it->value[0]);
}
}
string GetPidFile()
{
namespace fs = boost::filesystem;
fs::path pathConfig(GetArg("-pid", "bitcoind.pid"));
if (!pathConfig.is_complete())
pathConfig = fs::path(GetDataDir()) / pathConfig;
return pathConfig.string();
}
void CreatePidFile(string pidFile, pid_t pid)
{
FILE* file;
if (file = fopen(pidFile.c_str(), "w"))
{
fprintf(file, "%d\n", pid);
fclose(file);
}
}
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;
}
void ShrinkDebugFile()
{
// Scroll debug.log if it's getting too big
string strFile = GetDataDir() + "/debug.log";
FILE* file = fopen(strFile.c_str(), "r");
if (file && GetFilesize(file) > 10 * 1000000)
{
// Restart the file with some of the end
char pch[200000];
fseek(file, -sizeof(pch), SEEK_END);
int nBytes = fread(pch, 1, sizeof(pch), file);
fclose(file);
if (file = fopen(strFile.c_str(), "w"))
{
fwrite(pch, 1, nBytes, file);
fclose(file);
}
}
}
//
// "Never go to sea with two chronometers; take one or three."
// Our three time sources are:
// - System clock
// - Median of other nodes's clocks
// - The user (asking the user to fix the system clock if the first two disagree)
//
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();
// Ignore duplicates
static set<unsigned int> setKnown;
if (!setKnown.insert(ip).second)
return;
// Add data
static vector<int64> vTimeOffsets;
if (vTimeOffsets.empty())
vTimeOffsets.push_back(0);
vTimeOffsets.push_back(nOffsetSample);
printf("Added time data, samples %d, offset %+"PRI64d" (%+"PRI64d" minutes)\n", vTimeOffsets.size(), vTimeOffsets.back(), vTimeOffsets.back()/60);
if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
{
sort(vTimeOffsets.begin(), vTimeOffsets.end());
int64 nMedian = vTimeOffsets[vTimeOffsets.size()/2];
// Only let other nodes change our time by so much
if (abs64(nMedian) < 70 * 60)
{
nTimeOffset = nMedian;
}
else
{
nTimeOffset = 0;
static bool fDone;
if (!fDone)
{
// If nobody has a time different than ours but within 5 minutes of ours, give a warning
bool fMatch = false;
foreach(int64 nOffset, vTimeOffsets)
if (nOffset != 0 && abs64(nOffset) < 5 * 60)
fMatch = true;
if (!fMatch)
{
fDone = true;
string strMessage = _("Warning: Please check that your computer's date and time are correct. If your clock is wrong Bitcoin will not work properly.");
strMiscWarning = strMessage;
printf("*** %s\n", strMessage.c_str());
boost::thread(boost::bind(ThreadSafeMessageBox, strMessage+" ", string("Bitcoin"), wxOK | wxICON_EXCLAMATION, (wxWindow*)NULL, -1, -1));
}
}
}
foreach(int64 n, vTimeOffsets)
printf("%+"PRI64d" ", n);
printf("| nTimeOffset = %+"PRI64d" (%+"PRI64d" minutes)\n", nTimeOffset, nTimeOffset/60);
}
}
string FormatVersion(int nVersion)
{
if (nVersion%100 == 0)
return strprintf("%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100);
else
return strprintf("%d.%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100, nVersion%100);
}
string FormatFullVersion()
{
string s = FormatVersion(VERSION) + pszSubVer;
if (VERSION_IS_BETA)
s += _("-beta");
return s;
}

2
gui/include/bitcoinaddressvalidator.h

@ -3,8 +3,6 @@
#include <QRegExpValidator>
#include <base58.h>
class BitcoinAddressValidator : public QRegExpValidator
{
Q_OBJECT

13
gui/src/sendcoinsdialog.cpp

@ -7,6 +7,8 @@
#include <QApplication>
#include <QClipboard>
#include "base58.h"
SendCoinsDialog::SendCoinsDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::SendCoinsDialog)
@ -24,7 +26,16 @@ SendCoinsDialog::~SendCoinsDialog()
void SendCoinsDialog::on_sendButton_clicked()
{
accept();
QByteArray payTo = ui->payTo->text().toUtf8();
uint160 payToHash = 0;
if(AddressToHash160(payTo.constData(), payToHash))
{
accept();
}
else
{
}
}
void SendCoinsDialog::on_pasteButton_clicked()

Loading…
Cancel
Save