mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-28 02:46:31 +01:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
910bd45756 | ||
|
|
838e8c9166 | ||
|
|
e2a186af10 | ||
|
|
461764cbbe | ||
|
|
3b8848fa4e | ||
|
|
3cac997e19 | ||
|
|
c891967b6f | ||
|
|
c285051c08 | ||
|
|
2ce73dbe85 | ||
|
|
d9c6b09ac4 | ||
|
|
2ea5fa0710 | ||
|
|
5cbf75324d | ||
|
|
2fad3d34b7 | ||
|
|
77cd030ac3 | ||
|
|
ed54768f5f | ||
|
|
83082f04a4 | ||
|
|
103849419a | ||
|
|
0a27bd065e | ||
|
|
b22c884231 | ||
|
|
dc8adc3b48 |
2
base58.h
2
base58.h
@@ -152,7 +152,7 @@ inline bool DecodeBase58Check(const string& str, vector<unsigned char>& vchRet)
|
||||
|
||||
|
||||
|
||||
static const unsigned char ADDRESSVERSION = 0;
|
||||
#define ADDRESSVERSION ((unsigned char)(fTestNet ? 111 : 0))
|
||||
|
||||
inline string Hash160ToAddress(uint160 hash160)
|
||||
{
|
||||
|
||||
@@ -12,12 +12,8 @@ WINDOWS BUILD NOTES
|
||||
Compilers Supported
|
||||
-------------------
|
||||
MinGW GCC (recommended)
|
||||
|
||||
MSVC 6.0 SP6: You'll need Boost version 1.34 because they dropped support
|
||||
for MSVC 6.0 after that. However, they didn't add Asio until 1.35.
|
||||
You should still be able to build with MSVC 6.0 by adding Asio to 1.34 by
|
||||
unpacking boost_asio_*.zip into the boost directory:
|
||||
http://sourceforge.net/projects/asio/files/asio
|
||||
http://tdm-gcc.tdragon.net/ has an easy installer. Go back a few versions
|
||||
for a little older gcc like gcc 4.4.?.
|
||||
|
||||
MSVC 8.0 (2005) SP1 has been tested. Note: MSVC 7.0 and up have a habit of
|
||||
linking to runtime DLLs that are not installed on XP by default.
|
||||
@@ -67,8 +63,7 @@ nmake -f makefile.vc
|
||||
|
||||
OpenSSL
|
||||
-------
|
||||
Bitcoin does not use any encryption. If you want to do a no-everything
|
||||
build of OpenSSL to exclude encryption routines, a few patches are required.
|
||||
If you want to exclude unused optional algorithms, a few patches are required.
|
||||
(instructions for OpenSSL v0.9.8k)
|
||||
|
||||
Edit engines\e_gmp.c and engines\e_capi.c and add this #ifndef around
|
||||
@@ -92,7 +87,7 @@ Build
|
||||
cd \openssl
|
||||
ms\mingw32.bat
|
||||
|
||||
If you want to use it with MSVC, generate the .lib file
|
||||
If you're using MSVC, generate the .lib file
|
||||
lib /machine:i386 /def:ms\libeay32.def /out:out\libeay32.lib
|
||||
|
||||
|
||||
|
||||
91
db.cpp
91
db.cpp
@@ -503,6 +503,11 @@ bool CAddrDB::WriteAddress(const CAddress& addr)
|
||||
return Write(make_pair(string("addr"), addr.GetKey()), addr);
|
||||
}
|
||||
|
||||
bool CAddrDB::EraseAddress(const CAddress& addr)
|
||||
{
|
||||
return Erase(make_pair(string("addr"), addr.GetKey()));
|
||||
}
|
||||
|
||||
bool CAddrDB::LoadAddresses()
|
||||
{
|
||||
CRITICAL_BLOCK(cs_mapAddresses)
|
||||
@@ -554,11 +559,6 @@ bool CAddrDB::LoadAddresses()
|
||||
pcursor->close();
|
||||
|
||||
printf("Loaded %d addresses\n", mapAddresses.size());
|
||||
|
||||
// Fix for possible bug that manifests in mapAddresses.count in irc.cpp,
|
||||
// just need to call count here and it doesn't happen there. The bug was the
|
||||
// pack pragma in irc.cpp and has been fixed, but I'm not in a hurry to delete this.
|
||||
mapAddresses.count(vector<unsigned char>(18));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -576,6 +576,9 @@ bool LoadAddresses()
|
||||
// CWalletDB
|
||||
//
|
||||
|
||||
static set<int64> setKeyPool;
|
||||
static CCriticalSection cs_setKeyPool;
|
||||
|
||||
bool CWalletDB::LoadWallet()
|
||||
{
|
||||
vchDefaultKey.clear();
|
||||
@@ -654,6 +657,12 @@ bool CWalletDB::LoadWallet()
|
||||
{
|
||||
ssValue >> vchDefaultKey;
|
||||
}
|
||||
else if (strType == "pool")
|
||||
{
|
||||
int64 nIndex;
|
||||
ssKey >> nIndex;
|
||||
setKeyPool.insert(nIndex);
|
||||
}
|
||||
else if (strType == "version")
|
||||
{
|
||||
ssValue >> nFileVersion;
|
||||
@@ -836,3 +845,75 @@ void BackupWallet(const string& strDest)
|
||||
Sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CWalletDB::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
|
||||
{
|
||||
nIndex = -1;
|
||||
keypool.vchPubKey.clear();
|
||||
CRITICAL_BLOCK(cs_main)
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
CRITICAL_BLOCK(cs_setKeyPool)
|
||||
{
|
||||
// Top up key pool
|
||||
int64 nTargetSize = max(GetArg("-keypool", 100), (int64)0);
|
||||
while (setKeyPool.size() < nTargetSize+1)
|
||||
{
|
||||
int64 nEnd = 1;
|
||||
if (!setKeyPool.empty())
|
||||
nEnd = *(--setKeyPool.end()) + 1;
|
||||
if (!Write(make_pair(string("pool"), nEnd), CKeyPool(GenerateNewKey())))
|
||||
throw runtime_error("ReserveKeyFromKeyPool() : writing generated key failed");
|
||||
setKeyPool.insert(nEnd);
|
||||
printf("keypool added key %"PRI64d", size=%d\n", nEnd, setKeyPool.size());
|
||||
}
|
||||
|
||||
// Get the oldest key
|
||||
assert(!setKeyPool.empty());
|
||||
nIndex = *(setKeyPool.begin());
|
||||
setKeyPool.erase(setKeyPool.begin());
|
||||
if (!Read(make_pair(string("pool"), nIndex), keypool))
|
||||
throw runtime_error("ReserveKeyFromKeyPool() : read failed");
|
||||
if (!mapKeys.count(keypool.vchPubKey))
|
||||
throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
|
||||
assert(!keypool.vchPubKey.empty());
|
||||
printf("keypool reserve %"PRI64d"\n", nIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void CWalletDB::KeepKey(int64 nIndex)
|
||||
{
|
||||
// Remove from key pool
|
||||
CRITICAL_BLOCK(cs_main)
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
{
|
||||
Erase(make_pair(string("pool"), nIndex));
|
||||
}
|
||||
printf("keypool keep %"PRI64d"\n", nIndex);
|
||||
}
|
||||
|
||||
void CWalletDB::ReturnKey(int64 nIndex)
|
||||
{
|
||||
// Return to key pool
|
||||
CRITICAL_BLOCK(cs_setKeyPool)
|
||||
setKeyPool.insert(nIndex);
|
||||
printf("keypool return %"PRI64d"\n", nIndex);
|
||||
}
|
||||
|
||||
vector<unsigned char> CWalletDB::GetKeyFromKeyPool()
|
||||
{
|
||||
int64 nIndex = 0;
|
||||
CKeyPool keypool;
|
||||
ReserveKeyFromKeyPool(nIndex, keypool);
|
||||
KeepKey(nIndex);
|
||||
return keypool.vchPubKey;
|
||||
}
|
||||
|
||||
int64 CWalletDB::GetOldestKeyPoolTime()
|
||||
{
|
||||
int64 nIndex = 0;
|
||||
CKeyPool keypool;
|
||||
ReserveKeyFromKeyPool(nIndex, keypool);
|
||||
ReturnKey(nIndex);
|
||||
return keypool.nTime;
|
||||
}
|
||||
|
||||
84
db.h
84
db.h
@@ -298,6 +298,7 @@ private:
|
||||
void operator=(const CAddrDB&);
|
||||
public:
|
||||
bool WriteAddress(const CAddress& addr);
|
||||
bool EraseAddress(const CAddress& addr);
|
||||
bool LoadAddresses();
|
||||
};
|
||||
|
||||
@@ -308,6 +309,35 @@ bool LoadAddresses();
|
||||
|
||||
|
||||
|
||||
class CKeyPool
|
||||
{
|
||||
public:
|
||||
int64 nTime;
|
||||
vector<unsigned char> vchPubKey;
|
||||
|
||||
CKeyPool()
|
||||
{
|
||||
nTime = GetTime();
|
||||
}
|
||||
|
||||
CKeyPool(const vector<unsigned char>& vchPubKeyIn)
|
||||
{
|
||||
nTime = GetTime();
|
||||
vchPubKey = vchPubKeyIn;
|
||||
}
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
if (!(nType & SER_GETHASH))
|
||||
READWRITE(nVersion);
|
||||
READWRITE(nTime);
|
||||
READWRITE(vchPubKey);
|
||||
)
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class CWalletDB : public CDB
|
||||
{
|
||||
public:
|
||||
@@ -396,6 +426,14 @@ public:
|
||||
}
|
||||
|
||||
bool LoadWallet();
|
||||
protected:
|
||||
void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool);
|
||||
void KeepKey(int64 nIndex);
|
||||
static void ReturnKey(int64 nIndex);
|
||||
friend class CReserveKey;
|
||||
public:
|
||||
vector<unsigned char> GetKeyFromKeyPool();
|
||||
int64 GetOldestKeyPoolTime();
|
||||
};
|
||||
|
||||
bool LoadWallet(bool& fFirstRunRet);
|
||||
@@ -405,3 +443,49 @@ inline bool SetAddressBookName(const string& strAddress, const string& strName)
|
||||
{
|
||||
return CWalletDB().WriteName(strAddress, strName);
|
||||
}
|
||||
|
||||
class CReserveKey
|
||||
{
|
||||
protected:
|
||||
int64 nIndex;
|
||||
vector<unsigned char> vchPubKey;
|
||||
public:
|
||||
CReserveKey()
|
||||
{
|
||||
nIndex = -1;
|
||||
}
|
||||
|
||||
~CReserveKey()
|
||||
{
|
||||
if (!fShutdown)
|
||||
ReturnKey();
|
||||
}
|
||||
|
||||
vector<unsigned char> GetReservedKey()
|
||||
{
|
||||
if (nIndex == -1)
|
||||
{
|
||||
CKeyPool keypool;
|
||||
CWalletDB().ReserveKeyFromKeyPool(nIndex, keypool);
|
||||
vchPubKey = keypool.vchPubKey;
|
||||
}
|
||||
assert(!vchPubKey.empty());
|
||||
return vchPubKey;
|
||||
}
|
||||
|
||||
void KeepKey()
|
||||
{
|
||||
if (nIndex != -1)
|
||||
CWalletDB().KeepKey(nIndex);
|
||||
nIndex = -1;
|
||||
vchPubKey.clear();
|
||||
}
|
||||
|
||||
void ReturnKey()
|
||||
{
|
||||
if (nIndex != -1)
|
||||
CWalletDB::ReturnKey(nIndex);
|
||||
nIndex = -1;
|
||||
vchPubKey.clear();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include <db_cxx.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#include <float.h>
|
||||
@@ -70,6 +71,7 @@
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/interprocess/sync/file_lock.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_mutex.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
|
||||
#include <boost/date_time/gregorian/gregorian_types.hpp>
|
||||
|
||||
61
init.cpp
61
init.cpp
@@ -165,17 +165,35 @@ bool AppInit2(int argc, char* argv[])
|
||||
" bitcoin [options] help \t\t " + _("List commands\n") +
|
||||
" bitcoin [options] help <command> \t\t " + _("Get help for a command\n") +
|
||||
_("Options:\n") +
|
||||
" -conf=<file> \t " + _("Specify configuration file (default: bitcoin.conf)\n") +
|
||||
" -gen \t " + _("Generate coins\n") +
|
||||
" -gen=0 \t " + _("Don't generate coins\n") +
|
||||
" -min \t " + _("Start minimized\n") +
|
||||
" -datadir=<dir> \t " + _("Specify data directory\n") +
|
||||
" -proxy=<ip:port>\t " + _("Connect through socks4 proxy\n") +
|
||||
" -addnode=<ip> \t " + _("Add a node to connect to\n") +
|
||||
" -connect=<ip> \t " + _("Connect only to the specified node\n") +
|
||||
" -server \t " + _("Accept command line and JSON-RPC commands\n") +
|
||||
" -daemon \t " + _("Run in the background as a daemon and accept commands\n") +
|
||||
" -? \t " + _("This help message\n");
|
||||
" -conf=<file> \t\t " + _("Specify configuration file (default: bitcoin.conf)\n") +
|
||||
" -gen \t\t " + _("Generate coins\n") +
|
||||
" -gen=0 \t\t " + _("Don't generate coins\n") +
|
||||
" -min \t\t " + _("Start minimized\n") +
|
||||
" -datadir=<dir> \t\t " + _("Specify data directory\n") +
|
||||
" -proxy=<ip:port> \t " + _("Connect through socks4 proxy\n") +
|
||||
" -addnode=<ip> \t " + _("Add a node to connect to\n") +
|
||||
" -connect=<ip> \t\t " + _("Connect only to the specified node\n") +
|
||||
" -paytxfee=<amt> \t " + _("Fee per KB to add to transactions you send\n") +
|
||||
" -server \t\t " + _("Accept command line and JSON-RPC commands\n") +
|
||||
" -daemon \t\t " + _("Run in the background as a daemon and accept commands\n") +
|
||||
" -testnet \t\t " + _("Use the test network\n") +
|
||||
" -rpcuser=<user> \t " + _("Username for JSON-RPC connections\n") +
|
||||
" -rpcpassword=<pw>\t " + _("Password for JSON-RPC connections\n") +
|
||||
" -rpcport=<port> \t\t " + _("Listen for JSON-RPC connections on <port>\n") +
|
||||
" -rpcallowip=<ip> \t\t " + _("Allow JSON-RPC connections from specified IP address\n") +
|
||||
" -rpcconnect=<ip> \t " + _("Send commands to node running on <ip>\n");
|
||||
|
||||
#ifdef USE_SSL
|
||||
strUsage += string() +
|
||||
_("\nSSL options: (see the Bitcoin Wiki for SSL setup instructions)\n") +
|
||||
" -rpcssl=1 \t " + _("Use OpenSSL (https) for JSON-RPC connections\n") +
|
||||
" -rpcsslcertificatchainfile=<file.cert>\t " + _("Server certificate file (default: server.cert)\n") +
|
||||
" -rpcsslprivatekeyfile=<file.pem> \t " + _("Server private key (default: server.pem)\n") +
|
||||
" -rpcsslciphers=<ciphers> \t " + _("Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)\n");
|
||||
#endif
|
||||
|
||||
strUsage += string() +
|
||||
" -? \t\t " + _("This help message\n");
|
||||
|
||||
#if defined(__WXMSW__) && defined(GUI)
|
||||
// Tabs make the columns line up in the message box
|
||||
@@ -194,6 +212,9 @@ bool AppInit2(int argc, char* argv[])
|
||||
if (mapArgs.count("-printtodebugger"))
|
||||
fPrintToDebugger = true;
|
||||
|
||||
if (mapArgs.count("-testnet"))
|
||||
fTestNet = true;
|
||||
|
||||
if (fCommandLine)
|
||||
{
|
||||
int ret = CommandLineRPC(argc, argv);
|
||||
@@ -224,8 +245,7 @@ bool AppInit2(int argc, char* argv[])
|
||||
// Required to protect the database files if we're going to keep deleting log.*
|
||||
//
|
||||
#if defined(__WXMSW__) && defined(GUI)
|
||||
// todo: wxSingleInstanceChecker wasn't working on Linux, never deleted its lock file
|
||||
// maybe should go by whether successfully bind port 8333 instead
|
||||
// wxSingleInstanceChecker doesn't work on Linux
|
||||
wxString strMutexName = wxString("bitcoin_running.") + getenv("HOMEPATH");
|
||||
for (int i = 0; i < strMutexName.size(); i++)
|
||||
if (!isalnum(strMutexName[i]))
|
||||
@@ -237,7 +257,6 @@ bool AppInit2(int argc, char* argv[])
|
||||
unsigned int nStart = GetTime();
|
||||
loop
|
||||
{
|
||||
// TODO: find out how to do this in Linux, or replace with wxWidgets commands
|
||||
// Show the previous instance and exit
|
||||
HWND hwndPrev = FindWindowA("wxWindowClassNR", "Bitcoin");
|
||||
if (hwndPrev)
|
||||
@@ -261,8 +280,18 @@ bool AppInit2(int argc, char* argv[])
|
||||
}
|
||||
#endif
|
||||
|
||||
// Make sure only a single bitcoin process is using the data directory.
|
||||
string strLockFile = GetDataDir() + "/.lock";
|
||||
FILE* file = fopen(strLockFile.c_str(), "a"); // empty lock file; created if it doesn't exist.
|
||||
fclose(file);
|
||||
static boost::interprocess::file_lock lock(strLockFile.c_str());
|
||||
if (!lock.try_lock())
|
||||
{
|
||||
wxMessageBox(strprintf(_("Cannot obtain a lock on data directory %s. Bitcoin is probably already running."), GetDataDir().c_str()), "Bitcoin");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bind to the port early so we can tell if another instance is already running.
|
||||
// This is a backup to wxSingleInstanceChecker, which doesn't work on Linux.
|
||||
string strErrors;
|
||||
if (!BindListenPort(strErrors))
|
||||
{
|
||||
@@ -385,7 +414,7 @@ bool AppInit2(int argc, char* argv[])
|
||||
wxMessageBox(_("Invalid amount for -paytxfee=<amount>"), "Bitcoin");
|
||||
return false;
|
||||
}
|
||||
if (nTransactionFee > 1 * COIN)
|
||||
if (nTransactionFee > 0.25 * COIN)
|
||||
wxMessageBox(_("Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction."), "Bitcoin", wxOK | wxICON_EXCLAMATION);
|
||||
}
|
||||
|
||||
|
||||
45
irc.cpp
45
irc.cpp
@@ -84,18 +84,31 @@ bool RecvLine(SOCKET hSocket, string& strLine)
|
||||
}
|
||||
else if (nBytes <= 0)
|
||||
{
|
||||
if (fShutdown)
|
||||
return false;
|
||||
if (nBytes < 0)
|
||||
{
|
||||
int nErr = WSAGetLastError();
|
||||
if (nErr == WSAEMSGSIZE)
|
||||
continue;
|
||||
if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS)
|
||||
{
|
||||
Sleep(10);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!strLine.empty())
|
||||
return true;
|
||||
// socket closed
|
||||
printf("IRC socket closed\n");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// socket error
|
||||
int nErr = WSAGetLastError();
|
||||
if (nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
|
||||
if (nBytes == 0)
|
||||
{
|
||||
// socket closed
|
||||
printf("IRC socket closed\n");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// socket error
|
||||
int nErr = WSAGetLastError();
|
||||
printf("IRC recv failed: %d\n", nErr);
|
||||
return false;
|
||||
}
|
||||
@@ -126,7 +139,7 @@ bool RecvLineIRC(SOCKET hSocket, string& strLine)
|
||||
}
|
||||
}
|
||||
|
||||
int RecvUntil(SOCKET hSocket, const char* psz1, const char* psz2=NULL, const char* psz3=NULL)
|
||||
int RecvUntil(SOCKET hSocket, const char* psz1, const char* psz2=NULL, const char* psz3=NULL, const char* psz4=NULL)
|
||||
{
|
||||
loop
|
||||
{
|
||||
@@ -141,6 +154,8 @@ int RecvUntil(SOCKET hSocket, const char* psz1, const char* psz2=NULL, const cha
|
||||
return 2;
|
||||
if (psz3 && strLine.find(psz3) != -1)
|
||||
return 3;
|
||||
if (psz4 && strLine.find(psz4) != -1)
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,7 +225,7 @@ void ThreadIRCSeed2(void* parg)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!RecvUntil(hSocket, "Found your hostname", "using your IP address instead", "Couldn't look up your hostname"))
|
||||
if (!RecvUntil(hSocket, "Found your hostname", "using your IP address instead", "Couldn't look up your hostname", "ignoring hostname"))
|
||||
{
|
||||
closesocket(hSocket);
|
||||
hSocket = INVALID_SOCKET;
|
||||
@@ -250,8 +265,8 @@ void ThreadIRCSeed2(void* parg)
|
||||
}
|
||||
Sleep(500);
|
||||
|
||||
Send(hSocket, "JOIN #bitcoin\r");
|
||||
Send(hSocket, "WHO #bitcoin\r");
|
||||
Send(hSocket, fTestNet ? "JOIN #bitcoinTEST\r" : "JOIN #bitcoin\r");
|
||||
Send(hSocket, fTestNet ? "WHO #bitcoinTEST\r" : "WHO #bitcoin\r");
|
||||
|
||||
int64 nStart = GetTime();
|
||||
string strLine;
|
||||
@@ -291,8 +306,8 @@ void ThreadIRCSeed2(void* parg)
|
||||
CAddress addr;
|
||||
if (DecodeAddress(pszName, addr))
|
||||
{
|
||||
addr.nTime = GetAdjustedTime() - 51 * 60;
|
||||
if (AddAddress(addr))
|
||||
addr.nTime = GetAdjustedTime();
|
||||
if (AddAddress(addr, 51 * 60))
|
||||
printf("IRC got new address\n");
|
||||
nGotIRCAddresses++;
|
||||
}
|
||||
|
||||
BIN
locale/ru/LC_MESSAGES/bitcoin.mo
Normal file
BIN
locale/ru/LC_MESSAGES/bitcoin.mo
Normal file
Binary file not shown.
895
locale/ru/LC_MESSAGES/bitcoin.po
Normal file
895
locale/ru/LC_MESSAGES/bitcoin.po
Normal file
@@ -0,0 +1,895 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2010-10-05 10:53+0300\n"
|
||||
"PO-Revision-Date: 2010-10-05 11:43+0300\n"
|
||||
"Last-Translator: eurekafag\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Poedit-KeywordsList: _;gettext;gettext_noop\n"
|
||||
"X-Poedit-Basepath: .\n"
|
||||
"X-Poedit-SearchPath-0: ../../..\n"
|
||||
|
||||
#: ../../../init.cpp:162
|
||||
msgid "Usage:"
|
||||
msgstr "Использование"
|
||||
|
||||
#: ../../../init.cpp:164
|
||||
msgid "Send command to -server or bitcoind\n"
|
||||
msgstr "Отправить команду bitcoin, запущенному с -server\n"
|
||||
|
||||
#: ../../../init.cpp:165
|
||||
msgid "List commands\n"
|
||||
msgstr "Список команд\n"
|
||||
|
||||
#: ../../../init.cpp:166
|
||||
msgid "Get help for a command\n"
|
||||
msgstr "Получить помощь для команды\n"
|
||||
|
||||
#: ../../../init.cpp:167
|
||||
msgid "Options:\n"
|
||||
msgstr "Параметры:\n"
|
||||
|
||||
#: ../../../init.cpp:168
|
||||
msgid "Specify configuration file (default: bitcoin.conf)\n"
|
||||
msgstr "Укажите конфигурационный файл (по умолчанию: bitcoin.conf)\n"
|
||||
|
||||
#: ../../../init.cpp:169
|
||||
msgid "Generate coins\n"
|
||||
msgstr "Генерировать монеты\n"
|
||||
|
||||
#: ../../../init.cpp:170
|
||||
msgid "Don't generate coins\n"
|
||||
msgstr "Не генерировать монеты\n"
|
||||
|
||||
#: ../../../init.cpp:171
|
||||
msgid "Start minimized\n"
|
||||
msgstr "Запускать свёрнутым\n"
|
||||
|
||||
#: ../../../init.cpp:172
|
||||
msgid "Specify data directory\n"
|
||||
msgstr "Указать каталог данных\n"
|
||||
|
||||
#: ../../../init.cpp:173
|
||||
msgid "Connect through socks4 proxy\n"
|
||||
msgstr "Подключаться через socks4 прокси\n"
|
||||
|
||||
#: ../../../init.cpp:174
|
||||
msgid "Add a node to connect to\n"
|
||||
msgstr "Добавить узел для подключения\n"
|
||||
|
||||
#: ../../../init.cpp:175
|
||||
msgid "Connect only to the specified node\n"
|
||||
msgstr "Подключаться только к указанному узлу\n"
|
||||
|
||||
#: ../../../init.cpp:176
|
||||
msgid "Accept command line and JSON-RPC commands\n"
|
||||
msgstr "Принимать команды из командной строки и через JSON-RPC\n"
|
||||
|
||||
#: ../../../init.cpp:177
|
||||
msgid "Run in the background as a daemon and accept commands\n"
|
||||
msgstr "Запустить в фоне как демон и принимать команды\n"
|
||||
|
||||
#: ../../../init.cpp:178
|
||||
msgid "This help message\n"
|
||||
msgstr "Эта справка\n"
|
||||
|
||||
#: ../../../init.cpp:284
|
||||
msgid "Error loading addr.dat \n"
|
||||
msgstr "Ошибка загрузки addr.dat \n"
|
||||
|
||||
#: ../../../init.cpp:290
|
||||
msgid "Error loading blkindex.dat \n"
|
||||
msgstr "Ошибка загрузки blkindex.dat \n"
|
||||
|
||||
#: ../../../init.cpp:297
|
||||
msgid "Error loading wallet.dat \n"
|
||||
msgstr "Ошибка загрузки wallet.dat \n"
|
||||
|
||||
#: ../../../init.cpp:365
|
||||
msgid "Invalid -proxy address"
|
||||
msgstr "Неверный адрес -proxy"
|
||||
|
||||
#: ../../../init.cpp:385
|
||||
msgid "Invalid amount for -paytxfee=<amount>"
|
||||
msgstr "Неверное значение для -paytxfee=<amount>"
|
||||
|
||||
#: ../../../init.cpp:389
|
||||
msgid "Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction."
|
||||
msgstr "Внимание: -paytxfee установлено в очень большое значение. Это комиссия, которую вы будете платить при переводе."
|
||||
|
||||
#: ../../../main.cpp:1641
|
||||
msgid "Warning: Disk space is low "
|
||||
msgstr "Внимание: мало места на диске "
|
||||
|
||||
#: ../../../main.cpp:3505
|
||||
#, c-format
|
||||
msgid "Error: This is an oversized transaction that requires a transaction fee of %s "
|
||||
msgstr "Ошибка: этот перевод слишком большого размера, который требует комиссию %s "
|
||||
|
||||
#: ../../../main.cpp:3507
|
||||
msgid "Error: Transaction creation failed "
|
||||
msgstr "Ошибка: не удалось создать перевод "
|
||||
|
||||
#: ../../../main.cpp:3512
|
||||
#: ../../../ui.cpp:1964
|
||||
#: ../../../ui.cpp:1966
|
||||
#: ../../../ui.cpp:2107
|
||||
#: ../../../ui.cpp:2260
|
||||
msgid "Sending..."
|
||||
msgstr "Отправка..."
|
||||
|
||||
#: ../../../main.cpp:3516
|
||||
msgid "Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."
|
||||
msgstr "Перевод был отклонен. Это могло произойти, если некоторые из монет в вашем кошельке уже были потрачены, например, если вы использовали копию wallet.dat, и монеты были потрачены в копии, но не отмечены израсходованными здесь."
|
||||
|
||||
#: ../../../main.cpp:3528
|
||||
msgid "Invalid amount"
|
||||
msgstr "Неверное количество"
|
||||
|
||||
#: ../../../main.cpp:3530
|
||||
#: ../../../ui.cpp:2174
|
||||
#: ../../../ui.cpp:2245
|
||||
msgid "Insufficient funds"
|
||||
msgstr "Недостаточно средств"
|
||||
|
||||
#: ../../../main.cpp:3535
|
||||
msgid "Invalid bitcoin address"
|
||||
msgstr "Неверный адрес bitcoin"
|
||||
|
||||
#: ../../../rpc.cpp:963
|
||||
#: ../../../rpc.cpp:965
|
||||
#, c-format
|
||||
msgid "To use the %s option"
|
||||
msgstr "Чтобы использовать опцию %s"
|
||||
|
||||
#: ../../../rpc.cpp:967
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Warning: %s, you must set rpcpassword=<password>\n"
|
||||
"in the configuration file: %s\n"
|
||||
"If the file does not exist, create it with owner-readable-only file permissions.\n"
|
||||
msgstr ""
|
||||
"Внимание: %s, вы должны установить rpcpassword=<пароль>\n"
|
||||
"в конфигурационном файле: %s\n"
|
||||
"Если файл не существует, создайте его с правами \"чтение только владельцем\".\n"
|
||||
|
||||
#: ../../../rpc.cpp:1100
|
||||
#, c-format
|
||||
msgid ""
|
||||
"You must set rpcpassword=<password> in the configuration file:\n"
|
||||
"%s\n"
|
||||
"If the file does not exist, create it with owner-readable-only file permissions."
|
||||
msgstr ""
|
||||
"Вы должны установить rpcpassword=<пароль> в конфигурационном файле:\n"
|
||||
"%s\n"
|
||||
"Если файл не существует, создайте его с правами \"чтение только владельцем\"."
|
||||
|
||||
#: ../../../ui.cpp:202
|
||||
#, c-format
|
||||
msgid "This transaction is over the size limit. You can still send it for a fee of %s, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee?"
|
||||
msgstr "Этот перевод превышает допустимый лимит. Вы можете провести его с комиссией %s, которую получат узлы, обрабатывающие перевод, и поможет поддерживать сеть. Вы хотите заплатить комиссию?"
|
||||
|
||||
#: ../../../ui.cpp:301
|
||||
msgid "Status"
|
||||
msgstr "Статус"
|
||||
|
||||
#: ../../../ui.cpp:302
|
||||
msgid "Date"
|
||||
msgstr "Дата"
|
||||
|
||||
#: ../../../ui.cpp:303
|
||||
msgid "Description"
|
||||
msgstr "Описание"
|
||||
|
||||
#: ../../../ui.cpp:304
|
||||
msgid "Debit"
|
||||
msgstr "Дебет"
|
||||
|
||||
#: ../../../ui.cpp:305
|
||||
msgid "Credit"
|
||||
msgstr "Кредит"
|
||||
|
||||
#: ../../../ui.cpp:511
|
||||
#, c-format
|
||||
msgid "Open for %d blocks"
|
||||
msgstr "Открыто для %d блоков"
|
||||
|
||||
#: ../../../ui.cpp:513
|
||||
#, c-format
|
||||
msgid "Open until %s"
|
||||
msgstr "Открыто до %s"
|
||||
|
||||
#: ../../../ui.cpp:519
|
||||
#, c-format
|
||||
msgid "%d/offline?"
|
||||
msgstr "%d/оффлайн?"
|
||||
|
||||
#: ../../../ui.cpp:521
|
||||
#, c-format
|
||||
msgid "%d/unconfirmed"
|
||||
msgstr "%d/не подтверждено"
|
||||
|
||||
#: ../../../ui.cpp:523
|
||||
#, c-format
|
||||
msgid "%d confirmations"
|
||||
msgstr "%d подтверждений"
|
||||
|
||||
#: ../../../ui.cpp:608
|
||||
msgid "Generated"
|
||||
msgstr "Сгенерировано"
|
||||
|
||||
#: ../../../ui.cpp:616
|
||||
#, c-format
|
||||
msgid "Generated (%s matures in %d more blocks)"
|
||||
msgstr "Сгенерировано (%s станет доступно через %d блоков)"
|
||||
|
||||
#: ../../../ui.cpp:620
|
||||
msgid "Generated - Warning: This block was not received by any other nodes and will probably not be accepted!"
|
||||
msgstr "Сгенерировано - Внимание: этот блок не был получен ни одним узлом и, скорее всего, не будет принят!"
|
||||
|
||||
#: ../../../ui.cpp:624
|
||||
msgid "Generated (not accepted)"
|
||||
msgstr "Сгенерировано (не принято)"
|
||||
|
||||
#: ../../../ui.cpp:634
|
||||
msgid "From: "
|
||||
msgstr "От: "
|
||||
|
||||
#: ../../../ui.cpp:658
|
||||
msgid "Received with: "
|
||||
msgstr "Получено для: "
|
||||
|
||||
#: ../../../ui.cpp:704
|
||||
msgid "Payment to yourself"
|
||||
msgstr "Платёж самому себе"
|
||||
|
||||
#: ../../../ui.cpp:741
|
||||
msgid "To: "
|
||||
msgstr "Кому: "
|
||||
|
||||
#: ../../../ui.cpp:1049
|
||||
msgid " Generating"
|
||||
msgstr " Генерация"
|
||||
|
||||
#: ../../../ui.cpp:1051
|
||||
msgid "(not connected)"
|
||||
msgstr "(не подключен)"
|
||||
|
||||
#: ../../../ui.cpp:1054
|
||||
#, c-format
|
||||
msgid " %d connections %d blocks %d transactions"
|
||||
msgstr " %d подключений %d блоков %d переводов"
|
||||
|
||||
#: ../../../ui.cpp:1165
|
||||
#: ../../../ui.cpp:2560
|
||||
msgid "New Receiving Address"
|
||||
msgstr "Новый адрес получения"
|
||||
|
||||
#: ../../../ui.cpp:1166
|
||||
#: ../../../ui.cpp:2561
|
||||
msgid ""
|
||||
"You should use a new address for each payment you receive.\n"
|
||||
"\n"
|
||||
"Label"
|
||||
msgstr ""
|
||||
"Вы должны использовать новый адрес для каждого получаемого платежа.\n"
|
||||
"\n"
|
||||
"Метка"
|
||||
|
||||
#: ../../../ui.cpp:1235
|
||||
msgid "<b>Status:</b> "
|
||||
msgstr "<b>Статус:</b> "
|
||||
|
||||
#: ../../../ui.cpp:1240
|
||||
msgid ", has not been successfully broadcast yet"
|
||||
msgstr ", ещё не был успешно разослан"
|
||||
|
||||
#: ../../../ui.cpp:1242
|
||||
#, c-format
|
||||
msgid ", broadcast through %d node"
|
||||
msgstr ", рассылка через %d узел"
|
||||
|
||||
#: ../../../ui.cpp:1244
|
||||
#, c-format
|
||||
msgid ", broadcast through %d nodes"
|
||||
msgstr ", рассылка через %d узлов"
|
||||
|
||||
#: ../../../ui.cpp:1248
|
||||
msgid "<b>Date:</b> "
|
||||
msgstr "<b>Дата:</b> "
|
||||
|
||||
#: ../../../ui.cpp:1256
|
||||
msgid "<b>Source:</b> Generated<br>"
|
||||
msgstr "<b>Источник:</b> Сгенерировано<br>"
|
||||
|
||||
#: ../../../ui.cpp:1262
|
||||
#: ../../../ui.cpp:1280
|
||||
msgid "<b>From:</b> "
|
||||
msgstr "<b>От:</b> "
|
||||
|
||||
#: ../../../ui.cpp:1280
|
||||
msgid "unknown"
|
||||
msgstr "аноним"
|
||||
|
||||
#: ../../../ui.cpp:1281
|
||||
#: ../../../ui.cpp:1305
|
||||
#: ../../../ui.cpp:1364
|
||||
msgid "<b>To:</b> "
|
||||
msgstr "<b>Кому:</b> "
|
||||
|
||||
#: ../../../ui.cpp:1284
|
||||
msgid " (yours, label: "
|
||||
msgstr " (ваш, метка: "
|
||||
|
||||
#: ../../../ui.cpp:1286
|
||||
msgid " (yours)"
|
||||
msgstr " (ваш)"
|
||||
|
||||
#: ../../../ui.cpp:1323
|
||||
#: ../../../ui.cpp:1335
|
||||
#: ../../../ui.cpp:1398
|
||||
msgid "<b>Credit:</b> "
|
||||
msgstr "<b>Кредит:</b> "
|
||||
|
||||
#: ../../../ui.cpp:1325
|
||||
#, c-format
|
||||
msgid "(%s matures in %d more blocks)"
|
||||
msgstr "(%s станет доступно через %d блоков)"
|
||||
|
||||
#: ../../../ui.cpp:1327
|
||||
msgid "(not accepted)"
|
||||
msgstr "(не принято)"
|
||||
|
||||
#: ../../../ui.cpp:1372
|
||||
#: ../../../ui.cpp:1395
|
||||
msgid "<b>Debit:</b> "
|
||||
msgstr "<b>Дебет:</b> "
|
||||
|
||||
#: ../../../ui.cpp:1386
|
||||
msgid "<b>Transaction fee:</b> "
|
||||
msgstr "<b>Комиссия:</b> "
|
||||
|
||||
#: ../../../ui.cpp:1402
|
||||
msgid "<b>Net amount:</b> "
|
||||
msgstr "<b>Количество сети:</b> "
|
||||
|
||||
#: ../../../ui.cpp:1409
|
||||
msgid "Message:"
|
||||
msgstr "Сообщение:"
|
||||
|
||||
#: ../../../ui.cpp:1412
|
||||
msgid "Generated coins must wait 120 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, it will change to \"not accepted\" and not be spendable. This may occasionally happen if another node generates a block within a few seconds of yours."
|
||||
msgstr "Сгенерированные монеты должны ждать 120 блоков, прежде чем они могут быть потрачены. Когда вы сгенерировали этот блок, он был разослан в сети для добавления в цепь блоков. Если не удалось добавить этот блок в цепь, он будет обозначен как \"не принятый\" и не может быть потрачен. Такое может случиться, если другой узел сгенерировал блок через несколько секунд после вас."
|
||||
|
||||
#: ../../../ui.cpp:1593
|
||||
msgid "Cannot write autostart/bitcoin.desktop file"
|
||||
msgstr "Не удаётся записать файл autostart/bitcoin.desktop"
|
||||
|
||||
#: ../../../ui.cpp:1629
|
||||
msgid "Main"
|
||||
msgstr "Основные"
|
||||
|
||||
#: ../../../ui.cpp:1634
|
||||
msgid "&Start Bitcoin on window system startup"
|
||||
msgstr "&Запускать Bitcoin при запуске оконной системы"
|
||||
|
||||
#: ../../../ui.cpp:1641
|
||||
msgid "&Minimize on close"
|
||||
msgstr "&Сворачивать при закрытии"
|
||||
|
||||
#: ../../../ui.cpp:1798
|
||||
#, c-format
|
||||
msgid "version %s%s beta"
|
||||
msgstr "версия %s%s бета"
|
||||
|
||||
#: ../../../ui.cpp:1884
|
||||
msgid "n/a"
|
||||
msgstr "н/д"
|
||||
|
||||
#: ../../../ui.cpp:1885
|
||||
msgid "Can't include a message when sending to a Bitcoin address"
|
||||
msgstr "Не удаётся включить сообщение при отправке на адрес Bitcoin"
|
||||
|
||||
#: ../../../ui.cpp:1938
|
||||
msgid "Error in amount "
|
||||
msgstr "Ошибка в количестве "
|
||||
|
||||
#: ../../../ui.cpp:1938
|
||||
#: ../../../ui.cpp:1943
|
||||
#: ../../../ui.cpp:1948
|
||||
#: ../../../ui.cpp:1974
|
||||
#: ../../../uibase.cpp:59
|
||||
msgid "Send Coins"
|
||||
msgstr "Отправить монеты"
|
||||
|
||||
#: ../../../ui.cpp:1943
|
||||
msgid "Amount exceeds your balance "
|
||||
msgstr "Количество превышает ваш баланс "
|
||||
|
||||
#: ../../../ui.cpp:1948
|
||||
msgid "Total exceeds your balance when the "
|
||||
msgstr "Общая сумма превышает ваш баланс, когда "
|
||||
|
||||
#: ../../../ui.cpp:1948
|
||||
msgid " transaction fee is included "
|
||||
msgstr " комиссия включена "
|
||||
|
||||
#: ../../../ui.cpp:1964
|
||||
msgid "Payment sent "
|
||||
msgstr "Платёж отправлен "
|
||||
|
||||
#: ../../../ui.cpp:1974
|
||||
msgid "Invalid address "
|
||||
msgstr "Неверный адрес "
|
||||
|
||||
#: ../../../ui.cpp:2028
|
||||
#, c-format
|
||||
msgid "Sending %s to %s"
|
||||
msgstr "Отправка %s для %s"
|
||||
|
||||
#: ../../../ui.cpp:2101
|
||||
#: ../../../ui.cpp:2134
|
||||
msgid "CANCELLED"
|
||||
msgstr "ОТМЕНЕНО"
|
||||
|
||||
#: ../../../ui.cpp:2105
|
||||
msgid "Cancelled"
|
||||
msgstr "Отменено"
|
||||
|
||||
#: ../../../ui.cpp:2107
|
||||
msgid "Transfer cancelled "
|
||||
msgstr "Передача отменена "
|
||||
|
||||
#: ../../../ui.cpp:2160
|
||||
msgid "Error: "
|
||||
msgstr "Ошибка: "
|
||||
|
||||
#: ../../../ui.cpp:2179
|
||||
msgid "Connecting..."
|
||||
msgstr "Подключение..."
|
||||
|
||||
#: ../../../ui.cpp:2184
|
||||
msgid "Unable to connect"
|
||||
msgstr "Невозможно подключиться"
|
||||
|
||||
#: ../../../ui.cpp:2189
|
||||
msgid "Requesting public key..."
|
||||
msgstr "Запрос публичного ключа..."
|
||||
|
||||
#: ../../../ui.cpp:2201
|
||||
msgid "Received public key..."
|
||||
msgstr "Получен публичный ключ..."
|
||||
|
||||
#: ../../../ui.cpp:2215
|
||||
msgid "Recipient is not accepting transactions sent by IP address"
|
||||
msgstr "Получатель не принимает переводы на IP-адрес"
|
||||
|
||||
#: ../../../ui.cpp:2217
|
||||
msgid "Transfer was not accepted"
|
||||
msgstr "Передача не принята"
|
||||
|
||||
#: ../../../ui.cpp:2226
|
||||
msgid "Invalid response received"
|
||||
msgstr "Получен неверный отклик"
|
||||
|
||||
#: ../../../ui.cpp:2241
|
||||
msgid "Creating transaction..."
|
||||
msgstr "Создание перевода..."
|
||||
|
||||
#: ../../../ui.cpp:2253
|
||||
#, c-format
|
||||
msgid "This is an oversized transaction that requires a transaction fee of %s"
|
||||
msgstr "Это слишком большой перевод, который требует комиссию в размере %s"
|
||||
|
||||
#: ../../../ui.cpp:2255
|
||||
msgid "Transaction creation failed"
|
||||
msgstr "Не удалось создать перевод"
|
||||
|
||||
#: ../../../ui.cpp:2262
|
||||
msgid "Transaction aborted"
|
||||
msgstr "Перевод прерван"
|
||||
|
||||
#: ../../../ui.cpp:2270
|
||||
msgid "Lost connection, transaction cancelled"
|
||||
msgstr "Соединение разорвано, перевод отменён"
|
||||
|
||||
#: ../../../ui.cpp:2286
|
||||
msgid "Sending payment..."
|
||||
msgstr "Отправка платежа..."
|
||||
|
||||
#: ../../../ui.cpp:2292
|
||||
msgid "The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."
|
||||
msgstr "Перевод был отклонён. Это могло произойти, если некоторые из монет в вашем кошельке уже были потрачены, например, если вы использовали копию wallet.dat, и монеты были потрачены в копии, но не отмечены израсходованными здесь."
|
||||
|
||||
#: ../../../ui.cpp:2301
|
||||
msgid "Waiting for confirmation..."
|
||||
msgstr "Ожидание подтверждения..."
|
||||
|
||||
#: ../../../ui.cpp:2319
|
||||
msgid ""
|
||||
"The payment was sent, but the recipient was unable to verify it.\n"
|
||||
"The transaction is recorded and will credit to the recipient,\n"
|
||||
"but the comment information will be blank."
|
||||
msgstr ""
|
||||
"Платёж был отправлен, но получатель не смог проверить его.\n"
|
||||
"Перевод был записан и будет начислен получателю,\n"
|
||||
"но поле комментария будет пустое."
|
||||
|
||||
#: ../../../ui.cpp:2328
|
||||
msgid "Payment was sent, but an invalid response was received"
|
||||
msgstr "Платёж отправлен, но был получен неверный отклик"
|
||||
|
||||
#: ../../../ui.cpp:2334
|
||||
msgid "Payment completed"
|
||||
msgstr "Платёж проведён"
|
||||
|
||||
#: ../../../ui.cpp:2365
|
||||
#: ../../../ui.cpp:2511
|
||||
#: ../../../ui.cpp:2548
|
||||
msgid "Name"
|
||||
msgstr "Имя"
|
||||
|
||||
#: ../../../ui.cpp:2366
|
||||
#: ../../../ui.cpp:2511
|
||||
#: ../../../ui.cpp:2548
|
||||
msgid "Address"
|
||||
msgstr "Адрес"
|
||||
|
||||
#: ../../../ui.cpp:2368
|
||||
#: ../../../ui.cpp:2523
|
||||
msgid "Label"
|
||||
msgstr "Метка"
|
||||
|
||||
#: ../../../ui.cpp:2369
|
||||
#: ../../../uibase.cpp:902
|
||||
msgid "Bitcoin Address"
|
||||
msgstr "Адрес Bitcoin"
|
||||
|
||||
#: ../../../ui.cpp:2493
|
||||
msgid "This is one of your own addresses for receiving payments and cannot be entered in the address book. "
|
||||
msgstr "Это один из ваших собственных адресов для получения платежей, он не может быть внесён в адресную книгу. "
|
||||
|
||||
#: ../../../ui.cpp:2511
|
||||
#: ../../../ui.cpp:2517
|
||||
msgid "Edit Address"
|
||||
msgstr "Правка адреса"
|
||||
|
||||
#: ../../../ui.cpp:2523
|
||||
msgid "Edit Address Label"
|
||||
msgstr "Правка метки адреса"
|
||||
|
||||
#: ../../../ui.cpp:2548
|
||||
#: ../../../ui.cpp:2554
|
||||
msgid "Add Address"
|
||||
msgstr "Добавить адрес"
|
||||
|
||||
#: ../../../ui.cpp:2630
|
||||
msgid "Bitcoin"
|
||||
msgstr "Bitcoin"
|
||||
|
||||
#: ../../../ui.cpp:2632
|
||||
msgid "Bitcoin - Generating"
|
||||
msgstr "Bitcoin - Генерация"
|
||||
|
||||
#: ../../../ui.cpp:2634
|
||||
msgid "Bitcoin - (not connected)"
|
||||
msgstr "Bitcoin - (не подключен)"
|
||||
|
||||
#: ../../../ui.cpp:2711
|
||||
msgid "&Open Bitcoin"
|
||||
msgstr "&Открыть Bitcoin"
|
||||
|
||||
#: ../../../ui.cpp:2712
|
||||
msgid "O&ptions..."
|
||||
msgstr "О&пции..."
|
||||
|
||||
#: ../../../ui.cpp:2713
|
||||
#: ../../../uibase.cpp:32
|
||||
msgid "&Generate Coins"
|
||||
msgstr "&Генерировать монеты"
|
||||
|
||||
#: ../../../ui.cpp:2716
|
||||
#: ../../../uibase.cpp:25
|
||||
msgid "E&xit"
|
||||
msgstr "&Выход"
|
||||
|
||||
#: ../../../ui.cpp:2931
|
||||
msgid "Program has crashed and will terminate. "
|
||||
msgstr "Сбой программы, завершение. "
|
||||
|
||||
#: ../../../uibase.cpp:28
|
||||
msgid "&File"
|
||||
msgstr "&Файл"
|
||||
|
||||
#: ../../../uibase.cpp:36
|
||||
msgid "&Your Receiving Addresses..."
|
||||
msgstr "&Ваши адреса получения..."
|
||||
|
||||
#: ../../../uibase.cpp:40
|
||||
msgid "&Options..."
|
||||
msgstr "&Опции"
|
||||
|
||||
#: ../../../uibase.cpp:43
|
||||
msgid "&Settings"
|
||||
msgstr "&Настройки"
|
||||
|
||||
#: ../../../uibase.cpp:47
|
||||
msgid "&About..."
|
||||
msgstr "&О программе..."
|
||||
|
||||
#: ../../../uibase.cpp:50
|
||||
msgid "&Help"
|
||||
msgstr "&Справка"
|
||||
|
||||
#: ../../../uibase.cpp:60
|
||||
msgid "Address Book"
|
||||
msgstr "Адресная книга"
|
||||
|
||||
#: ../../../uibase.cpp:75
|
||||
msgid "Your Bitcoin Address:"
|
||||
msgstr "Ваш адрес Bitcoin:"
|
||||
|
||||
#: ../../../uibase.cpp:82
|
||||
msgid " &New... "
|
||||
msgstr " &Новый... "
|
||||
|
||||
#: ../../../uibase.cpp:85
|
||||
#: ../../../uibase.cpp:845
|
||||
#: ../../../uibase.cpp:948
|
||||
msgid " &Copy to Clipboard "
|
||||
msgstr " &Копировать в буфер обмена "
|
||||
|
||||
#: ../../../uibase.cpp:99
|
||||
msgid "Balance:"
|
||||
msgstr "Баланс:"
|
||||
|
||||
#: ../../../uibase.cpp:115
|
||||
msgid " All"
|
||||
msgstr " Все"
|
||||
|
||||
#: ../../../uibase.cpp:115
|
||||
msgid " Sent"
|
||||
msgstr " Отправленные"
|
||||
|
||||
#: ../../../uibase.cpp:115
|
||||
msgid " Received"
|
||||
msgstr " Полученные"
|
||||
|
||||
#: ../../../uibase.cpp:115
|
||||
msgid " In Progress"
|
||||
msgstr " В процессе"
|
||||
|
||||
#: ../../../uibase.cpp:136
|
||||
msgid "All Transactions"
|
||||
msgstr "Все переводы"
|
||||
|
||||
#: ../../../uibase.cpp:147
|
||||
msgid "Sent/Received"
|
||||
msgstr "Отправленные/Полученные"
|
||||
|
||||
#: ../../../uibase.cpp:158
|
||||
msgid "Sent"
|
||||
msgstr "Отправленные"
|
||||
|
||||
#: ../../../uibase.cpp:169
|
||||
msgid "Received"
|
||||
msgstr "Полученные"
|
||||
|
||||
#: ../../../uibase.cpp:312
|
||||
#: ../../../uibase.cpp:473
|
||||
#: ../../../uibase.cpp:574
|
||||
#: ../../../uibase.cpp:787
|
||||
#: ../../../uibase.cpp:848
|
||||
#: ../../../uibase.cpp:957
|
||||
#: ../../../uibase.cpp:1046
|
||||
msgid "OK"
|
||||
msgstr "ОК"
|
||||
|
||||
#: ../../../uibase.cpp:355
|
||||
msgid "Optional transaction fee you give to the nodes that process your transactions."
|
||||
msgstr "Необязательная комиссия, которую вы даёте узлам, проводящим ваш перевод."
|
||||
|
||||
#: ../../../uibase.cpp:364
|
||||
msgid "Transaction fee:"
|
||||
msgstr "Комиссия:"
|
||||
|
||||
#: ../../../uibase.cpp:380
|
||||
msgid "&Limit coin generation to"
|
||||
msgstr "&Ограничить генерацию монет до"
|
||||
|
||||
#: ../../../uibase.cpp:387
|
||||
msgid "processors"
|
||||
msgstr "процессоров"
|
||||
|
||||
#: ../../../uibase.cpp:393
|
||||
msgid "&Start Bitcoin on system startup"
|
||||
msgstr "&Запускать Bitcoin при старте системы"
|
||||
|
||||
#: ../../../uibase.cpp:397
|
||||
msgid "&Minimize to the tray instead of the taskbar"
|
||||
msgstr "&Сворачивать в трей вместо панели задач"
|
||||
|
||||
#: ../../../uibase.cpp:401
|
||||
msgid "M&inimize to the tray on close"
|
||||
msgstr "С&ворачивать в трей при закрытии"
|
||||
|
||||
#: ../../../uibase.cpp:408
|
||||
msgid "&Connect through socks4 proxy: "
|
||||
msgstr "&Подключаться через socks4 прокси: "
|
||||
|
||||
#: ../../../uibase.cpp:420
|
||||
msgid "Proxy &IP:"
|
||||
msgstr "IP п&рокси:"
|
||||
|
||||
#: ../../../uibase.cpp:428
|
||||
msgid " &Port:"
|
||||
msgstr " &Порт"
|
||||
|
||||
#: ../../../uibase.cpp:450
|
||||
msgid "// [don't translate] Test panel 2 for future expansion"
|
||||
msgstr ""
|
||||
|
||||
#: ../../../uibase.cpp:454
|
||||
msgid "// [don't translate] Let's not start multiple pages until the first page is filled up"
|
||||
msgstr ""
|
||||
|
||||
#: ../../../uibase.cpp:476
|
||||
#: ../../../uibase.cpp:729
|
||||
#: ../../../uibase.cpp:792
|
||||
#: ../../../uibase.cpp:851
|
||||
#: ../../../uibase.cpp:960
|
||||
#: ../../../uibase.cpp:1049
|
||||
msgid "Cancel"
|
||||
msgstr "Отмена"
|
||||
|
||||
#: ../../../uibase.cpp:479
|
||||
msgid "&Apply"
|
||||
msgstr "&Применить"
|
||||
|
||||
#: ../../../uibase.cpp:540
|
||||
msgid "Bitcoin "
|
||||
msgstr "Bitcoin "
|
||||
|
||||
#: ../../../uibase.cpp:546
|
||||
msgid "version"
|
||||
msgstr "версия"
|
||||
|
||||
#: ../../../uibase.cpp:557
|
||||
msgid ""
|
||||
"Copyright (c) 2009-2010 Satoshi Nakamoto.\n"
|
||||
"\n"
|
||||
"This is experimental software.\n"
|
||||
"\n"
|
||||
"Distributed under the MIT/X11 software license, see the accompanying file \n"
|
||||
"license.txt or http://www.opensource.org/licenses/mit-license.php.\n"
|
||||
"\n"
|
||||
"This product includes software developed by the OpenSSL Project for use in the \n"
|
||||
"OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by \n"
|
||||
"Eric Young (eay@cryptsoft.com)."
|
||||
msgstr ""
|
||||
"Все права защищены (c) 2009-2010 Satoshi Nakamoto.\n"
|
||||
"\n"
|
||||
"Это экспериментальное ПО.\n"
|
||||
"\n"
|
||||
"Распространяется под лицензией MIT/X11, см. файл\n"
|
||||
"license.txt или http://www.opensource.org/licenses/mit-license.php.\n"
|
||||
"\n"
|
||||
"Этот продукт включает ПО, разработанное проектом OpenSSL для использования в\n"
|
||||
"OpenSSL Toolkit (http://www.openssl.org/), и криптографическое ПО, написанное\n"
|
||||
"Eric Young (eay@cryptsoft.com)."
|
||||
|
||||
#: ../../../uibase.cpp:613
|
||||
msgid "Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L) or IP address (e.g. 123.45.6.7)"
|
||||
msgstr "Введите адрес Bitcoin (напр. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L) или IP адрес (напр. 123.45.6.7)"
|
||||
|
||||
#: ../../../uibase.cpp:627
|
||||
msgid "Pay &To:"
|
||||
msgstr "&Кому:"
|
||||
|
||||
#: ../../../uibase.cpp:642
|
||||
msgid "&Paste"
|
||||
msgstr "&Вставить"
|
||||
|
||||
#: ../../../uibase.cpp:645
|
||||
msgid " Address &Book..."
|
||||
msgstr " А&дресная книга..."
|
||||
|
||||
#: ../../../uibase.cpp:652
|
||||
msgid "&Amount:"
|
||||
msgstr "К&оличество:"
|
||||
|
||||
#: ../../../uibase.cpp:662
|
||||
msgid "T&ransfer:"
|
||||
msgstr "&Передача:"
|
||||
|
||||
#: ../../../uibase.cpp:668
|
||||
msgid " Standard"
|
||||
msgstr " Стандарт"
|
||||
|
||||
#: ../../../uibase.cpp:690
|
||||
msgid "&From:"
|
||||
msgstr "О&т:"
|
||||
|
||||
#: ../../../uibase.cpp:707
|
||||
msgid "&Message:"
|
||||
msgstr "&Сообщение:"
|
||||
|
||||
#: ../../../uibase.cpp:724
|
||||
msgid "&Send"
|
||||
msgstr "Отп&равить"
|
||||
|
||||
#: ../../../uibase.cpp:776
|
||||
msgid ""
|
||||
"\n"
|
||||
"\n"
|
||||
"Connecting..."
|
||||
msgstr ""
|
||||
"\n"
|
||||
"\n"
|
||||
"Подключение..."
|
||||
|
||||
#: ../../../uibase.cpp:826
|
||||
msgid "These are your Bitcoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. The highlighted address is displayed in the main window."
|
||||
msgstr "Это ваши адреса для получения платежей. Вы можете использовать разные для каждого отправителя, чтобы отслеживать, кто вам платит. Выделенный адрес отображается в главном окне."
|
||||
|
||||
#: ../../../uibase.cpp:839
|
||||
#: ../../../uibase.cpp:951
|
||||
msgid "&Edit..."
|
||||
msgstr "&Правка..."
|
||||
|
||||
#: ../../../uibase.cpp:842
|
||||
#: ../../../uibase.cpp:954
|
||||
msgid " &New Address... "
|
||||
msgstr " &Новый адрес... "
|
||||
|
||||
#: ../../../uibase.cpp:914
|
||||
msgid "Sending"
|
||||
msgstr "Отправка"
|
||||
|
||||
#: ../../../uibase.cpp:922
|
||||
msgid "These are your Bitcoin addresses for receiving payments. You can give a different one to each sender to keep track of who is paying you. The highlighted address will be displayed in the main window."
|
||||
msgstr "Это ваши адреса для получения платежей. Вы можете использовать разные для каждого отправителя, чтобы отслеживать, кто вам платит. Выделенный адрес отображается в главном окне."
|
||||
|
||||
#: ../../../uibase.cpp:935
|
||||
msgid "Receiving"
|
||||
msgstr "Получение"
|
||||
|
||||
#: ../../../uibase.cpp:945
|
||||
msgid "&Delete"
|
||||
msgstr "&Удалить"
|
||||
|
||||
#: ../../../util.cpp:807
|
||||
msgid "Warning: Please check that your computer's date and time are correct. If your clock is wrong Bitcoin will not work properly."
|
||||
msgstr "Внимание: пожалуйста, проверьте дату и время на вашем компьютере. Если часы идут неверно, Bitcoin не будет работать правильно."
|
||||
|
||||
#: ../../../uibase.h:149
|
||||
msgid "Transaction Details"
|
||||
msgstr "Подробности транзакции"
|
||||
|
||||
#: ../../../uibase.h:202
|
||||
msgid "Options"
|
||||
msgstr "Опции"
|
||||
|
||||
#: ../../../uibase.h:230
|
||||
msgid "About Bitcoin"
|
||||
msgstr "О Bitcoin"
|
||||
|
||||
#: ../../../uibase.h:340
|
||||
msgid "Your Bitcoin Addresses"
|
||||
msgstr "Ваш адрес Bitcoin"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "It's good policy to use a new address for each payment you receive.\n"
|
||||
#~ "\n"
|
||||
#~ "Label"
|
||||
#~ msgstr ""
|
||||
#~ "Неплохо будет использовать новый адрес для каждого получаемого платежа.\n"
|
||||
#~ "\n"
|
||||
#~ "Метка"
|
||||
|
||||
#~ msgid "Will appear as \"From: Unknown\""
|
||||
#~ msgstr "Будет отображаться как \"От: Аноним\""
|
||||
448
main.cpp
448
main.cpp
@@ -21,7 +21,8 @@ unsigned int nTransactionsUpdated = 0;
|
||||
map<COutPoint, CInPoint> mapNextTx;
|
||||
|
||||
map<uint256, CBlockIndex*> mapBlockIndex;
|
||||
const uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
|
||||
uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
|
||||
CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
|
||||
CBlockIndex* pindexGenesisBlock = NULL;
|
||||
int nBestHeight = -1;
|
||||
CBigNum bnBestChainWork = 0;
|
||||
@@ -143,7 +144,7 @@ bool AddToWallet(const CWalletTx& wtxIn)
|
||||
}
|
||||
|
||||
//// debug print
|
||||
printf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString().substr(0,6).c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
|
||||
printf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString().substr(0,10).c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
|
||||
|
||||
// Write to disk
|
||||
if (fInsertedNew || fUpdated)
|
||||
@@ -158,7 +159,8 @@ bool AddToWallet(const CWalletTx& wtxIn)
|
||||
if (txout.scriptPubKey == scriptDefaultKey)
|
||||
{
|
||||
CWalletDB walletdb;
|
||||
walletdb.WriteDefaultKey(GenerateNewKey());
|
||||
vchDefaultKey = walletdb.GetKeyFromKeyPool();
|
||||
walletdb.WriteDefaultKey(vchDefaultKey);
|
||||
walletdb.WriteName(PubKeyToAddress(vchDefaultKey), "");
|
||||
}
|
||||
}
|
||||
@@ -275,6 +277,34 @@ void EraseOrphanTx(uint256 hash)
|
||||
// CTransaction
|
||||
//
|
||||
|
||||
bool CTransaction::ReadFromDisk(CTxDB& txdb, COutPoint prevout, CTxIndex& txindexRet)
|
||||
{
|
||||
SetNull();
|
||||
if (!txdb.ReadTxIndex(prevout.hash, txindexRet))
|
||||
return false;
|
||||
if (!ReadFromDisk(txindexRet.pos))
|
||||
return false;
|
||||
if (prevout.n >= vout.size())
|
||||
{
|
||||
SetNull();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CTransaction::ReadFromDisk(CTxDB& txdb, COutPoint prevout)
|
||||
{
|
||||
CTxIndex txindex;
|
||||
return ReadFromDisk(txdb, prevout, txindex);
|
||||
}
|
||||
|
||||
bool CTransaction::ReadFromDisk(COutPoint prevout)
|
||||
{
|
||||
CTxDB txdb("r");
|
||||
CTxIndex txindex;
|
||||
return ReadFromDisk(txdb, prevout, txindex);
|
||||
}
|
||||
|
||||
bool CTxIn::IsMine() const
|
||||
{
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
@@ -587,7 +617,7 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
|
||||
{
|
||||
if (pfMissingInputs)
|
||||
*pfMissingInputs = true;
|
||||
return error("AcceptToMemoryPool() : ConnectInputs failed %s", hash.ToString().substr(0,6).c_str());
|
||||
return error("AcceptToMemoryPool() : ConnectInputs failed %s", hash.ToString().substr(0,10).c_str());
|
||||
}
|
||||
|
||||
// Store transaction in memory
|
||||
@@ -606,7 +636,7 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
|
||||
if (ptxOld)
|
||||
EraseFromWallet(ptxOld->GetHash());
|
||||
|
||||
printf("AcceptToMemoryPool(): accepted %s\n", hash.ToString().substr(0,6).c_str());
|
||||
printf("AcceptToMemoryPool(): accepted %s\n", hash.ToString().substr(0,10).c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -775,7 +805,7 @@ void CWalletTx::RelayWalletTransaction(CTxDB& txdb)
|
||||
uint256 hash = GetHash();
|
||||
if (!txdb.ContainsTx(hash))
|
||||
{
|
||||
printf("Relaying wtx %s\n", hash.ToString().substr(0,6).c_str());
|
||||
printf("Relaying wtx %s\n", hash.ToString().substr(0,10).c_str());
|
||||
RelayMessage(CInv(MSG_TX, hash), (CTransaction)*this);
|
||||
}
|
||||
}
|
||||
@@ -927,7 +957,7 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits)
|
||||
|
||||
bool IsInitialBlockDownload()
|
||||
{
|
||||
if (pindexBest == NULL)
|
||||
if (pindexBest == NULL || (!fTestNet && nBestHeight < 74000))
|
||||
return true;
|
||||
static int64 nLastUpdate;
|
||||
static CBlockIndex* pindexLastBest;
|
||||
@@ -985,7 +1015,8 @@ bool CTransaction::DisconnectInputs(CTxDB& txdb)
|
||||
txindex.vSpent[prevout.n].SetNull();
|
||||
|
||||
// Write back
|
||||
txdb.UpdateTxIndex(prevout.hash, txindex);
|
||||
if (!txdb.UpdateTxIndex(prevout.hash, txindex))
|
||||
return error("DisconnectInputs() : UpdateTxIndex failed");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1022,7 +1053,7 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPoo
|
||||
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());
|
||||
return fMiner ? false : error("ConnectInputs() : %s prev tx %s index entry not found", GetHash().ToString().substr(0,10).c_str(), prevout.hash.ToString().substr(0,10).c_str());
|
||||
|
||||
// Read txPrev
|
||||
CTransaction txPrev;
|
||||
@@ -1032,7 +1063,7 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPoo
|
||||
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());
|
||||
return error("ConnectInputs() : %s mapTransactions prev not found %s", GetHash().ToString().substr(0,10).c_str(), prevout.hash.ToString().substr(0,10).c_str());
|
||||
txPrev = mapTransactions[prevout.hash];
|
||||
}
|
||||
if (!fFound)
|
||||
@@ -1042,11 +1073,11 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPoo
|
||||
{
|
||||
// Get prev tx from disk
|
||||
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());
|
||||
return error("ConnectInputs() : %s ReadFromDisk prev tx %s failed", GetHash().ToString().substr(0,10).c_str(), prevout.hash.ToString().substr(0,10).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 prev tx %s\n%s", GetHash().ToString().substr(0,6).c_str(), prevout.n, txPrev.vout.size(), txindex.vSpent.size(), prevout.hash.ToString().substr(0,6).c_str(), txPrev.ToString().c_str());
|
||||
return error("ConnectInputs() : %s prevout.n out of range %d %d %d prev tx %s\n%s", GetHash().ToString().substr(0,10).c_str(), prevout.n, txPrev.vout.size(), txindex.vSpent.size(), prevout.hash.ToString().substr(0,10).c_str(), txPrev.ToString().c_str());
|
||||
|
||||
// If prev is coinbase, check that it's matured
|
||||
if (txPrev.IsCoinBase())
|
||||
@@ -1056,11 +1087,11 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPoo
|
||||
|
||||
// Verify signature
|
||||
if (!VerifySignature(txPrev, *this, i))
|
||||
return error("ConnectInputs() : %s VerifySignature failed", GetHash().ToString().substr(0,6).c_str());
|
||||
return error("ConnectInputs() : %s VerifySignature failed", GetHash().ToString().substr(0,10).c_str());
|
||||
|
||||
// Check for conflicts
|
||||
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());
|
||||
return fMiner ? false : error("ConnectInputs() : %s prev tx already used at %s", GetHash().ToString().substr(0,10).c_str(), txindex.vSpent[prevout.n].ToString().c_str());
|
||||
|
||||
// Check for negative or overflow input values
|
||||
nValueIn += txPrev.vout[prevout.n].nValue;
|
||||
@@ -1072,18 +1103,23 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPoo
|
||||
|
||||
// Write back
|
||||
if (fBlock)
|
||||
txdb.UpdateTxIndex(prevout.hash, txindex);
|
||||
{
|
||||
if (!txdb.UpdateTxIndex(prevout.hash, txindex))
|
||||
return error("ConnectInputs() : UpdateTxIndex failed");
|
||||
}
|
||||
else if (fMiner)
|
||||
{
|
||||
mapTestPool[prevout.hash] = txindex;
|
||||
}
|
||||
}
|
||||
|
||||
if (nValueIn < GetValueOut())
|
||||
return error("ConnectInputs() : %s value in < value out", GetHash().ToString().substr(0,6).c_str());
|
||||
return error("ConnectInputs() : %s value in < value out", GetHash().ToString().substr(0,10).c_str());
|
||||
|
||||
// Tally transaction fees
|
||||
int64 nTxFee = nValueIn - GetValueOut();
|
||||
if (nTxFee < 0)
|
||||
return error("ConnectInputs() : %s nTxFee < 0", GetHash().ToString().substr(0,6).c_str());
|
||||
return error("ConnectInputs() : %s nTxFee < 0", GetHash().ToString().substr(0,10).c_str());
|
||||
if (nTxFee < nMinFee)
|
||||
return false;
|
||||
nFees += nTxFee;
|
||||
@@ -1168,7 +1204,8 @@ bool CBlock::DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex)
|
||||
{
|
||||
CDiskBlockIndex blockindexPrev(pindex->pprev);
|
||||
blockindexPrev.hashNext = 0;
|
||||
txdb.WriteBlockIndex(blockindexPrev);
|
||||
if (!txdb.WriteBlockIndex(blockindexPrev))
|
||||
return error("DisconnectBlock() : WriteBlockIndex failed");
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1203,7 +1240,8 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex)
|
||||
{
|
||||
CDiskBlockIndex blockindexPrev(pindex->pprev);
|
||||
blockindexPrev.hashNext = pindex->GetBlockHash();
|
||||
txdb.WriteBlockIndex(blockindexPrev);
|
||||
if (!txdb.WriteBlockIndex(blockindexPrev))
|
||||
return error("ConnectBlock() : WriteBlockIndex failed");
|
||||
}
|
||||
|
||||
// Watch for transactions paying to me
|
||||
@@ -1282,8 +1320,9 @@ bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
|
||||
if (!txdb.WriteHashBestChain(pindexNew->GetBlockHash()))
|
||||
return error("Reorganize() : WriteHashBestChain failed");
|
||||
|
||||
// Commit now because resurrecting could take some time
|
||||
txdb.TxnCommit();
|
||||
// Make sure it's successfully written to disk before changing memory structure
|
||||
if (!txdb.TxnCommit())
|
||||
return error("Reorganize() : TxnCommit failed");
|
||||
|
||||
// Disconnect shorter branch
|
||||
foreach(CBlockIndex* pindex, vDisconnect)
|
||||
@@ -1314,8 +1353,10 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
|
||||
txdb.TxnBegin();
|
||||
if (pindexGenesisBlock == NULL && hash == hashGenesisBlock)
|
||||
{
|
||||
pindexGenesisBlock = pindexNew;
|
||||
txdb.WriteHashBestChain(hash);
|
||||
if (!txdb.TxnCommit())
|
||||
return error("SetBestChain() : TxnCommit failed");
|
||||
pindexGenesisBlock = pindexNew;
|
||||
}
|
||||
else if (hashPrevBlock == hashBestChain)
|
||||
{
|
||||
@@ -1326,7 +1367,10 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
|
||||
InvalidChainFound(pindexNew);
|
||||
return error("SetBestChain() : ConnectBlock failed");
|
||||
}
|
||||
txdb.TxnCommit();
|
||||
if (!txdb.TxnCommit())
|
||||
return error("SetBestChain() : TxnCommit failed");
|
||||
|
||||
// Add to current best branch
|
||||
pindexNew->pprev->pnext = pindexNew;
|
||||
|
||||
// Delete redundant memory transactions
|
||||
@@ -1343,7 +1387,6 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
|
||||
return error("SetBestChain() : Reorganize failed");
|
||||
}
|
||||
}
|
||||
txdb.TxnCommit();
|
||||
|
||||
// New best block
|
||||
hashBestChain = hash;
|
||||
@@ -1473,21 +1516,13 @@ bool CBlock::AcceptBlock()
|
||||
return error("AcceptBlock() : contains a non-final transaction");
|
||||
|
||||
// Check that the block chain matches the known block chain up to a checkpoint
|
||||
if ((nHeight == 11111 && hash != uint256("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")) ||
|
||||
(nHeight == 33333 && hash != uint256("0x000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6")) ||
|
||||
(nHeight == 68555 && hash != uint256("0x00000000001e1b4903550a0b96e9a9405c8a95f387162e4944e8d9fbe501cd6a")) ||
|
||||
(nHeight == 70567 && hash != uint256("0x00000000006a49b14bcf27462068f1264c961f11fa2e0eddd2be0791e1d4124a")) ||
|
||||
(nHeight == 74000 && hash != uint256("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20")))
|
||||
return error("AcceptBlock() : rejected by checkpoint lockin at %d", nHeight);
|
||||
|
||||
// Scanback checkpoint lockin
|
||||
for (CBlockIndex* pindex = pindexPrev; pindex->nHeight >= 74000; pindex = pindex->pprev)
|
||||
{
|
||||
if (pindex->nHeight == 74000 && pindex->GetBlockHash() != uint256("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20"))
|
||||
return error("AcceptBlock() : rejected by scanback lockin at %d", pindex->nHeight);
|
||||
if (pindex->nHeight == 74638 && pindex->GetBlockHash() == uint256("0x0000000000790ab3f22ec756ad43b6ab569abf0bddeb97c67a6f7b1470a7ec1c"))
|
||||
return error("AcceptBlock() : rejected by scanback lockin at %d", pindex->nHeight);
|
||||
}
|
||||
if (!fTestNet)
|
||||
if ((nHeight == 11111 && hash != uint256("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")) ||
|
||||
(nHeight == 33333 && hash != uint256("0x000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6")) ||
|
||||
(nHeight == 68555 && hash != uint256("0x00000000001e1b4903550a0b96e9a9405c8a95f387162e4944e8d9fbe501cd6a")) ||
|
||||
(nHeight == 70567 && hash != uint256("0x00000000006a49b14bcf27462068f1264c961f11fa2e0eddd2be0791e1d4124a")) ||
|
||||
(nHeight == 74000 && hash != uint256("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20")))
|
||||
return error("AcceptBlock() : rejected by checkpoint lockin at %d", nHeight);
|
||||
|
||||
// Write block to history file
|
||||
if (!CheckDiskSpace(::GetSerializeSize(*this, SER_DISK)))
|
||||
@@ -1678,6 +1713,16 @@ FILE* AppendBlockFile(unsigned int& nFileRet)
|
||||
|
||||
bool LoadBlockIndex(bool fAllowNew)
|
||||
{
|
||||
if (fTestNet)
|
||||
{
|
||||
hashGenesisBlock = uint256("0x0000000224b1593e3ff16a0e3b61285bbc393a39f78c8aa48c456142671f7110");
|
||||
bnProofOfWorkLimit = CBigNum(~uint256(0) >> 28);
|
||||
pchMessageStart[0] = 0xfa;
|
||||
pchMessageStart[1] = 0xbf;
|
||||
pchMessageStart[2] = 0xb5;
|
||||
pchMessageStart[3] = 0xda;
|
||||
}
|
||||
|
||||
//
|
||||
// Load block index
|
||||
//
|
||||
@@ -1718,13 +1763,19 @@ bool LoadBlockIndex(bool fAllowNew)
|
||||
block.nBits = 0x1d00ffff;
|
||||
block.nNonce = 2083236893;
|
||||
|
||||
//// debug print
|
||||
printf("%s\n", block.GetHash().ToString().c_str());
|
||||
printf("%s\n", hashGenesisBlock.ToString().c_str());
|
||||
printf("%s\n", block.hashMerkleRoot.ToString().c_str());
|
||||
assert(block.hashMerkleRoot == uint256("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
|
||||
block.print();
|
||||
if (fTestNet)
|
||||
{
|
||||
block.nTime = 1279232055;
|
||||
block.nBits = 0x1d07fff8;
|
||||
block.nNonce = 81622180;
|
||||
}
|
||||
|
||||
//// debug print
|
||||
printf("%s\n", block.GetHash().ToString().c_str());
|
||||
printf("%s\n", hashGenesisBlock.ToString().c_str());
|
||||
printf("%s\n", block.hashMerkleRoot.ToString().c_str());
|
||||
assert(block.hashMerkleRoot == uint256("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
|
||||
block.print();
|
||||
assert(block.GetHash() == hashGenesisBlock);
|
||||
|
||||
// Start new block file
|
||||
@@ -1948,7 +1999,7 @@ bool AlreadyHave(CTxDB& txdb, const CInv& inv)
|
||||
{
|
||||
switch (inv.type)
|
||||
{
|
||||
case MSG_TX: return mapTransactions.count(inv.hash) || txdb.ContainsTx(inv.hash);
|
||||
case MSG_TX: return mapTransactions.count(inv.hash) || mapOrphanTransactions.count(inv.hash) || txdb.ContainsTx(inv.hash);
|
||||
case MSG_BLOCK: return mapBlockIndex.count(inv.hash) || mapOrphanBlocks.count(inv.hash);
|
||||
}
|
||||
// Don't know what it is, just say we already got one
|
||||
@@ -1958,7 +2009,10 @@ bool AlreadyHave(CTxDB& txdb, const CInv& inv)
|
||||
|
||||
|
||||
|
||||
|
||||
// The message start string is designed to be unlikely to occur in normal data.
|
||||
// The characters are rarely used upper ascii, not valid as UTF-8, and produce
|
||||
// a large 4-byte int at any alignment.
|
||||
char pchMessageStart[4] = { 0xf9, 0xbe, 0xb4, 0xd9 };
|
||||
|
||||
|
||||
bool ProcessMessages(CNode* pfrom)
|
||||
@@ -2017,19 +2071,14 @@ bool ProcessMessages(CNode* pfrom)
|
||||
if (nMessageSize > vRecv.size())
|
||||
{
|
||||
// Rewind and wait for rest of message
|
||||
///// need a mechanism to give up waiting for overlong message size error
|
||||
vRecv.insert(vRecv.begin(), vHeaderSave.begin(), vHeaderSave.end());
|
||||
break;
|
||||
}
|
||||
|
||||
// Copy message to its own buffer
|
||||
CDataStream vMsg(vRecv.begin(), vRecv.begin() + nMessageSize, vRecv.nType, vRecv.nVersion);
|
||||
vRecv.ignore(nMessageSize);
|
||||
|
||||
// Checksum
|
||||
if (vRecv.GetVersion() >= 209)
|
||||
{
|
||||
uint256 hash = Hash(vMsg.begin(), vMsg.end());
|
||||
uint256 hash = Hash(vRecv.begin(), vRecv.begin() + nMessageSize);
|
||||
unsigned int nChecksum = 0;
|
||||
memcpy(&nChecksum, &hash, sizeof(nChecksum));
|
||||
if (nChecksum != hdr.nChecksum)
|
||||
@@ -2040,6 +2089,10 @@ bool ProcessMessages(CNode* pfrom)
|
||||
}
|
||||
}
|
||||
|
||||
// Copy message to its own buffer
|
||||
CDataStream vMsg(vRecv.begin(), vRecv.begin() + nMessageSize, vRecv.nType, vRecv.nVersion);
|
||||
vRecv.ignore(nMessageSize);
|
||||
|
||||
// Process message
|
||||
bool fRet = false;
|
||||
try
|
||||
@@ -2126,6 +2179,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
// Disconnect if we connected to ourself
|
||||
if (nNonce == nLocalHostNonce && nNonce > 1)
|
||||
{
|
||||
printf("connected to self at %s, disconnecting\n", pfrom->addr.ToString().c_str());
|
||||
pfrom->fDisconnect = true;
|
||||
return true;
|
||||
}
|
||||
@@ -2146,6 +2200,24 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
if (pfrom->nVersion < 209)
|
||||
pfrom->vRecv.SetVersion(min(pfrom->nVersion, VERSION));
|
||||
|
||||
if (!pfrom->fInbound)
|
||||
{
|
||||
// Advertise our address
|
||||
if (addrLocalHost.IsRoutable() && !fUseProxy)
|
||||
{
|
||||
CAddress addr(addrLocalHost);
|
||||
addr.nTime = GetAdjustedTime();
|
||||
pfrom->PushAddress(addr);
|
||||
}
|
||||
|
||||
// Get recent addresses
|
||||
if (pfrom->nVersion >= 31402 || mapAddresses.size() < 1000)
|
||||
{
|
||||
pfrom->PushMessage("getaddr");
|
||||
pfrom->fGetAddr = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Ask the first connected node for block updates
|
||||
static int nAskedForBlocks;
|
||||
if (!pfrom->fClient && (nAskedForBlocks < 1 || vNodes.size() <= 1))
|
||||
@@ -2182,14 +2254,18 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
{
|
||||
vector<CAddress> vAddr;
|
||||
vRecv >> vAddr;
|
||||
if (pfrom->nVersion < 200) // don't want addresses from 0.1.5
|
||||
|
||||
// Don't want addr from older versions unless seeding
|
||||
if (pfrom->nVersion < 209)
|
||||
return true;
|
||||
if (pfrom->nVersion < 209 && mapAddresses.size() > 1000) // don't want addr from 0.2.0 unless seeding
|
||||
if (pfrom->nVersion < 31402 && mapAddresses.size() > 1000)
|
||||
return true;
|
||||
if (vAddr.size() > 1000)
|
||||
return error("message addr size() = %d", vAddr.size());
|
||||
|
||||
// Store the new addresses
|
||||
int64 nNow = GetAdjustedTime();
|
||||
int64 nSince = nNow - 10 * 60;
|
||||
foreach(CAddress& addr, vAddr)
|
||||
{
|
||||
if (fShutdown)
|
||||
@@ -2197,25 +2273,33 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
// ignore IPv6 for now, since it isn't implemented anyway
|
||||
if (!addr.IsIPv4())
|
||||
continue;
|
||||
addr.nTime = GetAdjustedTime() - 2 * 60 * 60;
|
||||
if (pfrom->fGetAddr || vAddr.size() > 10)
|
||||
addr.nTime -= 5 * 24 * 60 * 60;
|
||||
AddAddress(addr);
|
||||
if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60)
|
||||
addr.nTime = nNow - 5 * 24 * 60 * 60;
|
||||
AddAddress(addr, 2 * 60 * 60);
|
||||
pfrom->AddAddressKnown(addr);
|
||||
if (!pfrom->fGetAddr && addr.IsRoutable())
|
||||
if (addr.nTime > nSince && !pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable())
|
||||
{
|
||||
// Relay to a limited number of other nodes
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
{
|
||||
// Use deterministic randomness to send to
|
||||
// the same places for 12 hours at a time
|
||||
// Use deterministic randomness to send to the same nodes for 24 hours
|
||||
// at a time so the setAddrKnowns of the chosen nodes prevent repeats
|
||||
static uint256 hashSalt;
|
||||
if (hashSalt == 0)
|
||||
RAND_bytes((unsigned char*)&hashSalt, sizeof(hashSalt));
|
||||
uint256 hashRand = addr.ip ^ ((GetTime()+addr.ip)/(12*60*60)) ^ hashSalt;
|
||||
uint256 hashRand = hashSalt ^ (((int64)addr.ip)<<32) ^ ((GetTime()+addr.ip)/(24*60*60));
|
||||
hashRand = Hash(BEGIN(hashRand), END(hashRand));
|
||||
multimap<uint256, CNode*> mapMix;
|
||||
foreach(CNode* pnode, vNodes)
|
||||
mapMix.insert(make_pair(hashRand = Hash(BEGIN(hashRand), END(hashRand)), pnode));
|
||||
{
|
||||
if (pnode->nVersion < 31402)
|
||||
continue;
|
||||
unsigned int nPointer;
|
||||
memcpy(&nPointer, &pnode, sizeof(nPointer));
|
||||
uint256 hashKey = hashRand ^ nPointer;
|
||||
hashKey = Hash(BEGIN(hashKey), END(hashKey));
|
||||
mapMix.insert(make_pair(hashKey, pnode));
|
||||
}
|
||||
int nRelayNodes = 2;
|
||||
for (multimap<uint256, CNode*>::iterator mi = mapMix.begin(); mi != mapMix.end() && nRelayNodes-- > 0; ++mi)
|
||||
((*mi).second)->PushAddress(addr);
|
||||
@@ -2386,7 +2470,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
|
||||
if (tx.AcceptToMemoryPool(true))
|
||||
{
|
||||
printf(" accepted orphan tx %s\n", inv.hash.ToString().substr(0,6).c_str());
|
||||
printf(" accepted orphan tx %s\n", inv.hash.ToString().substr(0,10).c_str());
|
||||
AddToWalletIfMine(tx, NULL);
|
||||
RelayMessage(inv, vMsg);
|
||||
mapAlreadyAskedFor.erase(inv);
|
||||
@@ -2400,7 +2484,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
}
|
||||
else if (fMissingInputs)
|
||||
{
|
||||
printf("storing orphan tx %s\n", inv.hash.ToString().substr(0,6).c_str());
|
||||
printf("storing orphan tx %s\n", inv.hash.ToString().substr(0,10).c_str());
|
||||
AddOrphanTx(vMsg);
|
||||
}
|
||||
}
|
||||
@@ -2427,15 +2511,20 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
{
|
||||
// Nodes rebroadcast an addr every 24 hours
|
||||
pfrom->vAddrToSend.clear();
|
||||
int64 nSince = GetAdjustedTime() - 6 * 60 * 60; // in the last 6 hours
|
||||
int64 nSince = GetAdjustedTime() - 3 * 60 * 60; // in the last 3 hours
|
||||
CRITICAL_BLOCK(cs_mapAddresses)
|
||||
{
|
||||
unsigned int nCount = 0;
|
||||
foreach(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
|
||||
{
|
||||
if (fShutdown)
|
||||
return true;
|
||||
const CAddress& addr = item.second;
|
||||
if (addr.nTime > nSince)
|
||||
nCount++;
|
||||
}
|
||||
foreach(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
|
||||
{
|
||||
const CAddress& addr = item.second;
|
||||
if (addr.nTime > nSince && GetRand(nCount) < 2500)
|
||||
pfrom->PushAddress(addr);
|
||||
}
|
||||
}
|
||||
@@ -2458,7 +2547,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
|
||||
// Keep giving the same key to the same ip until they use it
|
||||
if (!mapReuseKey.count(pfrom->addr.ip))
|
||||
mapReuseKey[pfrom->addr.ip] = GenerateNewKey();
|
||||
mapReuseKey[pfrom->addr.ip] = CWalletDB().GetKeyFromKeyPool();
|
||||
|
||||
// Send back approval of order and pubkey to use
|
||||
CScript scriptPubKey;
|
||||
@@ -2572,9 +2661,12 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
||||
if (pto->nLastSend && GetTime() - pto->nLastSend > 30 * 60 && pto->vSend.empty())
|
||||
pto->PushMessage("ping");
|
||||
|
||||
// Resend wallet transactions that haven't gotten in a block yet
|
||||
ResendWalletTransactions();
|
||||
|
||||
// Address refresh broadcast
|
||||
static int64 nLastRebroadcast;
|
||||
if (GetTime() - nLastRebroadcast > 24 * 60 * 60) // every 24 hours
|
||||
if (GetTime() - nLastRebroadcast > 24 * 60 * 60)
|
||||
{
|
||||
nLastRebroadcast = GetTime();
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
@@ -2586,13 +2678,42 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
||||
|
||||
// Rebroadcast our address
|
||||
if (addrLocalHost.IsRoutable() && !fUseProxy)
|
||||
pnode->PushAddress(addrLocalHost);
|
||||
{
|
||||
CAddress addr(addrLocalHost);
|
||||
addr.nTime = GetAdjustedTime();
|
||||
pnode->PushAddress(addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Resend wallet transactions that haven't gotten in a block yet
|
||||
ResendWalletTransactions();
|
||||
// Clear out old addresses periodically so it's not too much work at once
|
||||
static int64 nLastClear;
|
||||
if (nLastClear == 0)
|
||||
nLastClear = GetTime();
|
||||
if (GetTime() - nLastClear > 10 * 60 && vNodes.size() >= 3)
|
||||
{
|
||||
nLastClear = GetTime();
|
||||
CRITICAL_BLOCK(cs_mapAddresses)
|
||||
{
|
||||
CAddrDB addrdb;
|
||||
int64 nSince = GetAdjustedTime() - 14 * 24 * 60 * 60;
|
||||
for (map<vector<unsigned char>, CAddress>::iterator mi = mapAddresses.begin();
|
||||
mi != mapAddresses.end();)
|
||||
{
|
||||
const CAddress& addr = (*mi).second;
|
||||
if (addr.nTime < nSince)
|
||||
{
|
||||
if (mapAddresses.size() < 1000 || GetTime() > nLastClear + 20)
|
||||
break;
|
||||
addrdb.EraseAddress(addr);
|
||||
mapAddresses.erase(mi++);
|
||||
}
|
||||
else
|
||||
mi++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
@@ -2774,7 +2895,7 @@ void ThreadBitcoinMiner(void* parg)
|
||||
vnThreadsRunning[3]--;
|
||||
PrintException(NULL, "ThreadBitcoinMiner()");
|
||||
}
|
||||
UIThreadCall(bind(CalledSetStatusBar, "", 0));
|
||||
UIThreadCall(boost::bind(CalledSetStatusBar, "", 0));
|
||||
nHPSTimerStart = 0;
|
||||
if (vnThreadsRunning[3] == 0)
|
||||
dHashesPerSec = 0;
|
||||
@@ -2789,7 +2910,7 @@ void CallCPUID(int in, int& aret, int& cret)
|
||||
"mov %2, %%eax; " // in into eax
|
||||
"cpuid;"
|
||||
"mov %%eax, %0;" // eax into a
|
||||
"mov %%ecx, %1;" // eax into c
|
||||
"mov %%ecx, %1;" // ecx into c
|
||||
:"=r"(a),"=r"(c) /* output */
|
||||
:"r"(in) /* input */
|
||||
:"%eax","%ecx" /* clobbered register */
|
||||
@@ -2831,6 +2952,10 @@ bool Detect128BitSSE2()
|
||||
bool fUseSSE2 = ((fIntel && nFamily * 10000 + nModel >= 60026) ||
|
||||
(fAMD && nFamily * 10000 + nModel >= 160010));
|
||||
|
||||
// AMD reports a lower model number in 64-bit mode
|
||||
if (fAMD && sizeof(void*) > 4 && nFamily * 10000 + nModel >= 160000)
|
||||
fUseSSE2 = true;
|
||||
|
||||
static bool fPrinted;
|
||||
if (!fPrinted)
|
||||
{
|
||||
@@ -2915,12 +3040,13 @@ void BitcoinMiner()
|
||||
if (mapArgs.count("-4way"))
|
||||
f4WaySSE2 = (mapArgs["-4way"] != "0");
|
||||
|
||||
CKey key;
|
||||
key.MakeNewKey();
|
||||
CBigNum bnExtraNonce = 0;
|
||||
CReserveKey reservekey;
|
||||
unsigned int nExtraNonce = 0;
|
||||
int64 nPrevTime = 0;
|
||||
while (fGenerateBitcoins)
|
||||
{
|
||||
Sleep(50);
|
||||
if (AffinityBugWorkaround(ThreadBitcoinMiner))
|
||||
return;
|
||||
if (fShutdown)
|
||||
return;
|
||||
while (vNodes.empty() || IsInitialBlockDownload())
|
||||
@@ -2943,9 +3069,15 @@ void BitcoinMiner()
|
||||
CTransaction txNew;
|
||||
txNew.vin.resize(1);
|
||||
txNew.vin[0].prevout.SetNull();
|
||||
txNew.vin[0].scriptSig << nBits << ++bnExtraNonce;
|
||||
int64 nNow = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
|
||||
if (++nExtraNonce >= 0x7f && nNow > nPrevTime+1)
|
||||
{
|
||||
nExtraNonce = 1;
|
||||
nPrevTime = nNow;
|
||||
}
|
||||
txNew.vin[0].scriptSig << nBits << CBigNum(nExtraNonce);
|
||||
txNew.vout.resize(1);
|
||||
txNew.vout[0].scriptPubKey << key.GetPubKey() << OP_CHECKSIG;
|
||||
txNew.vout[0].scriptPubKey << reservekey.GetReservedKey() << OP_CHECKSIG;
|
||||
|
||||
|
||||
//
|
||||
@@ -2964,42 +3096,97 @@ void BitcoinMiner()
|
||||
CRITICAL_BLOCK(cs_mapTransactions)
|
||||
{
|
||||
CTxDB txdb("r");
|
||||
|
||||
// Priority order to process transactions
|
||||
multimap<double, CTransaction*> mapPriority;
|
||||
for (map<uint256, CTransaction>::iterator mi = mapTransactions.begin(); mi != mapTransactions.end(); ++mi)
|
||||
{
|
||||
CTransaction& tx = (*mi).second;
|
||||
if (tx.IsCoinBase() || !tx.IsFinal())
|
||||
continue;
|
||||
|
||||
double dPriority = 0;
|
||||
foreach(const CTxIn& txin, tx.vin)
|
||||
{
|
||||
// Read prev transaction
|
||||
CTransaction txPrev;
|
||||
CTxIndex txindex;
|
||||
if (!txPrev.ReadFromDisk(txdb, txin.prevout, txindex))
|
||||
continue;
|
||||
int64 nValueIn = txPrev.vout[txin.prevout.n].nValue;
|
||||
|
||||
// Read block header
|
||||
int nConf = 0;
|
||||
CBlock block;
|
||||
if (block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false))
|
||||
{
|
||||
map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(block.GetHash());
|
||||
if (it != mapBlockIndex.end())
|
||||
{
|
||||
CBlockIndex* pindex = (*it).second;
|
||||
if (pindex->IsInMainChain())
|
||||
nConf = 1 + nBestHeight - pindex->nHeight;
|
||||
}
|
||||
}
|
||||
|
||||
dPriority += (double)nValueIn * nConf;
|
||||
|
||||
if (fDebug && mapArgs.count("-printpriority"))
|
||||
printf("priority nValueIn=%-12I64d nConf=%-5d dPriority=%-20.1f\n", nValueIn, nConf, dPriority);
|
||||
}
|
||||
|
||||
// Priority is sum(valuein * age) / txsize
|
||||
dPriority /= ::GetSerializeSize(tx, SER_NETWORK);
|
||||
|
||||
mapPriority.insert(make_pair(-dPriority, &(*mi).second));
|
||||
|
||||
if (fDebug && mapArgs.count("-printpriority"))
|
||||
printf("priority %-20.1f %s\n%s\n", dPriority, tx.GetHash().ToString().substr(0,10).c_str(), tx.ToString().c_str());
|
||||
}
|
||||
|
||||
// Collect transactions into block
|
||||
map<uint256, CTxIndex> mapTestPool;
|
||||
vector<char> vfAlreadyAdded(mapTransactions.size());
|
||||
uint64 nBlockSize = 1000;
|
||||
int nBlockSigOps = 100;
|
||||
bool fFoundSomething = true;
|
||||
while (fFoundSomething)
|
||||
{
|
||||
fFoundSomething = false;
|
||||
unsigned int n = 0;
|
||||
for (map<uint256, CTransaction>::iterator mi = mapTransactions.begin(); mi != mapTransactions.end(); ++mi, ++n)
|
||||
for (multimap<double, CTransaction*>::iterator mi = mapPriority.begin(); mi != mapPriority.end();)
|
||||
{
|
||||
if (vfAlreadyAdded[n])
|
||||
continue;
|
||||
CTransaction& tx = (*mi).second;
|
||||
if (tx.IsCoinBase() || !tx.IsFinal())
|
||||
continue;
|
||||
CTransaction& tx = *(*mi).second;
|
||||
unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK);
|
||||
if (nBlockSize + nTxSize >= MAX_BLOCK_SIZE_GEN)
|
||||
{
|
||||
mapPriority.erase(mi++);
|
||||
continue;
|
||||
}
|
||||
int nTxSigOps = tx.GetSigOpCount();
|
||||
if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
|
||||
{
|
||||
mapPriority.erase(mi++);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Transaction fee based on block size
|
||||
int64 nMinFee = tx.GetMinFee(nBlockSize);
|
||||
|
||||
// Connecting can fail due to dependency on other memory pool transactions
|
||||
// that aren't in the block yet, so keep trying in later passes
|
||||
map<uint256, CTxIndex> mapTestPoolTmp(mapTestPool);
|
||||
if (!tx.ConnectInputs(txdb, mapTestPoolTmp, CDiskTxPos(1,1,1), pindexPrev, nFees, false, true, nMinFee))
|
||||
{
|
||||
mi++;
|
||||
continue;
|
||||
}
|
||||
swap(mapTestPool, mapTestPoolTmp);
|
||||
|
||||
// Added
|
||||
pblock->vtx.push_back(tx);
|
||||
nBlockSize += nTxSize;
|
||||
nBlockSigOps += nTxSigOps;
|
||||
vfAlreadyAdded[n] = true;
|
||||
fFoundSomething = true;
|
||||
mapPriority.erase(mi++);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3031,9 +3218,9 @@ void BitcoinMiner()
|
||||
tmpworkspace& tmp = *(tmpworkspace*)alignup<16>(tmpbuf);
|
||||
|
||||
tmp.block.nVersion = pblock->nVersion;
|
||||
tmp.block.hashPrevBlock = pblock->hashPrevBlock = (pindexPrev ? pindexPrev->GetBlockHash() : 0);
|
||||
tmp.block.hashPrevBlock = pblock->hashPrevBlock = pindexPrev->GetBlockHash();
|
||||
tmp.block.hashMerkleRoot = pblock->hashMerkleRoot = pblock->BuildMerkleTree();
|
||||
tmp.block.nTime = pblock->nTime = max((pindexPrev ? pindexPrev->GetMedianTimePast()+1 : 0), GetAdjustedTime());
|
||||
tmp.block.nTime = pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
|
||||
tmp.block.nBits = pblock->nBits = nBits;
|
||||
tmp.block.nNonce = pblock->nNonce = 0;
|
||||
|
||||
@@ -3095,10 +3282,8 @@ void BitcoinMiner()
|
||||
{
|
||||
if (pindexPrev == pindexBest)
|
||||
{
|
||||
// Save key
|
||||
if (!AddKey(key))
|
||||
return;
|
||||
key.MakeNewKey();
|
||||
// Remove key from key pool
|
||||
reservekey.KeepKey();
|
||||
|
||||
// Track how many getdata requests this block gets
|
||||
CRITICAL_BLOCK(cs_mapRequestCount)
|
||||
@@ -3136,7 +3321,7 @@ void BitcoinMiner()
|
||||
nHPSTimerStart = GetTimeMillis();
|
||||
nHashCounter = 0;
|
||||
string strStatus = strprintf(" %.0f khash/s", dHashesPerSec/1000.0);
|
||||
UIThreadCall(bind(CalledSetStatusBar, strStatus, 0));
|
||||
UIThreadCall(boost::bind(CalledSetStatusBar, strStatus, 0));
|
||||
static int64 nLogTime;
|
||||
if (GetTime() - nLogTime > 30 * 60)
|
||||
{
|
||||
@@ -3204,9 +3389,7 @@ int64 GetBalance()
|
||||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||
{
|
||||
CWalletTx* pcoin = &(*it).second;
|
||||
if (!pcoin->IsFinal() || pcoin->fSpent)
|
||||
continue;
|
||||
if (pcoin->GetDepthInMainChain() < 1 && pcoin->GetDebit() <= 0)
|
||||
if (!pcoin->IsFinal() || pcoin->fSpent || !pcoin->IsConfirmed())
|
||||
continue;
|
||||
nTotal += pcoin->GetCredit(true);
|
||||
}
|
||||
@@ -3217,7 +3400,7 @@ int64 GetBalance()
|
||||
}
|
||||
|
||||
|
||||
bool SelectCoins(int64 nTargetValue, set<CWalletTx*>& setCoinsRet)
|
||||
bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<CWalletTx*>& setCoinsRet)
|
||||
{
|
||||
setCoinsRet.clear();
|
||||
|
||||
@@ -3237,10 +3420,13 @@ bool SelectCoins(int64 nTargetValue, set<CWalletTx*>& setCoinsRet)
|
||||
|
||||
foreach(CWalletTx* pcoin, vCoins)
|
||||
{
|
||||
if (!pcoin->IsFinal() || pcoin->fSpent)
|
||||
if (!pcoin->IsFinal() || pcoin->fSpent || !pcoin->IsConfirmed())
|
||||
continue;
|
||||
if (pcoin->GetDepthInMainChain() < 1 && pcoin->GetDebit() <= 0)
|
||||
|
||||
int nDepth = pcoin->GetDepthInMainChain();
|
||||
if (nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
|
||||
continue;
|
||||
|
||||
int64 n = pcoin->GetCredit();
|
||||
if (n <= 0)
|
||||
continue;
|
||||
@@ -3325,19 +3511,25 @@ bool SelectCoins(int64 nTargetValue, set<CWalletTx*>& setCoinsRet)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CKey& keyRet, int64& nFeeRequiredRet)
|
||||
bool SelectCoins(int64 nTargetValue, set<CWalletTx*>& setCoinsRet)
|
||||
{
|
||||
return (SelectCoinsMinConf(nTargetValue, 1, 6, setCoinsRet) ||
|
||||
SelectCoinsMinConf(nTargetValue, 1, 1, setCoinsRet) ||
|
||||
SelectCoinsMinConf(nTargetValue, 0, 1, setCoinsRet));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
|
||||
{
|
||||
nFeeRequiredRet = 0;
|
||||
CRITICAL_BLOCK(cs_main)
|
||||
{
|
||||
// txdb must be opened before the mapWallet lock
|
||||
CTxDB txdb("r");
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
{
|
||||
int64 nFee = nTransactionFee;
|
||||
nFeeRet = nTransactionFee;
|
||||
loop
|
||||
{
|
||||
wtxNew.vin.clear();
|
||||
@@ -3346,7 +3538,7 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CK
|
||||
if (nValue < 0)
|
||||
return false;
|
||||
int64 nValueOut = nValue;
|
||||
int64 nTotalValue = nValue + nFee;
|
||||
int64 nTotalValue = nValue + nFeeRet;
|
||||
|
||||
// Choose coins to use
|
||||
set<CWalletTx*> setCoins;
|
||||
@@ -3372,18 +3564,20 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CK
|
||||
// rediscover unknown transactions that were written with keys of ours to recover
|
||||
// post-backup change.
|
||||
|
||||
// New private key
|
||||
if (keyRet.IsNull())
|
||||
keyRet.MakeNewKey();
|
||||
// Reserve a new key pair from key pool
|
||||
vector<unsigned char> vchPubKey = reservekey.GetReservedKey();
|
||||
assert(mapKeys.count(vchPubKey));
|
||||
|
||||
// Fill a vout to ourself, using same address type as the payment
|
||||
CScript scriptChange;
|
||||
if (scriptPubKey.GetBitcoinAddressHash160() != 0)
|
||||
scriptChange.SetBitcoinAddress(keyRet.GetPubKey());
|
||||
scriptChange.SetBitcoinAddress(vchPubKey);
|
||||
else
|
||||
scriptChange << keyRet.GetPubKey() << OP_CHECKSIG;
|
||||
scriptChange << vchPubKey << OP_CHECKSIG;
|
||||
wtxNew.vout.push_back(CTxOut(nChange, scriptChange));
|
||||
}
|
||||
else
|
||||
reservekey.ReturnKey();
|
||||
|
||||
// Fill a vout to the payee
|
||||
if (fChangeFirst)
|
||||
@@ -3404,13 +3598,16 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CK
|
||||
return false;
|
||||
|
||||
// Limit size
|
||||
if (::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK) >= MAX_BLOCK_SIZE_GEN/5)
|
||||
unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK);
|
||||
if (nBytes >= MAX_BLOCK_SIZE_GEN/5)
|
||||
return false;
|
||||
|
||||
// Check that enough fee is included
|
||||
if (nFee < wtxNew.GetMinFee())
|
||||
int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
|
||||
int64 nMinFee = wtxNew.GetMinFee();
|
||||
if (nFeeRet < max(nPayFee, nMinFee))
|
||||
{
|
||||
nFee = nFeeRequiredRet = wtxNew.GetMinFee();
|
||||
nFeeRet = max(nPayFee, nMinFee);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -3426,7 +3623,7 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CK
|
||||
}
|
||||
|
||||
// Call after CreateTransaction unless you want to abort
|
||||
bool CommitTransaction(CWalletTx& wtxNew, const CKey& key)
|
||||
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_main)
|
||||
{
|
||||
@@ -3438,9 +3635,8 @@ bool CommitTransaction(CWalletTx& wtxNew, const CKey& key)
|
||||
// maybe makes sense; please don't do it anywhere else.
|
||||
CWalletDB walletdb("r");
|
||||
|
||||
// Add the change's private key to wallet
|
||||
if (!key.IsNull() && !AddKey(key))
|
||||
throw runtime_error("CommitTransaction() : AddKey failed");
|
||||
// Take key pair from key pool so it won't be used again
|
||||
reservekey.KeepKey();
|
||||
|
||||
// Add tx to wallet, because if it has change it's also ours,
|
||||
// otherwise just for transaction history.
|
||||
@@ -3482,9 +3678,9 @@ string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAs
|
||||
{
|
||||
CRITICAL_BLOCK(cs_main)
|
||||
{
|
||||
CKey key;
|
||||
CReserveKey reservekey;
|
||||
int64 nFeeRequired;
|
||||
if (!CreateTransaction(scriptPubKey, nValue, wtxNew, key, nFeeRequired))
|
||||
if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
|
||||
{
|
||||
string strError;
|
||||
if (nValue + nFeeRequired > GetBalance())
|
||||
@@ -3498,7 +3694,7 @@ string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAs
|
||||
if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL))
|
||||
return "ABORTED";
|
||||
|
||||
if (!CommitTransaction(wtxNew, key))
|
||||
if (!CommitTransaction(wtxNew, reservekey))
|
||||
return _("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
|
||||
}
|
||||
MainFrameRepaint();
|
||||
|
||||
77
main.h
77
main.h
@@ -22,7 +22,6 @@ static const int64 CENT = 1000000;
|
||||
static const int64 MAX_MONEY = 21000000 * COIN;
|
||||
inline bool MoneyRange(int64 nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
|
||||
static const int COINBASE_MATURITY = 100;
|
||||
static const CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
|
||||
|
||||
|
||||
|
||||
@@ -31,7 +30,8 @@ static const CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
|
||||
|
||||
extern CCriticalSection cs_main;
|
||||
extern map<uint256, CBlockIndex*> mapBlockIndex;
|
||||
extern const uint256 hashGenesisBlock;
|
||||
extern uint256 hashGenesisBlock;
|
||||
extern CBigNum bnProofOfWorkLimit;
|
||||
extern CBlockIndex* pindexGenesisBlock;
|
||||
extern int nBestHeight;
|
||||
extern CBigNum bnBestChainWork;
|
||||
@@ -76,8 +76,8 @@ bool ProcessMessages(CNode* pfrom);
|
||||
bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv);
|
||||
bool SendMessages(CNode* pto, bool fSendTrickle);
|
||||
int64 GetBalance();
|
||||
bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CKey& keyRet, int64& nFeeRequiredRet);
|
||||
bool CommitTransaction(CWalletTx& wtxNew, const CKey& key);
|
||||
bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
|
||||
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
|
||||
bool BroadcastTransaction(CWalletTx& wtxNew);
|
||||
string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
|
||||
string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
|
||||
@@ -195,7 +195,7 @@ public:
|
||||
|
||||
string ToString() const
|
||||
{
|
||||
return strprintf("COutPoint(%s, %d)", hash.ToString().substr(0,6).c_str(), n);
|
||||
return strprintf("COutPoint(%s, %d)", hash.ToString().substr(0,10).c_str(), n);
|
||||
}
|
||||
|
||||
void print() const
|
||||
@@ -361,7 +361,7 @@ public:
|
||||
{
|
||||
if (scriptPubKey.size() < 6)
|
||||
return "CTxOut(error)";
|
||||
return strprintf("CTxOut(nValue=%"PRI64d".%08"PRI64d", scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,24).c_str());
|
||||
return strprintf("CTxOut(nValue=%"PRI64d".%08"PRI64d", scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,30).c_str());
|
||||
}
|
||||
|
||||
void print() const
|
||||
@@ -487,6 +487,11 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsFromMe() const
|
||||
{
|
||||
return (GetDebit() > 0);
|
||||
}
|
||||
|
||||
int64 GetDebit() const
|
||||
{
|
||||
int64 nDebit = 0;
|
||||
@@ -580,7 +585,6 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
friend bool operator==(const CTransaction& a, const CTransaction& b)
|
||||
{
|
||||
return (a.nVersion == b.nVersion &&
|
||||
@@ -599,7 +603,7 @@ public:
|
||||
{
|
||||
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(),
|
||||
GetHash().ToString().substr(0,10).c_str(),
|
||||
nVersion,
|
||||
vin.size(),
|
||||
vout.size(),
|
||||
@@ -617,6 +621,9 @@ public:
|
||||
}
|
||||
|
||||
|
||||
bool ReadFromDisk(CTxDB& txdb, COutPoint prevout, CTxIndex& txindexRet);
|
||||
bool ReadFromDisk(CTxDB& txdb, COutPoint prevout);
|
||||
bool ReadFromDisk(COutPoint prevout);
|
||||
bool DisconnectInputs(CTxDB& txdb);
|
||||
bool ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPool, CDiskTxPos posThisTx,
|
||||
CBlockIndex* pindexBlock, int64& nFees, bool fBlock, bool fMiner, int64 nMinFee=0);
|
||||
@@ -787,6 +794,52 @@ public:
|
||||
return nCreditCached;
|
||||
}
|
||||
|
||||
bool IsFromMe() const
|
||||
{
|
||||
return (GetDebit() > 0);
|
||||
}
|
||||
|
||||
bool IsConfirmed() const
|
||||
{
|
||||
// Quick answer in most cases
|
||||
if (!IsFinal())
|
||||
return false;
|
||||
if (GetDepthInMainChain() >= 1)
|
||||
return true;
|
||||
if (!IsFromMe()) // using wtx's cached debit
|
||||
return false;
|
||||
|
||||
// If no confirmations but it's from us, we can still
|
||||
// consider it confirmed if all dependencies are confirmed
|
||||
map<uint256, const CMerkleTx*> mapPrev;
|
||||
vector<const CMerkleTx*> vWorkQueue;
|
||||
vWorkQueue.reserve(vtxPrev.size()+1);
|
||||
vWorkQueue.push_back(this);
|
||||
for (int i = 0; i < vWorkQueue.size(); i++)
|
||||
{
|
||||
const CMerkleTx* ptx = vWorkQueue[i];
|
||||
|
||||
if (!ptx->IsFinal())
|
||||
return false;
|
||||
if (ptx->GetDepthInMainChain() >= 1)
|
||||
return true;
|
||||
if (!ptx->IsFromMe())
|
||||
return false;
|
||||
|
||||
if (mapPrev.empty())
|
||||
foreach(const CMerkleTx& tx, vtxPrev)
|
||||
mapPrev[tx.GetHash()] = &tx;
|
||||
|
||||
foreach(const CTxIn& txin, ptx->vin)
|
||||
{
|
||||
if (!mapPrev.count(txin.prevout.hash))
|
||||
return false;
|
||||
vWorkQueue.push_back(mapPrev[txin.prevout.hash]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteToDisk()
|
||||
{
|
||||
return CWalletDB().WriteTx(GetHash(), *this);
|
||||
@@ -1065,7 +1118,7 @@ public:
|
||||
GetHash().ToString().substr(0,20).c_str(),
|
||||
nVersion,
|
||||
hashPrevBlock.ToString().substr(0,20).c_str(),
|
||||
hashMerkleRoot.ToString().substr(0,6).c_str(),
|
||||
hashMerkleRoot.ToString().substr(0,10).c_str(),
|
||||
nTime, nBits, nNonce,
|
||||
vtx.size());
|
||||
for (int i = 0; i < vtx.size(); i++)
|
||||
@@ -1075,7 +1128,7 @@ public:
|
||||
}
|
||||
printf(" vMerkleTree: ");
|
||||
for (int i = 0; i < vMerkleTree.size(); i++)
|
||||
printf("%s ", vMerkleTree[i].ToString().substr(0,6).c_str());
|
||||
printf("%s ", vMerkleTree[i].ToString().substr(0,10).c_str());
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
@@ -1233,7 +1286,7 @@ public:
|
||||
{
|
||||
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(),
|
||||
hashMerkleRoot.ToString().substr(0,10).c_str(),
|
||||
GetBlockHash().ToString().substr(0,20).c_str());
|
||||
}
|
||||
|
||||
@@ -1623,7 +1676,7 @@ public:
|
||||
bool Cancels(const CAlert& alert) const
|
||||
{
|
||||
if (!IsInEffect())
|
||||
false;
|
||||
return false; // this was a no-op before 31403
|
||||
return (alert.nID <= nCancel || setCancel.count(alert.nID));
|
||||
}
|
||||
|
||||
|
||||
@@ -22,9 +22,10 @@ LIBS= -dead_strip \
|
||||
$(DEPSDIR)/lib/libboost_filesystem.a \
|
||||
$(DEPSDIR)/lib/libboost_program_options.a \
|
||||
$(DEPSDIR)/lib/libboost_thread.a \
|
||||
$(DEPSDIR)/lib/libssl.a \
|
||||
$(DEPSDIR)/lib/libcrypto.a
|
||||
|
||||
DEFS=$(shell $(DEPSDIR)/bin/wx-config --cxxflags) -D__WXMAC_OSX__ -DNOPCH -DMSG_NOSIGNAL=0
|
||||
DEFS=$(shell $(DEPSDIR)/bin/wx-config --cxxflags) -D__WXMAC_OSX__ -DNOPCH -DMSG_NOSIGNAL=0 -DUSE_SSL
|
||||
|
||||
DEBUGFLAGS=-g -DwxDEBUG_LEVEL=0
|
||||
# ppc doesn't work because we don't support big-endian
|
||||
|
||||
@@ -23,11 +23,14 @@ LIBS= \
|
||||
-l boost_program_options \
|
||||
-l boost_thread \
|
||||
-l db_cxx \
|
||||
-l ssl \
|
||||
-l crypto \
|
||||
-Wl,-Bdynamic \
|
||||
-l gthread-2.0
|
||||
-l gthread-2.0 \
|
||||
-l z \
|
||||
-l dl
|
||||
|
||||
DEFS=-D__WXGTK__ -DNOPCH -DFOURWAYSSE2
|
||||
DEFS=-D__WXGTK__ -DNOPCH -DFOURWAYSSE2 -DUSE_SSL
|
||||
DEBUGFLAGS=-g -D__WXDEBUG__
|
||||
CFLAGS=-O2 -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
|
||||
HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h \
|
||||
|
||||
39
net.cpp
39
net.cpp
@@ -20,7 +20,7 @@ bool OpenNetworkConnection(const CAddress& addrConnect);
|
||||
//
|
||||
bool fClient = false;
|
||||
uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
|
||||
CAddress addrLocalHost(0, DEFAULT_PORT, nLocalServices);
|
||||
CAddress addrLocalHost(0, 0, nLocalServices);
|
||||
CNode* pnodeLocalHost = NULL;
|
||||
uint64 nLocalHostNonce = 0;
|
||||
array<int, 10> vnThreadsRunning;
|
||||
@@ -144,7 +144,7 @@ bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const cha
|
||||
}
|
||||
}
|
||||
closesocket(hSocket);
|
||||
if (strLine.find("<"))
|
||||
if (strLine.find("<") != -1)
|
||||
strLine = strLine.substr(0, strLine.find("<"));
|
||||
strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
|
||||
while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
|
||||
@@ -224,12 +224,13 @@ bool GetMyExternalIP(unsigned int& ipRet)
|
||||
|
||||
|
||||
|
||||
bool AddAddress(CAddress addr)
|
||||
bool AddAddress(CAddress addr, int64 nTimePenalty)
|
||||
{
|
||||
if (!addr.IsRoutable())
|
||||
return false;
|
||||
if (addr.ip == addrLocalHost.ip)
|
||||
return false;
|
||||
addr.nTime = max((int64)0, (int64)addr.nTime - nTimePenalty);
|
||||
CRITICAL_BLOCK(cs_mapAddresses)
|
||||
{
|
||||
map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
|
||||
@@ -937,7 +938,7 @@ void ThreadOpenConnections2(void* parg)
|
||||
// Add seed nodes if IRC isn't working
|
||||
static bool fSeedUsed;
|
||||
bool fTOR = (fUseProxy && addrProxy.port == htons(9050));
|
||||
if (mapAddresses.empty() && (GetTime() - nStart > 60 || fTOR))
|
||||
if (mapAddresses.empty() && (GetTime() - nStart > 60 || fTOR) && !fTestNet)
|
||||
{
|
||||
for (int i = 0; i < ARRAYLEN(pnSeed); i++)
|
||||
{
|
||||
@@ -1006,7 +1007,7 @@ void ThreadOpenConnections2(void* parg)
|
||||
|
||||
// Randomize the order in a deterministic way, putting the standard port first
|
||||
int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60);
|
||||
if (addr.port != DEFAULT_PORT)
|
||||
if (addr.port != GetDefaultPort())
|
||||
nRandomizer += 2 * 60 * 60;
|
||||
|
||||
// Last seen Base retry frequency
|
||||
@@ -1073,25 +1074,6 @@ bool OpenNetworkConnection(const CAddress& addrConnect)
|
||||
return false;
|
||||
pnode->fNetworkNode = true;
|
||||
|
||||
if (addrLocalHost.IsRoutable() && !fUseProxy)
|
||||
{
|
||||
// Advertise our address
|
||||
vector<CAddress> vAddr;
|
||||
vAddr.push_back(addrLocalHost);
|
||||
pnode->PushMessage("addr", vAddr);
|
||||
}
|
||||
|
||||
// Get as many addresses as we can
|
||||
pnode->PushMessage("getaddr");
|
||||
pnode->fGetAddr = true; // don't relay the results of the getaddr
|
||||
|
||||
////// should the one on the receiving end do this too?
|
||||
// Subscribe our local subscription list
|
||||
const unsigned int nHops = 0;
|
||||
for (unsigned int nChannel = 0; nChannel < pnodeLocalHost->vfSubscribe.size(); nChannel++)
|
||||
if (pnodeLocalHost->vfSubscribe[nChannel])
|
||||
pnode->PushMessage("subscribe", nChannel, nHops);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1185,6 +1167,7 @@ bool BindListenPort(string& strError)
|
||||
{
|
||||
strError = "";
|
||||
int nOne = 1;
|
||||
addrLocalHost.port = GetDefaultPort();
|
||||
|
||||
#ifdef __WXMSW__
|
||||
// Initialize Windows Sockets
|
||||
@@ -1236,12 +1219,12 @@ bool BindListenPort(string& strError)
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
sockaddr.sin_family = AF_INET;
|
||||
sockaddr.sin_addr.s_addr = INADDR_ANY; // bind to all IPs on this computer
|
||||
sockaddr.sin_port = DEFAULT_PORT;
|
||||
sockaddr.sin_port = GetDefaultPort();
|
||||
if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
|
||||
{
|
||||
int nErr = WSAGetLastError();
|
||||
if (nErr == WSAEADDRINUSE)
|
||||
strError = strprintf("Unable to bind to port %d on this computer. Bitcoin is probably already running.", ntohs(sockaddr.sin_port));
|
||||
strError = strprintf(_("Unable to bind to port %d on this computer. Bitcoin is probably already running."), ntohs(sockaddr.sin_port));
|
||||
else
|
||||
strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
|
||||
printf("%s\n", strError.c_str());
|
||||
@@ -1278,7 +1261,7 @@ void StartNode(void* parg)
|
||||
printf("host ip %d: %s\n", i, CAddress(*(unsigned int*)phostent->h_addr_list[i]).ToStringIP().c_str());
|
||||
for (int i = 0; phostent->h_addr_list[i] != NULL; i++)
|
||||
{
|
||||
CAddress addr(*(unsigned int*)phostent->h_addr_list[i], DEFAULT_PORT, nLocalServices);
|
||||
CAddress addr(*(unsigned int*)phostent->h_addr_list[i], GetDefaultPort(), nLocalServices);
|
||||
if (addr.IsValid() && addr.GetByte(3) != 127)
|
||||
{
|
||||
addrLocalHost = addr;
|
||||
@@ -1306,7 +1289,7 @@ void StartNode(void* parg)
|
||||
printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
|
||||
|
||||
// Take the first IP that isn't loopback 127.x.x.x
|
||||
CAddress addr(*(unsigned int*)&s4->sin_addr, DEFAULT_PORT, nLocalServices);
|
||||
CAddress addr(*(unsigned int*)&s4->sin_addr, GetDefaultPort(), nLocalServices);
|
||||
if (addr.IsValid() && addr.GetByte(3) != 127)
|
||||
{
|
||||
addrLocalHost = addr;
|
||||
|
||||
35
net.h
35
net.h
@@ -12,7 +12,7 @@ extern int nBestHeight;
|
||||
|
||||
|
||||
|
||||
static const unsigned short DEFAULT_PORT = 0x8d20; // htons(8333)
|
||||
inline unsigned short GetDefaultPort() { return fTestNet ? htons(18333) : htons(8333); }
|
||||
static const unsigned int PUBLISH_HOPS = 5;
|
||||
enum
|
||||
{
|
||||
@@ -24,7 +24,7 @@ enum
|
||||
|
||||
bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet);
|
||||
bool GetMyExternalIP(unsigned int& ipRet);
|
||||
bool AddAddress(CAddress addr);
|
||||
bool AddAddress(CAddress addr, int64 nTimePenalty=0);
|
||||
void AddressCurrentlyConnected(const CAddress& addr);
|
||||
CNode* FindNode(unsigned int ip);
|
||||
CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0);
|
||||
@@ -48,10 +48,7 @@ bool StopNode();
|
||||
// (4) size
|
||||
// (4) checksum
|
||||
|
||||
// The message start string is designed to be unlikely to occur in normal data.
|
||||
// The characters are rarely used upper ascii, not valid as UTF-8, and produce
|
||||
// a large 4-byte int at any alignment.
|
||||
static const char pchMessageStart[4] = { 0xf9, 0xbe, 0xb4, 0xd9 };
|
||||
extern char pchMessageStart[4];
|
||||
|
||||
class CMessageHeader
|
||||
{
|
||||
@@ -142,7 +139,7 @@ public:
|
||||
unsigned int ip;
|
||||
unsigned short port;
|
||||
|
||||
// disk only
|
||||
// disk and network only
|
||||
unsigned int nTime;
|
||||
|
||||
// memory only
|
||||
@@ -153,11 +150,11 @@ public:
|
||||
Init();
|
||||
}
|
||||
|
||||
CAddress(unsigned int ipIn, unsigned short portIn=DEFAULT_PORT, uint64 nServicesIn=NODE_NETWORK)
|
||||
CAddress(unsigned int ipIn, unsigned short portIn=0, uint64 nServicesIn=NODE_NETWORK)
|
||||
{
|
||||
Init();
|
||||
ip = ipIn;
|
||||
port = portIn;
|
||||
port = (portIn == 0 ? GetDefaultPort() : portIn);
|
||||
nServices = nServicesIn;
|
||||
}
|
||||
|
||||
@@ -188,15 +185,15 @@ public:
|
||||
nServices = NODE_NETWORK;
|
||||
memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
|
||||
ip = INADDR_NONE;
|
||||
port = DEFAULT_PORT;
|
||||
nTime = GetAdjustedTime();
|
||||
port = GetDefaultPort();
|
||||
nTime = 100000000;
|
||||
nLastTry = 0;
|
||||
}
|
||||
|
||||
bool SetAddress(const char* pszIn)
|
||||
{
|
||||
ip = INADDR_NONE;
|
||||
port = DEFAULT_PORT;
|
||||
port = GetDefaultPort();
|
||||
char psz[100];
|
||||
strlcpy(psz, pszIn, sizeof(psz));
|
||||
unsigned int a=0, b=0, c=0, d=0, e=0;
|
||||
@@ -221,11 +218,12 @@ public:
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
if (fRead)
|
||||
const_cast<CAddress*>(this)->Init();
|
||||
if (nType & SER_DISK)
|
||||
{
|
||||
READWRITE(nVersion);
|
||||
if ((nType & SER_DISK) || (nVersion >= 31402 && !(nType & SER_GETHASH)))
|
||||
READWRITE(nTime);
|
||||
}
|
||||
READWRITE(nServices);
|
||||
READWRITE(FLATDATA(pchReserved)); // for IPv6
|
||||
READWRITE(ip);
|
||||
@@ -418,7 +416,7 @@ public:
|
||||
const char* GetCommand() const
|
||||
{
|
||||
if (!IsKnownType())
|
||||
throw std::out_of_range(strprintf("CInv::GetCommand() : type=% unknown type", type));
|
||||
throw std::out_of_range(strprintf("CInv::GetCommand() : type=%d unknown type", type));
|
||||
return ppszTypeName[type];
|
||||
}
|
||||
|
||||
@@ -735,13 +733,6 @@ public:
|
||||
AbortMessage();
|
||||
}
|
||||
|
||||
const char* GetMessageCommand() const
|
||||
{
|
||||
if (nHeaderStart == -1)
|
||||
return "";
|
||||
return &vSend[nHeaderStart] + offsetof(CMessageHeader, pchCommand);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
183
rpc.cpp
183
rpc.cpp
@@ -5,6 +5,12 @@
|
||||
#include "headers.h"
|
||||
#undef printf
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/iostreams/concepts.hpp>
|
||||
#include <boost/iostreams/stream.hpp>
|
||||
#ifdef USE_SSL
|
||||
#include <boost/asio/ssl.hpp>
|
||||
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
|
||||
#endif
|
||||
#include "json/json_spirit_reader_template.h"
|
||||
#include "json/json_spirit_writer_template.h"
|
||||
#include "json/json_spirit_utils.h"
|
||||
@@ -14,7 +20,7 @@
|
||||
// a certain size around 145MB. If we need access to json_spirit outside this
|
||||
// file, we could use the compiled json_spirit option.
|
||||
|
||||
using boost::asio::ip::tcp;
|
||||
using namespace boost::asio;
|
||||
using namespace json_spirit;
|
||||
|
||||
void ThreadRPCServer2(void* parg);
|
||||
@@ -255,6 +261,9 @@ Value getinfo(const Array& params, bool fHelp)
|
||||
obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
|
||||
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
|
||||
obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
|
||||
obj.push_back(Pair("testnet", fTestNet));
|
||||
obj.push_back(Pair("keypoololdest", (boost::int64_t)CWalletDB().GetOldestKeyPoolTime()));
|
||||
obj.push_back(Pair("paytxfee", (double)nTransactionFee / (double)COIN));
|
||||
obj.push_back(Pair("errors", GetWarnings("statusbar")));
|
||||
return obj;
|
||||
}
|
||||
@@ -275,7 +284,7 @@ Value getnewaddress(const Array& params, bool fHelp)
|
||||
strLabel = params[0].get_str();
|
||||
|
||||
// Generate a new key that is added to wallet
|
||||
string strAddress = PubKeyToAddress(GenerateNewKey());
|
||||
string strAddress = PubKeyToAddress(CWalletDB().GetKeyFromKeyPool());
|
||||
|
||||
SetAddressBookName(strAddress, strLabel);
|
||||
return strAddress;
|
||||
@@ -649,6 +658,28 @@ Value backupwallet(const Array& params, bool fHelp)
|
||||
}
|
||||
|
||||
|
||||
Value validateaddress(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error(
|
||||
"validateaddress <bitcoinaddress>\n"
|
||||
"Return information about <bitcoinaddress>.");
|
||||
|
||||
string strAddress = params[0].get_str();
|
||||
uint160 hash160;
|
||||
bool isValid = AddressToHash160(strAddress, hash160);
|
||||
|
||||
Object ret;
|
||||
ret.push_back(Pair("isvalid", isValid));
|
||||
if (isValid)
|
||||
{
|
||||
// Call Hash160ToAddress() so we always return current ADDRESSVERSION
|
||||
// version of the address:
|
||||
ret.push_back(Pair("address", Hash160ToAddress(hash160)));
|
||||
ret.push_back(Pair("ismine", (mapPubKeys.count(hash160) > 0)));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -689,6 +720,7 @@ pair<string, rpcfn_type> pCallTable[] =
|
||||
make_pair("listreceivedbyaddress", &listreceivedbyaddress),
|
||||
make_pair("listreceivedbylabel", &listreceivedbylabel),
|
||||
make_pair("backupwallet", &backupwallet),
|
||||
make_pair("validateaddress", &validateaddress),
|
||||
};
|
||||
map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
|
||||
|
||||
@@ -709,6 +741,7 @@ string pAllowInSafeMode[] =
|
||||
"getlabel",
|
||||
"getaddressesbylabel",
|
||||
"backupwallet",
|
||||
"validateaddress",
|
||||
};
|
||||
set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
|
||||
|
||||
@@ -738,12 +771,22 @@ string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeader
|
||||
return s.str();
|
||||
}
|
||||
|
||||
string rfc1123Time()
|
||||
{
|
||||
char buffer[32];
|
||||
time_t now;
|
||||
time(&now);
|
||||
struct tm* now_gmt = gmtime(&now);
|
||||
strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S %Z", now_gmt);
|
||||
return string(buffer);
|
||||
}
|
||||
|
||||
string HTTPReply(int nStatus, const string& strMsg)
|
||||
{
|
||||
if (nStatus == 401)
|
||||
return "HTTP/1.0 401 Authorization Required\r\n"
|
||||
"Server: HTTPd/1.0\r\n"
|
||||
"Date: Sat, 08 Jul 2006 12:04:08 GMT\r\n"
|
||||
return strprintf("HTTP/1.0 401 Authorization Required\r\n"
|
||||
"Date: %s\r\n"
|
||||
"Server: bitcoin-json-rpc\r\n"
|
||||
"WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
|
||||
"Content-Type: text/html\r\n"
|
||||
"Content-Length: 311\r\n"
|
||||
@@ -756,7 +799,7 @@ string HTTPReply(int nStatus, const string& strMsg)
|
||||
"<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
|
||||
"</HEAD>\r\n"
|
||||
"<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
|
||||
"</HTML>\r\n";
|
||||
"</HTML>\r\n", rfc1123Time().c_str());
|
||||
string strStatus;
|
||||
if (nStatus == 200) strStatus = "OK";
|
||||
else if (nStatus == 400) strStatus = "Bad Request";
|
||||
@@ -764,20 +807,21 @@ string HTTPReply(int nStatus, const string& strMsg)
|
||||
else if (nStatus == 500) strStatus = "Internal Server Error";
|
||||
return strprintf(
|
||||
"HTTP/1.1 %d %s\r\n"
|
||||
"Date: %s\r\n"
|
||||
"Connection: close\r\n"
|
||||
"Content-Length: %d\r\n"
|
||||
"Content-Type: application/json\r\n"
|
||||
"Date: Sat, 08 Jul 2006 12:04:08 GMT\r\n"
|
||||
"Server: json-rpc/1.0\r\n"
|
||||
"Server: bitcoin-json-rpc/1.0\r\n"
|
||||
"\r\n"
|
||||
"%s",
|
||||
nStatus,
|
||||
strStatus.c_str(),
|
||||
rfc1123Time().c_str(),
|
||||
strMsg.size(),
|
||||
strMsg.c_str());
|
||||
}
|
||||
|
||||
int ReadHTTPStatus(tcp::iostream& stream)
|
||||
int ReadHTTPStatus(std::basic_istream<char>& stream)
|
||||
{
|
||||
string str;
|
||||
getline(stream, str);
|
||||
@@ -788,7 +832,7 @@ int ReadHTTPStatus(tcp::iostream& stream)
|
||||
return atoi(vWords[1].c_str());
|
||||
}
|
||||
|
||||
int ReadHTTPHeader(tcp::iostream& stream, map<string, string>& mapHeadersRet)
|
||||
int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
|
||||
{
|
||||
int nLen = 0;
|
||||
loop
|
||||
@@ -812,7 +856,7 @@ int ReadHTTPHeader(tcp::iostream& stream, map<string, string>& mapHeadersRet)
|
||||
return nLen;
|
||||
}
|
||||
|
||||
int ReadHTTP(tcp::iostream& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
|
||||
int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
|
||||
{
|
||||
mapHeadersRet.clear();
|
||||
strMessageRet = "";
|
||||
@@ -930,8 +974,59 @@ bool ClientAllowed(const string& strAddress)
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef USE_SSL
|
||||
//
|
||||
// IOStream device that speaks SSL but can also speak non-SSL
|
||||
//
|
||||
class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
|
||||
public:
|
||||
SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
|
||||
{
|
||||
fUseSSL = fUseSSLIn;
|
||||
fNeedHandshake = fUseSSLIn;
|
||||
}
|
||||
|
||||
void handshake(ssl::stream_base::handshake_type role)
|
||||
{
|
||||
if (!fNeedHandshake) return;
|
||||
fNeedHandshake = false;
|
||||
stream.handshake(role);
|
||||
}
|
||||
std::streamsize read(char* s, std::streamsize n)
|
||||
{
|
||||
handshake(ssl::stream_base::server); // HTTPS servers read first
|
||||
if (fUseSSL) return stream.read_some(asio::buffer(s, n));
|
||||
return stream.next_layer().read_some(asio::buffer(s, n));
|
||||
}
|
||||
std::streamsize write(const char* s, std::streamsize n)
|
||||
{
|
||||
handshake(ssl::stream_base::client); // HTTPS clients write first
|
||||
if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
|
||||
return asio::write(stream.next_layer(), asio::buffer(s, n));
|
||||
}
|
||||
bool connect(const std::string& server, const std::string& port)
|
||||
{
|
||||
ip::tcp::resolver resolver(stream.get_io_service());
|
||||
ip::tcp::resolver::query query(server.c_str(), port.c_str());
|
||||
ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
|
||||
ip::tcp::resolver::iterator end;
|
||||
boost::system::error_code error = asio::error::host_not_found;
|
||||
while (error && endpoint_iterator != end)
|
||||
{
|
||||
stream.lowest_layer().close();
|
||||
stream.lowest_layer().connect(*endpoint_iterator++, error);
|
||||
}
|
||||
if (error)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool fNeedHandshake;
|
||||
bool fUseSSL;
|
||||
SSLStream& stream;
|
||||
};
|
||||
#endif
|
||||
|
||||
void ThreadRPCServer(void* parg)
|
||||
{
|
||||
@@ -972,18 +1067,54 @@ void ThreadRPCServer2(void* parg)
|
||||
return;
|
||||
}
|
||||
|
||||
// Bind to loopback 127.0.0.1 so the socket can only be accessed locally
|
||||
boost::asio::io_service io_service;
|
||||
tcp::endpoint endpoint(mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback(), 8332);
|
||||
tcp::acceptor acceptor(io_service, endpoint);
|
||||
bool fUseSSL = (mapArgs.count("-rpcssl") > 0);
|
||||
asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
|
||||
|
||||
asio::io_service io_service;
|
||||
ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
|
||||
ip::tcp::acceptor acceptor(io_service, endpoint);
|
||||
|
||||
#ifdef USE_SSL
|
||||
ssl::context context(io_service, ssl::context::sslv23);
|
||||
if (fUseSSL)
|
||||
{
|
||||
context.set_options(ssl::context::no_sslv2);
|
||||
filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
|
||||
if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
|
||||
if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
|
||||
else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
|
||||
filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
|
||||
if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
|
||||
if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
|
||||
else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
|
||||
|
||||
string ciphers = GetArg("-rpcsslciphers",
|
||||
"TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
|
||||
SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
|
||||
}
|
||||
#else
|
||||
if (fUseSSL)
|
||||
throw runtime_error("-rpcssl=true, but bitcoin compiled without full openssl libraries.");
|
||||
#endif
|
||||
|
||||
loop
|
||||
{
|
||||
// Accept connection
|
||||
tcp::iostream stream;
|
||||
tcp::endpoint peer;
|
||||
#ifdef USE_SSL
|
||||
SSLStream sslStream(io_service, context);
|
||||
SSLIOStreamDevice d(sslStream, fUseSSL);
|
||||
iostreams::stream<SSLIOStreamDevice> stream(d);
|
||||
#else
|
||||
ip::tcp::iostream stream;
|
||||
#endif
|
||||
|
||||
ip::tcp::endpoint peer;
|
||||
vnThreadsRunning[4]--;
|
||||
#ifdef USE_SSL
|
||||
acceptor.accept(sslStream.lowest_layer(), peer);
|
||||
#else
|
||||
acceptor.accept(*stream.rdbuf(), peer);
|
||||
#endif
|
||||
vnThreadsRunning[4]++;
|
||||
if (fShutdown)
|
||||
return;
|
||||
@@ -1102,9 +1233,25 @@ Object CallRPC(const string& strMethod, const Array& params)
|
||||
GetConfigFile().c_str()));
|
||||
|
||||
// Connect to localhost
|
||||
tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), "8332");
|
||||
bool fUseSSL = (mapArgs.count("-rpcssl") > 0);
|
||||
#ifdef USE_SSL
|
||||
asio::io_service io_service;
|
||||
ssl::context context(io_service, ssl::context::sslv23);
|
||||
context.set_options(ssl::context::no_sslv2);
|
||||
SSLStream sslStream(io_service, context);
|
||||
SSLIOStreamDevice d(sslStream, fUseSSL);
|
||||
iostreams::stream<SSLIOStreamDevice> stream(d);
|
||||
if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
|
||||
throw runtime_error("couldn't connect to server");
|
||||
#else
|
||||
if (fUseSSL)
|
||||
throw runtime_error("-rpcssl=true, but bitcoin compiled without full openssl libraries.");
|
||||
|
||||
ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
|
||||
if (stream.fail())
|
||||
throw runtime_error("couldn't connect to server");
|
||||
#endif
|
||||
|
||||
|
||||
// HTTP basic authentication
|
||||
string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
|
||||
|
||||
13
script.cpp
13
script.cpp
@@ -776,16 +776,11 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
|
||||
return false;
|
||||
|
||||
int nKeysCount = CastToBigNum(stacktop(-i)).getint();
|
||||
if (nKeysCount < 0)
|
||||
if (nKeysCount < 0 || nKeysCount > 20)
|
||||
return false;
|
||||
nOpCount += nKeysCount;
|
||||
if (nOpCount > 201)
|
||||
return false;
|
||||
if (nBestHeight > 84000)
|
||||
{
|
||||
if (nKeysCount > 20)
|
||||
return false;
|
||||
nOpCount += nKeysCount;
|
||||
if (nOpCount > 201)
|
||||
return false;
|
||||
}
|
||||
int ikey = ++i;
|
||||
i += nKeysCount;
|
||||
if (stack.size() < i)
|
||||
|
||||
16
serialize.h
16
serialize.h
@@ -22,7 +22,7 @@ class CDataStream;
|
||||
class CAutoFile;
|
||||
static const unsigned int MAX_SIZE = 0x02000000;
|
||||
|
||||
static const int VERSION = 31300;
|
||||
static const int VERSION = 31500;
|
||||
static const char* pszSubVer = "";
|
||||
|
||||
|
||||
@@ -725,39 +725,39 @@ public:
|
||||
typedef vector_type::const_iterator const_iterator;
|
||||
typedef vector_type::reverse_iterator reverse_iterator;
|
||||
|
||||
explicit CDataStream(int nTypeIn=0, int nVersionIn=VERSION)
|
||||
explicit CDataStream(int nTypeIn=SER_NETWORK, int nVersionIn=VERSION)
|
||||
{
|
||||
Init(nTypeIn, nVersionIn);
|
||||
}
|
||||
|
||||
CDataStream(const_iterator pbegin, const_iterator pend, int nTypeIn=0, int nVersionIn=VERSION) : vch(pbegin, pend)
|
||||
CDataStream(const_iterator pbegin, const_iterator pend, int nTypeIn=SER_NETWORK, 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)
|
||||
CDataStream(const char* pbegin, const char* pend, int nTypeIn=SER_NETWORK, 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())
|
||||
CDataStream(const vector_type& vchIn, int nTypeIn=SER_NETWORK, 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())
|
||||
CDataStream(const vector<char>& vchIn, int nTypeIn=SER_NETWORK, 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])
|
||||
CDataStream(const vector<unsigned char>& vchIn, int nTypeIn=SER_NETWORK, int nVersionIn=VERSION) : vch((char*)&vchIn.begin()[0], (char*)&vchIn.end()[0])
|
||||
{
|
||||
Init(nTypeIn, nVersionIn);
|
||||
}
|
||||
|
||||
void Init(int nTypeIn=0, int nVersionIn=VERSION)
|
||||
void Init(int nTypeIn=SER_NETWORK, int nVersionIn=VERSION)
|
||||
{
|
||||
nReadPos = 0;
|
||||
nType = nTypeIn;
|
||||
|
||||
@@ -7,7 +7,7 @@ RequestExecutionLevel highest
|
||||
|
||||
# General Symbol Definitions
|
||||
!define REGKEY "SOFTWARE\$(^Name)"
|
||||
!define VERSION 0.3.13
|
||||
!define VERSION 0.3.15
|
||||
!define COMPANY "Bitcoin project"
|
||||
!define URL http://www.bitcoin.org/
|
||||
|
||||
@@ -42,12 +42,12 @@ Var StartMenuGroup
|
||||
!insertmacro MUI_LANGUAGE English
|
||||
|
||||
# Installer attributes
|
||||
OutFile bitcoin-0.3.13-win32-setup.exe
|
||||
OutFile bitcoin-0.3.15-win32-setup.exe
|
||||
InstallDir $PROGRAMFILES\Bitcoin
|
||||
CRCCheck on
|
||||
XPStyle on
|
||||
ShowInstDetails show
|
||||
VIProductVersion 0.3.13.0
|
||||
VIProductVersion 0.3.15.0
|
||||
VIAddVersionKey ProductName Bitcoin
|
||||
VIAddVersionKey ProductVersion "${VERSION}"
|
||||
VIAddVersionKey CompanyName "${COMPANY}"
|
||||
|
||||
166
ui.cpp
166
ui.cpp
@@ -196,7 +196,7 @@ int ThreadSafeMessageBox(const string& message, const string& caption, int style
|
||||
|
||||
bool ThreadSafeAskFee(int64 nFeeRequired, const string& strCaption, wxWindow* parent)
|
||||
{
|
||||
if (nFeeRequired < CENT || fDaemon)
|
||||
if (nFeeRequired < CENT || nFeeRequired <= nTransactionFee || fDaemon)
|
||||
return true;
|
||||
string strMessage = strprintf(
|
||||
_("This transaction is over the size limit. You can still send it for a fee of %s, "
|
||||
@@ -502,10 +502,9 @@ bool CMainFrame::DeleteLine(uint256 hashKey)
|
||||
return nIndex != -1;
|
||||
}
|
||||
|
||||
string FormatTxStatus(const CWalletTx& wtx, bool& fConfirmed)
|
||||
string FormatTxStatus(const CWalletTx& wtx)
|
||||
{
|
||||
// Status
|
||||
fConfirmed = false;
|
||||
if (!wtx.IsFinal())
|
||||
{
|
||||
if (wtx.nLockTime < 500000000)
|
||||
@@ -516,8 +515,6 @@ string FormatTxStatus(const CWalletTx& wtx, bool& fConfirmed)
|
||||
else
|
||||
{
|
||||
int nDepth = wtx.GetDepthInMainChain();
|
||||
if (nDepth >= 1 || wtx.GetDebit() > 0)
|
||||
fConfirmed = true;
|
||||
if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
|
||||
return strprintf(_("%d/offline?"), nDepth);
|
||||
else if (nDepth < 6)
|
||||
@@ -527,12 +524,6 @@ string FormatTxStatus(const CWalletTx& wtx, bool& fConfirmed)
|
||||
}
|
||||
}
|
||||
|
||||
string FormatTxStatus(const CWalletTx& wtx)
|
||||
{
|
||||
bool fConfirmed;
|
||||
return FormatTxStatus(wtx, fConfirmed);
|
||||
}
|
||||
|
||||
string SingleLine(const string& strIn)
|
||||
{
|
||||
string strOut;
|
||||
@@ -561,9 +552,8 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
|
||||
int64 nDebit = wtx.GetDebit();
|
||||
int64 nNet = nCredit - nDebit;
|
||||
uint256 hash = wtx.GetHash();
|
||||
bool fConfirmed;
|
||||
string strStatus = FormatTxStatus(wtx, fConfirmed);
|
||||
wtx.fConfirmedDisplayed = fConfirmed;
|
||||
string strStatus = FormatTxStatus(wtx);
|
||||
bool fConfirmed = wtx.fConfirmedDisplayed = wtx.IsConfirmed();
|
||||
wxColour colour = (fConfirmed ? wxColour(0,0,0) : wxColour(128,128,128));
|
||||
map<string, string> mapValue = wtx.mapValue;
|
||||
wtx.nLinesDisplayed = 1;
|
||||
@@ -773,6 +763,7 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
|
||||
SingleLine(strDescription),
|
||||
FormatMoney(-nValue, true),
|
||||
"");
|
||||
nIndex = -1;
|
||||
wtx.nLinesDisplayed++;
|
||||
}
|
||||
}
|
||||
@@ -914,16 +905,16 @@ void CMainFrame::RefreshStatusColumn()
|
||||
continue;
|
||||
}
|
||||
CWalletTx& wtx = (*mi).second;
|
||||
bool fConfirmed;
|
||||
string strStatus = FormatTxStatus(wtx, fConfirmed);
|
||||
if (wtx.IsCoinBase() || wtx.GetTxTime() != wtx.nTimeDisplayed || fConfirmed != wtx.fConfirmedDisplayed)
|
||||
if (wtx.IsCoinBase() ||
|
||||
wtx.GetTxTime() != wtx.nTimeDisplayed ||
|
||||
wtx.IsConfirmed() != wtx.fConfirmedDisplayed)
|
||||
{
|
||||
if (!InsertTransaction(wtx, false, nIndex))
|
||||
m_listCtrl->DeleteItem(nIndex--);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_listCtrl->SetItem(nIndex, 2, strStatus);
|
||||
m_listCtrl->SetItem(nIndex, 2, FormatTxStatus(wtx));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1180,7 +1171,7 @@ void CMainFrame::OnButtonNew(wxCommandEvent& event)
|
||||
string strName = dialog.GetValue();
|
||||
|
||||
// Generate new key
|
||||
string strAddress = PubKeyToAddress(GenerateNewKey());
|
||||
string strAddress = PubKeyToAddress(CWalletDB().GetKeyFromKeyPool());
|
||||
|
||||
// Save
|
||||
SetAddressBookName(strAddress, strName);
|
||||
@@ -1435,7 +1426,10 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
|
||||
if (txout.IsMine())
|
||||
strHTML += "<b>Credit:</b> " + FormatMoney(txout.GetCredit()) + "<br>";
|
||||
|
||||
strHTML += "<b>Inputs:</b><br>";
|
||||
strHTML += "<br><b>Transaction:</b><br>";
|
||||
strHTML += HtmlEscape(wtx.ToString(), true);
|
||||
|
||||
strHTML += "<br><b>Inputs:</b><br>";
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
{
|
||||
foreach(const CTxIn& txin, wtx.vin)
|
||||
@@ -1454,9 +1448,6 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
strHTML += "<br><hr><br><b>Transaction:</b><br>";
|
||||
strHTML += HtmlEscape(wtx.ToString(), true);
|
||||
}
|
||||
|
||||
|
||||
@@ -1938,69 +1929,78 @@ void CSendDialog::OnButtonPaste(wxCommandEvent& event)
|
||||
|
||||
void CSendDialog::OnButtonSend(wxCommandEvent& event)
|
||||
{
|
||||
CWalletTx wtx;
|
||||
string strAddress = (string)m_textCtrlAddress->GetValue();
|
||||
static CCriticalSection cs_sendlock;
|
||||
TRY_CRITICAL_BLOCK(cs_sendlock)
|
||||
{
|
||||
CWalletTx wtx;
|
||||
string strAddress = (string)m_textCtrlAddress->GetValue();
|
||||
|
||||
// Parse amount
|
||||
int64 nValue = 0;
|
||||
if (!ParseMoney(m_textCtrlAmount->GetValue(), nValue) || nValue <= 0)
|
||||
{
|
||||
wxMessageBox(_("Error in amount "), _("Send Coins"));
|
||||
return;
|
||||
}
|
||||
if (nValue > GetBalance())
|
||||
{
|
||||
wxMessageBox(_("Amount exceeds your balance "), _("Send Coins"));
|
||||
return;
|
||||
}
|
||||
if (nValue + nTransactionFee > GetBalance())
|
||||
{
|
||||
wxMessageBox(string(_("Total exceeds your balance when the ")) + FormatMoney(nTransactionFee) + _(" transaction fee is included "), _("Send Coins"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse bitcoin address
|
||||
uint160 hash160;
|
||||
bool fBitcoinAddress = AddressToHash160(strAddress, hash160);
|
||||
|
||||
if (fBitcoinAddress)
|
||||
{
|
||||
// Send to bitcoin address
|
||||
CScript scriptPubKey;
|
||||
scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG;
|
||||
|
||||
string strError = SendMoney(scriptPubKey, nValue, wtx, true);
|
||||
if (strError == "")
|
||||
wxMessageBox(_("Payment sent "), _("Sending..."));
|
||||
else if (strError != "ABORTED")
|
||||
wxMessageBox(strError + " ", _("Sending..."));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Parse IP address
|
||||
CAddress addr(strAddress);
|
||||
if (!addr.IsValid())
|
||||
// Parse amount
|
||||
int64 nValue = 0;
|
||||
if (!ParseMoney(m_textCtrlAmount->GetValue(), nValue) || nValue <= 0)
|
||||
{
|
||||
wxMessageBox(_("Invalid address "), _("Send Coins"));
|
||||
wxMessageBox(_("Error in amount "), _("Send Coins"));
|
||||
return;
|
||||
}
|
||||
if (nValue > GetBalance())
|
||||
{
|
||||
wxMessageBox(_("Amount exceeds your balance "), _("Send Coins"));
|
||||
return;
|
||||
}
|
||||
if (nValue + nTransactionFee > GetBalance())
|
||||
{
|
||||
wxMessageBox(string(_("Total exceeds your balance when the ")) + FormatMoney(nTransactionFee) + _(" transaction fee is included "), _("Send Coins"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Message
|
||||
wtx.mapValue["to"] = strAddress;
|
||||
wtx.mapValue["from"] = m_textCtrlFrom->GetValue();
|
||||
wtx.mapValue["message"] = m_textCtrlMessage->GetValue();
|
||||
// Parse bitcoin address
|
||||
uint160 hash160;
|
||||
bool fBitcoinAddress = AddressToHash160(strAddress, hash160);
|
||||
|
||||
// Send to IP address
|
||||
CSendingDialog* pdialog = new CSendingDialog(this, addr, nValue, wtx);
|
||||
if (!pdialog->ShowModal())
|
||||
return;
|
||||
if (fBitcoinAddress)
|
||||
{
|
||||
// Send to bitcoin address
|
||||
CScript scriptPubKey;
|
||||
scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG;
|
||||
|
||||
string strError = SendMoney(scriptPubKey, nValue, wtx, true);
|
||||
if (strError == "")
|
||||
wxMessageBox(_("Payment sent "), _("Sending..."));
|
||||
else if (strError == "ABORTED")
|
||||
return; // leave send dialog open
|
||||
else
|
||||
{
|
||||
wxMessageBox(strError + " ", _("Sending..."));
|
||||
EndModal(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Parse IP address
|
||||
CAddress addr(strAddress);
|
||||
if (!addr.IsValid())
|
||||
{
|
||||
wxMessageBox(_("Invalid address "), _("Send Coins"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Message
|
||||
wtx.mapValue["to"] = strAddress;
|
||||
wtx.mapValue["from"] = m_textCtrlFrom->GetValue();
|
||||
wtx.mapValue["message"] = m_textCtrlMessage->GetValue();
|
||||
|
||||
// Send to IP address
|
||||
CSendingDialog* pdialog = new CSendingDialog(this, addr, nValue, wtx);
|
||||
if (!pdialog->ShowModal())
|
||||
return;
|
||||
}
|
||||
|
||||
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||
if (!mapAddressBook.count(strAddress))
|
||||
SetAddressBookName(strAddress, "");
|
||||
|
||||
EndModal(true);
|
||||
}
|
||||
|
||||
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||
if (!mapAddressBook.count(strAddress))
|
||||
SetAddressBookName(strAddress, "");
|
||||
|
||||
EndModal(true);
|
||||
}
|
||||
|
||||
void CSendDialog::OnButtonCancel(wxCommandEvent& event)
|
||||
@@ -2255,9 +2255,9 @@ void CSendingDialog::OnReply2(CDataStream& vRecv)
|
||||
Error(_("Insufficient funds"));
|
||||
return;
|
||||
}
|
||||
CKey key;
|
||||
CReserveKey reservekey;
|
||||
int64 nFeeRequired;
|
||||
if (!CreateTransaction(scriptPubKey, nPrice, wtx, key, nFeeRequired))
|
||||
if (!CreateTransaction(scriptPubKey, nPrice, wtx, reservekey, nFeeRequired))
|
||||
{
|
||||
if (nPrice + nFeeRequired > GetBalance())
|
||||
Error(strprintf(_("This is an oversized transaction that requires a transaction fee of %s"), FormatMoney(nFeeRequired).c_str()));
|
||||
@@ -2297,7 +2297,7 @@ void CSendingDialog::OnReply2(CDataStream& vRecv)
|
||||
return;
|
||||
|
||||
// Commit
|
||||
if (!CommitTransaction(wtx, key))
|
||||
if (!CommitTransaction(wtx, reservekey))
|
||||
{
|
||||
Error(_("The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."));
|
||||
return;
|
||||
@@ -2575,7 +2575,7 @@ void CAddressBookDialog::OnButtonNew(wxCommandEvent& event)
|
||||
strName = dialog.GetValue();
|
||||
|
||||
// Generate new key
|
||||
strAddress = PubKeyToAddress(GenerateNewKey());
|
||||
strAddress = PubKeyToAddress(CWalletDB().GetKeyFromKeyPool());
|
||||
}
|
||||
|
||||
// Add to list and select it
|
||||
|
||||
31
util.cpp
31
util.cpp
@@ -16,6 +16,7 @@ bool fShutdown = false;
|
||||
bool fDaemon = false;
|
||||
bool fCommandLine = false;
|
||||
string strMiscWarning;
|
||||
bool fTestNet = false;
|
||||
|
||||
|
||||
|
||||
@@ -572,7 +573,7 @@ void PrintExceptionContinue(std::exception* pex, const char* pszThread)
|
||||
strMiscWarning = pszMessage;
|
||||
#ifdef GUI
|
||||
if (wxTheApp && !fDaemon)
|
||||
boost::thread(bind(ThreadOneMessageBox, string(pszMessage)));
|
||||
boost::thread(boost::bind(ThreadOneMessageBox, string(pszMessage)));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -649,15 +650,11 @@ string GetDefaultDataDir()
|
||||
void GetDataDir(char* pszDir)
|
||||
{
|
||||
// pszDir must be at least MAX_PATH length.
|
||||
int nVariation;
|
||||
if (pszSetDataDir[0] != 0)
|
||||
{
|
||||
strlcpy(pszDir, pszSetDataDir, MAX_PATH);
|
||||
static bool fMkdirDone;
|
||||
if (!fMkdirDone)
|
||||
{
|
||||
fMkdirDone = true;
|
||||
filesystem::create_directory(pszDir);
|
||||
}
|
||||
nVariation = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -665,11 +662,23 @@ void GetDataDir(char* pszDir)
|
||||
// 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));
|
||||
filesystem::create_directory(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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -807,7 +816,7 @@ void AddTimeData(unsigned int ip, int64 nTime)
|
||||
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(bind(ThreadSafeMessageBox, strMessage+" ", string("Bitcoin"), wxOK | wxICON_EXCLAMATION, (wxWindow*)NULL, -1, -1));
|
||||
boost::thread(boost::bind(ThreadSafeMessageBox, strMessage+" ", string("Bitcoin"), wxOK | wxICON_EXCLAMATION, (wxWindow*)NULL, -1, -1));
|
||||
}
|
||||
}
|
||||
foreach(int64 n, vTimeOffsets)
|
||||
|
||||
25
util.h
25
util.h
@@ -145,6 +145,7 @@ extern bool fShutdown;
|
||||
extern bool fDaemon;
|
||||
extern bool fCommandLine;
|
||||
extern string strMiscWarning;
|
||||
extern bool fTestNet;
|
||||
|
||||
void RandAddSeed();
|
||||
void RandAddSeedPerfmon();
|
||||
@@ -621,3 +622,27 @@ inline void ExitThread(unsigned int nExitCode)
|
||||
pthread_exit((void*)nExitCode);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
inline bool AffinityBugWorkaround(void(*pfn)(void*))
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
// Sometimes after a few hours affinity gets stuck on one processor
|
||||
DWORD dwProcessAffinityMask = -1;
|
||||
DWORD dwSystemAffinityMask = -1;
|
||||
GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinityMask, &dwSystemAffinityMask);
|
||||
DWORD dwPrev1 = SetThreadAffinityMask(GetCurrentThread(), dwProcessAffinityMask);
|
||||
DWORD dwPrev2 = SetThreadAffinityMask(GetCurrentThread(), dwProcessAffinityMask);
|
||||
if (dwPrev2 != dwProcessAffinityMask)
|
||||
{
|
||||
printf("AffinityBugWorkaround() : SetThreadAffinityMask=%d, ProcessAffinityMask=%d, restarting thread\n", dwPrev2, dwProcessAffinityMask);
|
||||
if (!CreateThread(pfn, NULL))
|
||||
printf("Error: CreateThread() failed\n");
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user