command line and JSON-RPC first draft, requires Boost 1.35 or higher for boost::asio,
added SetBitcoinAddress and GetBitcoinAddress methods on CScript, critsect interlocks around mapAddressBook, added some random delays in tx broadcast to improve privacy, now compiles with MSVC 8.0 git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@60 1a98c847-1fd6-4fd8-948a-caf3550aa51b
This commit is contained in:
parent
fa9dbd6b62
commit
98500d70a8
23 changed files with 1202 additions and 348 deletions
33
bignum.h
33
bignum.h
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2009 Satoshi Nakamoto
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
@ -309,6 +309,37 @@ public:
|
||||||
*this = 0 - *this;
|
*this = 0 - *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string ToString(int nBase=10) const
|
||||||
|
{
|
||||||
|
CAutoBN_CTX pctx;
|
||||||
|
CBigNum bnBase = nBase;
|
||||||
|
CBigNum bn0 = 0;
|
||||||
|
string str;
|
||||||
|
CBigNum bn = *this;
|
||||||
|
BN_set_negative(&bn, false);
|
||||||
|
CBigNum dv;
|
||||||
|
CBigNum rem;
|
||||||
|
if (BN_cmp(&bn, &bn0) == 0)
|
||||||
|
return "0";
|
||||||
|
while (BN_cmp(&bn, &bn0) > 0)
|
||||||
|
{
|
||||||
|
if (!BN_div(&dv, &rem, &bn, &bnBase, pctx))
|
||||||
|
throw bignum_error("CBigNum::ToString() : BN_div failed");
|
||||||
|
bn = dv;
|
||||||
|
unsigned int c = rem.getulong();
|
||||||
|
str += "0123456789abcdef"[c];
|
||||||
|
}
|
||||||
|
if (BN_is_negative(this))
|
||||||
|
str += "-";
|
||||||
|
reverse(str.begin(), str.end());
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetHex() const
|
||||||
|
{
|
||||||
|
return ToString(16);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int GetSerializeSize(int nType=0, int nVersion=VERSION) const
|
unsigned int GetSerializeSize(int nType=0, int nVersion=VERSION) const
|
||||||
{
|
{
|
||||||
return ::GetSerializeSize(getvch(), nType, nVersion);
|
return ::GetSerializeSize(getvch(), nType, nVersion);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
Bitcoin v0.2.0 BETA
|
Bitcoin v0.2.0 BETA
|
||||||
|
|
||||||
Copyright (c) 2009 Satoshi Nakamoto
|
Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
Distributed under the MIT/X11 software license, see the accompanying
|
Distributed under the MIT/X11 software license, see the accompanying
|
||||||
file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||||
This product includes software developed by the OpenSSL Project for use in
|
This product includes software developed by the OpenSSL Project for use in
|
||||||
|
@ -13,8 +13,16 @@ WINDOWS BUILD NOTES
|
||||||
|
|
||||||
Compilers Supported
|
Compilers Supported
|
||||||
-------------------
|
-------------------
|
||||||
MinGW GCC
|
MinGW GCC (recommended)
|
||||||
Microsoft Visual C++ 6.0 SP6
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
Dependencies
|
Dependencies
|
||||||
|
@ -22,8 +30,7 @@ Dependencies
|
||||||
Libraries you need to download separately and build:
|
Libraries you need to download separately and build:
|
||||||
|
|
||||||
default path download
|
default path download
|
||||||
wxWidgets \wxwidgets http://www.wxwidgets.org/downloads/
|
wxWidgets \wxwidgets prebuilt: http://wxpack.sourceforge.net
|
||||||
or prebuilt: http://wxpack.sourceforge.net
|
|
||||||
OpenSSL \openssl http://www.openssl.org/source/
|
OpenSSL \openssl http://www.openssl.org/source/
|
||||||
Berkeley DB \db http://www.oracle.com/technology/software/products/berkeley-db/index.html
|
Berkeley DB \db http://www.oracle.com/technology/software/products/berkeley-db/index.html
|
||||||
Boost \boost http://www.boost.org/users/download/
|
Boost \boost http://www.boost.org/users/download/
|
||||||
|
@ -89,3 +96,13 @@ Using MinGW and MSYS:
|
||||||
cd \db\build_unix
|
cd \db\build_unix
|
||||||
sh ../dist/configure --enable-mingw --enable-cxx
|
sh ../dist/configure --enable-mingw --enable-cxx
|
||||||
make
|
make
|
||||||
|
|
||||||
|
|
||||||
|
Boost
|
||||||
|
-----
|
||||||
|
download bjam.exe from
|
||||||
|
http://sourceforge.net/project/showfiles.php?group_id=7586&package_id=72941
|
||||||
|
cd \boost
|
||||||
|
bjam toolset=gcc --build-type=complete stage
|
||||||
|
or
|
||||||
|
bjam toolset=msvc --build-type=complete stage
|
||||||
|
|
10
db.h
10
db.h
|
@ -1,8 +1,7 @@
|
||||||
// Copyright (c) 2009 Satoshi Nakamoto
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include <db_cxx.h>
|
|
||||||
class CTransaction;
|
class CTransaction;
|
||||||
class CTxIndex;
|
class CTxIndex;
|
||||||
class CDiskBlockIndex;
|
class CDiskBlockIndex;
|
||||||
|
@ -14,6 +13,7 @@ class CAddress;
|
||||||
class CWalletTx;
|
class CWalletTx;
|
||||||
|
|
||||||
extern map<string, string> mapAddressBook;
|
extern map<string, string> mapAddressBook;
|
||||||
|
extern CCriticalSection cs_mapAddressBook;
|
||||||
extern bool fClient;
|
extern bool fClient;
|
||||||
|
|
||||||
|
|
||||||
|
@ -359,15 +359,17 @@ public:
|
||||||
|
|
||||||
bool WriteName(const string& strAddress, const string& strName)
|
bool WriteName(const string& strAddress, const string& strName)
|
||||||
{
|
{
|
||||||
|
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||||
|
mapAddressBook[strAddress] = strName;
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdated++;
|
||||||
mapAddressBook[strAddress] = strName;
|
|
||||||
return Write(make_pair(string("name"), strAddress), strName);
|
return Write(make_pair(string("name"), strAddress), strName);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EraseName(const string& strAddress)
|
bool EraseName(const string& strAddress)
|
||||||
{
|
{
|
||||||
|
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||||
|
mapAddressBook.erase(strAddress);
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdated++;
|
||||||
mapAddressBook.erase(strAddress);
|
|
||||||
return Erase(make_pair(string("name"), strAddress));
|
return Erase(make_pair(string("name"), strAddress));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
#include <openssl/ripemd.h>
|
#include <openssl/ripemd.h>
|
||||||
|
#include <db_cxx.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
@ -36,6 +37,7 @@
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -53,6 +55,8 @@
|
||||||
#include <boost/array.hpp>
|
#include <boost/array.hpp>
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include <boost/function.hpp>
|
#include <boost/function.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
@ -73,8 +77,6 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <ifaddrs.h>
|
#include <ifaddrs.h>
|
||||||
#include <boost/filesystem.hpp>
|
|
||||||
#include <boost/algorithm/string.hpp>
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef __BSD__
|
#ifdef __BSD__
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
@ -85,8 +87,6 @@
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "strlcpy.h"
|
#include "strlcpy.h"
|
||||||
#include "serialize.h"
|
#include "serialize.h"
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
|
@ -100,6 +100,7 @@ using namespace boost;
|
||||||
#include "irc.h"
|
#include "irc.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "market.h"
|
#include "market.h"
|
||||||
|
#include "rpc.h"
|
||||||
#include "uibase.h"
|
#include "uibase.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
|
|
||||||
|
|
2
irc.cpp
2
irc.cpp
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2009 Satoshi Nakamoto
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
|
6
irc.h
6
irc.h
|
@ -1,8 +1,8 @@
|
||||||
// Copyright (c) 2009 Satoshi Nakamoto
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
extern bool RecvLine(SOCKET hSocket, string& strLine);
|
bool RecvLine(SOCKET hSocket, string& strLine);
|
||||||
extern void ThreadIRCSeed(void* parg);
|
void ThreadIRCSeed(void* parg);
|
||||||
|
|
||||||
extern int nGotIRCAddresses;
|
extern int nGotIRCAddresses;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 2009 Satoshi Nakamoto
|
Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
151
main.cpp
151
main.cpp
|
@ -26,6 +26,7 @@ CBlockIndex* pindexGenesisBlock = NULL;
|
||||||
int nBestHeight = -1;
|
int nBestHeight = -1;
|
||||||
uint256 hashBestChain = 0;
|
uint256 hashBestChain = 0;
|
||||||
CBlockIndex* pindexBest = NULL;
|
CBlockIndex* pindexBest = NULL;
|
||||||
|
int64 nTimeBestReceived = 0;
|
||||||
|
|
||||||
map<uint256, CBlock*> mapOrphanBlocks;
|
map<uint256, CBlock*> mapOrphanBlocks;
|
||||||
multimap<uint256, CBlock*> mapOrphanBlocksByPrev;
|
multimap<uint256, CBlock*> mapOrphanBlocksByPrev;
|
||||||
|
@ -45,6 +46,9 @@ CKey keyUser;
|
||||||
map<uint256, int> mapRequestCount;
|
map<uint256, int> mapRequestCount;
|
||||||
CCriticalSection cs_mapRequestCount;
|
CCriticalSection cs_mapRequestCount;
|
||||||
|
|
||||||
|
map<string, string> mapAddressBook;
|
||||||
|
CCriticalSection cs_mapAddressBook;
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
int fGenerateBitcoins = false;
|
int fGenerateBitcoins = false;
|
||||||
int64 nTransactionFee = 0;
|
int64 nTransactionFee = 0;
|
||||||
|
@ -573,7 +577,7 @@ bool CTransaction::RemoveFromMemoryPool()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int CMerkleTx::GetDepthInMainChain() const
|
int CMerkleTx::GetDepthInMainChain(int& nHeightRet) const
|
||||||
{
|
{
|
||||||
if (hashBlock == 0 || nIndex == -1)
|
if (hashBlock == 0 || nIndex == -1)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -594,6 +598,7 @@ int CMerkleTx::GetDepthInMainChain() const
|
||||||
fMerkleVerified = true;
|
fMerkleVerified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nHeightRet = pindex->nHeight;
|
||||||
return pindexBest->nHeight - pindex->nHeight + 1;
|
return pindexBest->nHeight - pindex->nHeight + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -708,15 +713,20 @@ void CWalletTx::RelayWalletTransaction(CTxDB& txdb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RelayWalletTransactions()
|
void ResendWalletTransactions()
|
||||||
{
|
{
|
||||||
static int64 nLastTime;
|
// Do this infrequently and randomly to avoid giving away
|
||||||
if (GetTime() - nLastTime < 10 * 60)
|
// that these are our transactions.
|
||||||
|
static int64 nNextTime;
|
||||||
|
if (GetTime() < nNextTime)
|
||||||
|
return;
|
||||||
|
bool fFirst = (nNextTime == 0);
|
||||||
|
nNextTime = GetTime() + GetRand(120 * 60);
|
||||||
|
if (fFirst)
|
||||||
return;
|
return;
|
||||||
nLastTime = GetTime();
|
|
||||||
|
|
||||||
// Rebroadcast any of our txes that aren't in a block yet
|
// Rebroadcast any of our txes that aren't in a block yet
|
||||||
printf("RelayWalletTransactions()\n");
|
printf("ResendWalletTransactions()\n");
|
||||||
CTxDB txdb("r");
|
CTxDB txdb("r");
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
CRITICAL_BLOCK(cs_mapWallet)
|
||||||
{
|
{
|
||||||
|
@ -725,7 +735,10 @@ void RelayWalletTransactions()
|
||||||
foreach(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
|
foreach(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
|
||||||
{
|
{
|
||||||
CWalletTx& wtx = item.second;
|
CWalletTx& wtx = item.second;
|
||||||
mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
|
// Don't rebroadcast until it's had plenty of time that
|
||||||
|
// it should have gotten in already by now.
|
||||||
|
if (nTimeBestReceived - wtx.nTimeReceived > 60 * 60)
|
||||||
|
mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
|
||||||
}
|
}
|
||||||
foreach(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
|
foreach(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
|
||||||
{
|
{
|
||||||
|
@ -1219,10 +1232,11 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// New best link
|
// New best block
|
||||||
hashBestChain = hash;
|
hashBestChain = hash;
|
||||||
pindexBest = pindexNew;
|
pindexBest = pindexNew;
|
||||||
nBestHeight = pindexBest->nHeight;
|
nBestHeight = pindexBest->nHeight;
|
||||||
|
nTimeBestReceived = GetTime();
|
||||||
nTransactionsUpdated++;
|
nTransactionsUpdated++;
|
||||||
printf("AddToBlockIndex: new best=%s height=%d\n", hashBestChain.ToString().substr(0,16).c_str(), nBestHeight);
|
printf("AddToBlockIndex: new best=%s height=%d\n", hashBestChain.ToString().substr(0,16).c_str(), nBestHeight);
|
||||||
}
|
}
|
||||||
|
@ -1232,9 +1246,6 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
|
||||||
|
|
||||||
if (pindexNew == pindexBest)
|
if (pindexNew == pindexBest)
|
||||||
{
|
{
|
||||||
// Relay wallet transactions that haven't gotten in yet
|
|
||||||
RelayWalletTransactions();
|
|
||||||
|
|
||||||
// Notify UI to display prev block's coinbase if it was ours
|
// Notify UI to display prev block's coinbase if it was ours
|
||||||
static uint256 hashPrevBestCoinBase;
|
static uint256 hashPrevBestCoinBase;
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
CRITICAL_BLOCK(cs_mapWallet)
|
||||||
|
@ -2248,7 +2259,7 @@ bool SendMessages(CNode* pto)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Keep-alive ping
|
// Keep-alive ping
|
||||||
if (pto->nLastSend && GetTime() - pto->nLastSend > 12 * 60 && pto->vSend.empty())
|
if (pto->nLastSend && GetTime() - pto->nLastSend > 30 * 60 && pto->vSend.empty())
|
||||||
pto->PushMessage("ping");
|
pto->PushMessage("ping");
|
||||||
|
|
||||||
// Address refresh broadcast
|
// Address refresh broadcast
|
||||||
|
@ -2270,60 +2281,81 @@ bool SendMessages(CNode* pto)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delay tx inv messages to protect privacy,
|
||||||
|
// trickle them out to a few nodes at a time.
|
||||||
|
bool fSendTxInv = false;
|
||||||
|
if (GetTimeMillis() - pto->nLastSentTxInv > 1800 + GetRand(200))
|
||||||
|
{
|
||||||
|
pto->nLastSentTxInv = GetTimeMillis();
|
||||||
|
fSendTxInv = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resend wallet transactions that haven't gotten in a block yet
|
||||||
|
ResendWalletTransactions();
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Message: addr
|
// Message: addr
|
||||||
//
|
//
|
||||||
vector<CAddress> vAddrToSend;
|
vector<CAddress> vAddr;
|
||||||
vAddrToSend.reserve(pto->vAddrToSend.size());
|
vAddr.reserve(pto->vAddrToSend.size());
|
||||||
foreach(const CAddress& addr, pto->vAddrToSend)
|
foreach(const CAddress& addr, pto->vAddrToSend)
|
||||||
{
|
{
|
||||||
// returns true if wasn't already contained in the set
|
// returns true if wasn't already contained in the set
|
||||||
if (pto->setAddrKnown.insert(addr).second)
|
if (pto->setAddrKnown.insert(addr).second)
|
||||||
{
|
{
|
||||||
vAddrToSend.push_back(addr);
|
vAddr.push_back(addr);
|
||||||
if (vAddrToSend.size() >= 1000)
|
if (vAddr.size() >= 1000)
|
||||||
{
|
{
|
||||||
pto->PushMessage("addr", vAddrToSend);
|
pto->PushMessage("addr", vAddr);
|
||||||
vAddrToSend.clear();
|
vAddr.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pto->vAddrToSend.clear();
|
pto->vAddrToSend.clear();
|
||||||
if (!vAddrToSend.empty())
|
if (!vAddr.empty())
|
||||||
pto->PushMessage("addr", vAddrToSend);
|
pto->PushMessage("addr", vAddr);
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Message: inventory
|
// Message: inventory
|
||||||
//
|
//
|
||||||
vector<CInv> vInventoryToSend;
|
vector<CInv> vInv;
|
||||||
|
vector<CInv> vInvWait;
|
||||||
CRITICAL_BLOCK(pto->cs_inventory)
|
CRITICAL_BLOCK(pto->cs_inventory)
|
||||||
{
|
{
|
||||||
vInventoryToSend.reserve(pto->vInventoryToSend.size());
|
vInv.reserve(pto->vInventoryToSend.size());
|
||||||
|
vInvWait.reserve(pto->vInventoryToSend.size());
|
||||||
foreach(const CInv& inv, pto->vInventoryToSend)
|
foreach(const CInv& inv, pto->vInventoryToSend)
|
||||||
{
|
{
|
||||||
|
// delay txes
|
||||||
|
if (!fSendTxInv && inv.type == MSG_TX)
|
||||||
|
{
|
||||||
|
vInvWait.push_back(inv);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// returns true if wasn't already contained in the set
|
// returns true if wasn't already contained in the set
|
||||||
if (pto->setInventoryKnown.insert(inv).second)
|
if (pto->setInventoryKnown.insert(inv).second)
|
||||||
{
|
{
|
||||||
vInventoryToSend.push_back(inv);
|
vInv.push_back(inv);
|
||||||
if (vInventoryToSend.size() >= 1000)
|
if (vInv.size() >= 1000)
|
||||||
{
|
{
|
||||||
pto->PushMessage("inv", vInventoryToSend);
|
pto->PushMessage("inv", vInv);
|
||||||
vInventoryToSend.clear();
|
vInv.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pto->vInventoryToSend.clear();
|
pto->vInventoryToSend = vInvWait;
|
||||||
}
|
}
|
||||||
if (!vInventoryToSend.empty())
|
if (!vInv.empty())
|
||||||
pto->PushMessage("inv", vInventoryToSend);
|
pto->PushMessage("inv", vInv);
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Message: getdata
|
// Message: getdata
|
||||||
//
|
//
|
||||||
vector<CInv> vAskFor;
|
vector<CInv> vGetData;
|
||||||
int64 nNow = GetTime() * 1000000;
|
int64 nNow = GetTime() * 1000000;
|
||||||
CTxDB txdb("r");
|
CTxDB txdb("r");
|
||||||
while (!pto->mapAskFor.empty() && (*pto->mapAskFor.begin()).first <= nNow)
|
while (!pto->mapAskFor.empty() && (*pto->mapAskFor.begin()).first <= nNow)
|
||||||
|
@ -2332,17 +2364,17 @@ bool SendMessages(CNode* pto)
|
||||||
if (!AlreadyHave(txdb, inv))
|
if (!AlreadyHave(txdb, inv))
|
||||||
{
|
{
|
||||||
printf("sending getdata: %s\n", inv.ToString().c_str());
|
printf("sending getdata: %s\n", inv.ToString().c_str());
|
||||||
vAskFor.push_back(inv);
|
vGetData.push_back(inv);
|
||||||
if (vAskFor.size() >= 1000)
|
if (vGetData.size() >= 1000)
|
||||||
{
|
{
|
||||||
pto->PushMessage("getdata", vAskFor);
|
pto->PushMessage("getdata", vGetData);
|
||||||
vAskFor.clear();
|
vGetData.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pto->mapAskFor.erase(pto->mapAskFor.begin());
|
pto->mapAskFor.erase(pto->mapAskFor.begin());
|
||||||
}
|
}
|
||||||
if (!vAskFor.empty())
|
if (!vGetData.empty())
|
||||||
pto->PushMessage("getdata", vAskFor);
|
pto->PushMessage("getdata", vGetData);
|
||||||
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -2405,7 +2437,6 @@ void ThreadBitcoinMiner(void* parg)
|
||||||
vnThreadsRunning[3]--;
|
vnThreadsRunning[3]--;
|
||||||
PrintException(NULL, "ThreadBitcoinMiner()");
|
PrintException(NULL, "ThreadBitcoinMiner()");
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("ThreadBitcoinMiner exiting, %d threads remaining\n", vnThreadsRunning[3]);
|
printf("ThreadBitcoinMiner exiting, %d threads remaining\n", vnThreadsRunning[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2842,6 +2873,13 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CK
|
||||||
// Fill a vout back to self with any change
|
// Fill a vout back to self with any change
|
||||||
if (nValueIn > nTotalValue)
|
if (nValueIn > nTotalValue)
|
||||||
{
|
{
|
||||||
|
// Note: We use a new key here to keep it from being obvious which side is the change.
|
||||||
|
// The drawback is that by not reusing a previous key, the change may be lost if a
|
||||||
|
// backup is restored, if the backup doesn't have the new private key for the change.
|
||||||
|
// If we reused the old key, it would be possible to add code to look for and
|
||||||
|
// rediscover unknown transactions that were written with keys of ours to recover
|
||||||
|
// post-backup change.
|
||||||
|
|
||||||
// New private key
|
// New private key
|
||||||
if (keyRet.IsNull())
|
if (keyRet.IsNull())
|
||||||
keyRet.MakeNewKey();
|
keyRet.MakeNewKey();
|
||||||
|
@ -2899,7 +2937,7 @@ bool CommitTransactionSpent(const CWalletTx& wtxNew, const CKey& key)
|
||||||
//// update: This matters even less now that fSpent can get corrected
|
//// update: This matters even less now that fSpent can get corrected
|
||||||
//// when transactions are seen in VerifySignature. The remote chance of
|
//// when transactions are seen in VerifySignature. The remote chance of
|
||||||
//// unmarked fSpent will be handled by that. Don't need to make this
|
//// unmarked fSpent will be handled by that. Don't need to make this
|
||||||
//// transactional.
|
//// transactional. Pls delete this comment block later.
|
||||||
|
|
||||||
// This is only to keep the database open to defeat the auto-flush for the
|
// This is only to keep the database open to defeat the auto-flush for the
|
||||||
// duration of this scope. This is the only place where this optimization
|
// duration of this scope. This is the only place where this optimization
|
||||||
|
@ -2932,7 +2970,7 @@ bool CommitTransactionSpent(const CWalletTx& wtxNew, const CKey& key)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew)
|
string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew)
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_main)
|
CRITICAL_BLOCK(cs_main)
|
||||||
{
|
{
|
||||||
|
@ -2945,13 +2983,13 @@ bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew)
|
||||||
strError = strprintf("Error: This is an oversized transaction that requires a transaction fee of %s ", FormatMoney(nFeeRequired).c_str());
|
strError = strprintf("Error: This is an oversized transaction that requires a transaction fee of %s ", FormatMoney(nFeeRequired).c_str());
|
||||||
else
|
else
|
||||||
strError = "Error: Transaction creation failed ";
|
strError = "Error: Transaction creation failed ";
|
||||||
wxMessageBox(strError, "Sending...");
|
printf("SendMoney() : %s", strError.c_str());
|
||||||
return error("SendMoney() : %s", strError.c_str());
|
return strError;
|
||||||
}
|
}
|
||||||
if (!CommitTransactionSpent(wtxNew, key))
|
if (!CommitTransactionSpent(wtxNew, key))
|
||||||
{
|
{
|
||||||
wxMessageBox("Error finalizing transaction ", "Sending...");
|
printf("SendMoney() : Error finalizing transaction");
|
||||||
return error("SendMoney() : Error finalizing transaction");
|
return "Error finalizing transaction";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Track how many getdata requests our transaction gets
|
// Track how many getdata requests our transaction gets
|
||||||
|
@ -2964,11 +3002,32 @@ bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew)
|
||||||
if (!wtxNew.AcceptTransaction())
|
if (!wtxNew.AcceptTransaction())
|
||||||
{
|
{
|
||||||
// This must not fail. The transaction has already been signed and recorded.
|
// This must not fail. The transaction has already been signed and recorded.
|
||||||
wxMessageBox("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.", "Sending...");
|
printf("SendMoney() : Error: Transaction not valid");
|
||||||
return error("SendMoney() : Error: Transaction not valid");
|
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.";
|
||||||
}
|
}
|
||||||
wtxNew.RelayWalletTransaction();
|
wtxNew.RelayWalletTransaction();
|
||||||
}
|
}
|
||||||
MainFrameRepaint();
|
MainFrameRepaint();
|
||||||
return true;
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew)
|
||||||
|
{
|
||||||
|
// Check amount
|
||||||
|
if (nValue <= 0)
|
||||||
|
return "Invalid amount";
|
||||||
|
if (nValue + nTransactionFee > GetBalance())
|
||||||
|
return "You don't have enough money";
|
||||||
|
|
||||||
|
// Parse bitcoin address
|
||||||
|
uint160 hash160;
|
||||||
|
if (!AddressToHash160(strAddress, hash160))
|
||||||
|
return "Invalid bitcoin address";
|
||||||
|
|
||||||
|
// Send to bitcoin address
|
||||||
|
CScript scriptPubKey;
|
||||||
|
scriptPubKey.SetBitcoinAddress(hash160);
|
||||||
|
return SendMoney(scriptPubKey, nValue, wtxNew);
|
||||||
}
|
}
|
||||||
|
|
9
main.h
9
main.h
|
@ -36,6 +36,8 @@ extern CBlockIndex* pindexBest;
|
||||||
extern unsigned int nTransactionsUpdated;
|
extern unsigned int nTransactionsUpdated;
|
||||||
extern map<uint256, int> mapRequestCount;
|
extern map<uint256, int> mapRequestCount;
|
||||||
extern CCriticalSection cs_mapRequestCount;
|
extern CCriticalSection cs_mapRequestCount;
|
||||||
|
extern map<string, string> mapAddressBook;
|
||||||
|
extern CCriticalSection cs_mapAddressBook;
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
extern int fGenerateBitcoins;
|
extern int fGenerateBitcoins;
|
||||||
|
@ -58,7 +60,6 @@ vector<unsigned char> GenerateNewKey();
|
||||||
bool AddToWallet(const CWalletTx& wtxIn);
|
bool AddToWallet(const CWalletTx& wtxIn);
|
||||||
void WalletUpdateSpent(const COutPoint& prevout);
|
void WalletUpdateSpent(const COutPoint& prevout);
|
||||||
void ReacceptWalletTransactions();
|
void ReacceptWalletTransactions();
|
||||||
void RelayWalletTransactions();
|
|
||||||
bool LoadBlockIndex(bool fAllowNew=true);
|
bool LoadBlockIndex(bool fAllowNew=true);
|
||||||
void PrintBlockTree();
|
void PrintBlockTree();
|
||||||
bool ProcessMessages(CNode* pfrom);
|
bool ProcessMessages(CNode* pfrom);
|
||||||
|
@ -67,7 +68,8 @@ bool SendMessages(CNode* pto);
|
||||||
int64 GetBalance();
|
int64 GetBalance();
|
||||||
bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CKey& keyRet, int64& nFeeRequiredRet);
|
bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CKey& keyRet, int64& nFeeRequiredRet);
|
||||||
bool CommitTransactionSpent(const CWalletTx& wtxNew, const CKey& key);
|
bool CommitTransactionSpent(const CWalletTx& wtxNew, const CKey& key);
|
||||||
bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew);
|
string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew);
|
||||||
|
string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew);
|
||||||
void GenerateBitcoins(bool fGenerate);
|
void GenerateBitcoins(bool fGenerate);
|
||||||
void ThreadBitcoinMiner(void* parg);
|
void ThreadBitcoinMiner(void* parg);
|
||||||
void BitcoinMiner();
|
void BitcoinMiner();
|
||||||
|
@ -680,7 +682,8 @@ public:
|
||||||
|
|
||||||
|
|
||||||
int SetMerkleBranch(const CBlock* pblock=NULL);
|
int SetMerkleBranch(const CBlock* pblock=NULL);
|
||||||
int GetDepthInMainChain() const;
|
int GetDepthInMainChain(int& nHeightRet) const;
|
||||||
|
int GetDepthInMainChain() const { int nHeight; return GetDepthInMainChain(nHeight); }
|
||||||
bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
|
bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
|
||||||
int GetBlocksToMaturity() const;
|
int GetBlocksToMaturity() const;
|
||||||
bool AcceptTransaction(CTxDB& txdb, bool fCheckInputs=true);
|
bool AcceptTransaction(CTxDB& txdb, bool fCheckInputs=true);
|
||||||
|
|
25
makefile
25
makefile
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2009 Satoshi Nakamoto
|
# Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
# Distributed under the MIT/X11 software license, see the accompanying
|
# Distributed under the MIT/X11 software license, see the accompanying
|
||||||
# file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
# file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
@ -16,22 +16,23 @@ endif
|
||||||
|
|
||||||
|
|
||||||
INCLUDEPATHS=-I"/boost" -I"/db/build_unix" -I"/openssl/include" -I"/wxwidgets/lib/vc_lib/mswd" -I"/wxwidgets/include"
|
INCLUDEPATHS=-I"/boost" -I"/db/build_unix" -I"/openssl/include" -I"/wxwidgets/lib/vc_lib/mswd" -I"/wxwidgets/include"
|
||||||
LIBPATHS=-L"/db/build_unix" -L"/openssl/out" -L"/wxwidgets/lib/gcc_lib"
|
LIBPATHS=-L"/boost/stage/lib" -L"/db/build_unix" -L"/openssl/out" -L"/wxwidgets/lib/gcc_lib"
|
||||||
LIBS= \
|
LIBS= \
|
||||||
|
-l libboost_system-mgw34-mt-d -l libboost_filesystem-mgw34-mt-d \
|
||||||
-l db_cxx \
|
-l db_cxx \
|
||||||
-l eay32 \
|
-l eay32 \
|
||||||
-l wxmsw28$(D)_richtext -l wxmsw28$(D)_html -l wxmsw28$(D)_core -l wxmsw28$(D)_adv -l wxbase28$(D) -l wxtiff$(D) -l wxjpeg$(D) -l wxpng$(D) -l wxzlib$(D) -l wxregex$(D) -l wxexpat$(D) \
|
-l wxmsw28$(D)_richtext -l wxmsw28$(D)_html -l wxmsw28$(D)_core -l wxmsw28$(D)_adv -l wxbase28$(D) -l wxtiff$(D) -l wxjpeg$(D) -l wxpng$(D) -l wxzlib$(D) -l wxregex$(D) -l wxexpat$(D) \
|
||||||
-l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l shlwapi
|
-l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l shlwapi
|
||||||
WXDEFS=-DWIN32 -D__WXMSW__ -D_WINDOWS -DNOPCH
|
WXDEFS=-DWIN32 -D__WXMSW__ -D_WINDOWS -DNOPCH
|
||||||
CFLAGS=-mthreads -O0 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
|
CFLAGS=-mthreads -O0 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
|
||||||
HEADERS=headers.h util.h main.h serialize.h uint256.h key.h bignum.h script.h db.h base58.h
|
HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h script.h db.h net.h irc.h main.h market.h rpc.h uibase.h ui.h
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
all: bitcoin.exe
|
all: bitcoin.exe
|
||||||
|
|
||||||
|
|
||||||
headers.h.gch: headers.h $(HEADERS) net.h irc.h market.h uibase.h ui.h
|
headers.h.gch: headers.h $(HEADERS)
|
||||||
g++ -c $(CFLAGS) -o $@ $<
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
obj/util.o: util.cpp $(HEADERS)
|
obj/util.o: util.cpp $(HEADERS)
|
||||||
|
@ -40,19 +41,19 @@ obj/util.o: util.cpp $(HEADERS)
|
||||||
obj/script.o: script.cpp $(HEADERS)
|
obj/script.o: script.cpp $(HEADERS)
|
||||||
g++ -c $(CFLAGS) -o $@ $<
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
obj/db.o: db.cpp $(HEADERS) market.h
|
obj/db.o: db.cpp $(HEADERS)
|
||||||
g++ -c $(CFLAGS) -o $@ $<
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
obj/net.o: net.cpp $(HEADERS) net.h
|
obj/net.o: net.cpp $(HEADERS)
|
||||||
g++ -c $(CFLAGS) -o $@ $<
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
obj/main.o: main.cpp $(HEADERS) net.h market.h sha.h
|
obj/main.o: main.cpp $(HEADERS) sha.h
|
||||||
g++ -c $(CFLAGS) -o $@ $<
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
obj/market.o: market.cpp $(HEADERS) market.h
|
obj/market.o: market.cpp $(HEADERS)
|
||||||
g++ -c $(CFLAGS) -o $@ $<
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
obj/ui.o: ui.cpp $(HEADERS) net.h uibase.h ui.h market.h
|
obj/ui.o: ui.cpp $(HEADERS)
|
||||||
g++ -c $(CFLAGS) -o $@ $<
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
obj/uibase.o: uibase.cpp uibase.h
|
obj/uibase.o: uibase.cpp uibase.h
|
||||||
|
@ -64,13 +65,17 @@ obj/sha.o: sha.cpp sha.h
|
||||||
obj/irc.o: irc.cpp $(HEADERS)
|
obj/irc.o: irc.cpp $(HEADERS)
|
||||||
g++ -c $(CFLAGS) -o $@ $<
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
obj/rpc.o: rpc.cpp $(HEADERS)
|
||||||
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
obj/ui_res.o: ui.rc rc/bitcoin.ico rc/check.ico rc/send16.bmp rc/send16mask.bmp rc/send16masknoshadow.bmp rc/send20.bmp rc/send20mask.bmp rc/addressbook16.bmp rc/addressbook16mask.bmp rc/addressbook20.bmp rc/addressbook20mask.bmp
|
obj/ui_res.o: ui.rc rc/bitcoin.ico rc/check.ico rc/send16.bmp rc/send16mask.bmp rc/send16masknoshadow.bmp rc/send20.bmp rc/send20mask.bmp rc/addressbook16.bmp rc/addressbook16mask.bmp rc/addressbook20.bmp rc/addressbook20mask.bmp
|
||||||
windres $(WXDEFS) $(INCLUDEPATHS) -o $@ -i $<
|
windres $(WXDEFS) $(INCLUDEPATHS) -o $@ -i $<
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
OBJS=obj/util.o obj/script.o obj/db.o obj/net.o obj/main.o obj/market.o \
|
OBJS=obj/util.o obj/script.o obj/db.o obj/net.o obj/main.o obj/market.o \
|
||||||
obj/ui.o obj/uibase.o obj/sha.o obj/irc.o obj/ui_res.o
|
obj/ui.o obj/uibase.o obj/sha.o obj/irc.o obj/rpc.o \
|
||||||
|
obj/ui_res.o
|
||||||
|
|
||||||
bitcoin.exe: headers.h.gch $(OBJS)
|
bitcoin.exe: headers.h.gch $(OBJS)
|
||||||
-kill /f bitcoin.exe
|
-kill /f bitcoin.exe
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2009 Satoshi Nakamoto
|
# Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
# Distributed under the MIT/X11 software license, see the accompanying
|
# Distributed under the MIT/X11 software license, see the accompanying
|
||||||
# file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
# file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
@ -35,14 +35,14 @@ LIBS= \
|
||||||
|
|
||||||
WXDEFS=-D__WXGTK__ -DNOPCH
|
WXDEFS=-D__WXGTK__ -DNOPCH
|
||||||
CFLAGS=-O0 -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
|
CFLAGS=-O0 -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
|
||||||
HEADERS=headers.h util.h main.h serialize.h uint256.h key.h bignum.h script.h db.h base58.h
|
HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h script.h db.h net.h irc.h main.h market.h rpc.h uibase.h ui.h
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
all: bitcoin
|
all: bitcoin
|
||||||
|
|
||||||
|
|
||||||
headers.h.gch: headers.h $(HEADERS) net.h irc.h market.h uibase.h ui.h
|
headers.h.gch: headers.h $(HEADERS)
|
||||||
g++ -c $(CFLAGS) -o $@ $<
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
obj/util.o: util.cpp $(HEADERS)
|
obj/util.o: util.cpp $(HEADERS)
|
||||||
|
@ -51,19 +51,19 @@ obj/util.o: util.cpp $(HEADERS)
|
||||||
obj/script.o: script.cpp $(HEADERS)
|
obj/script.o: script.cpp $(HEADERS)
|
||||||
g++ -c $(CFLAGS) -o $@ $<
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
obj/db.o: db.cpp $(HEADERS) market.h
|
obj/db.o: db.cpp $(HEADERS)
|
||||||
g++ -c $(CFLAGS) -o $@ $<
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
obj/net.o: net.cpp $(HEADERS) net.h
|
obj/net.o: net.cpp $(HEADERS)
|
||||||
g++ -c $(CFLAGS) -o $@ $<
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
obj/main.o: main.cpp $(HEADERS) net.h market.h sha.h
|
obj/main.o: main.cpp $(HEADERS) sha.h
|
||||||
g++ -c $(CFLAGS) -o $@ $<
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
obj/market.o: market.cpp $(HEADERS) market.h
|
obj/market.o: market.cpp $(HEADERS)
|
||||||
g++ -c $(CFLAGS) -o $@ $<
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
obj/ui.o: ui.cpp $(HEADERS) net.h uibase.h ui.h market.h
|
obj/ui.o: ui.cpp $(HEADERS)
|
||||||
g++ -c $(CFLAGS) -o $@ $<
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
obj/uibase.o: uibase.cpp uibase.h
|
obj/uibase.o: uibase.cpp uibase.h
|
||||||
|
@ -75,11 +75,13 @@ obj/sha.o: sha.cpp sha.h
|
||||||
obj/irc.o: irc.cpp $(HEADERS)
|
obj/irc.o: irc.cpp $(HEADERS)
|
||||||
g++ -c $(CFLAGS) -o $@ $<
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
obj/rpc.o: rpc.cpp $(HEADERS)
|
||||||
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
OBJS=obj/util.o obj/script.o obj/db.o obj/net.o obj/main.o obj/market.o \
|
OBJS=obj/util.o obj/script.o obj/db.o obj/net.o obj/main.o obj/market.o \
|
||||||
obj/ui.o obj/uibase.o obj/sha.o obj/irc.o
|
obj/ui.o obj/uibase.o obj/sha.o obj/irc.o obj/rpc.o
|
||||||
|
|
||||||
bitcoin: headers.h.gch $(OBJS)
|
bitcoin: headers.h.gch $(OBJS)
|
||||||
g++ $(CFLAGS) -o $@ $(LIBPATHS) $(OBJS) $(LIBS)
|
g++ $(CFLAGS) -o $@ $(LIBPATHS) $(OBJS) $(LIBS)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2009 Satoshi Nakamoto
|
# Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
# Distributed under the MIT/X11 software license, see the accompanying
|
# Distributed under the MIT/X11 software license, see the accompanying
|
||||||
# file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
# file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
@ -35,14 +35,14 @@ LIBS= \
|
||||||
|
|
||||||
WXDEFS=-D__WXGTK__ -DNOPCH
|
WXDEFS=-D__WXGTK__ -DNOPCH
|
||||||
CFLAGS=-O0 -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
|
CFLAGS=-O0 -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
|
||||||
HEADERS=headers.h util.h main.h serialize.h uint256.h key.h bignum.h script.h db.h base58.h
|
HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h script.h db.h net.h irc.h main.h market.h rpc.h uibase.h ui.h
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
all: bitcoin
|
all: bitcoin
|
||||||
|
|
||||||
|
|
||||||
headers.h.gch: headers.h $(HEADERS) net.h irc.h market.h uibase.h ui.h
|
headers.h.gch: headers.h $(HEADERS)
|
||||||
g++ -c $(CFLAGS) -o $@ $<
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
obj/util.o: util.cpp $(HEADERS)
|
obj/util.o: util.cpp $(HEADERS)
|
||||||
|
@ -51,19 +51,19 @@ obj/util.o: util.cpp $(HEADERS)
|
||||||
obj/script.o: script.cpp $(HEADERS)
|
obj/script.o: script.cpp $(HEADERS)
|
||||||
g++ -c $(CFLAGS) -o $@ $<
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
obj/db.o: db.cpp $(HEADERS) market.h
|
obj/db.o: db.cpp $(HEADERS)
|
||||||
g++ -c $(CFLAGS) -o $@ $<
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
obj/net.o: net.cpp $(HEADERS) net.h
|
obj/net.o: net.cpp $(HEADERS)
|
||||||
g++ -c $(CFLAGS) -o $@ $<
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
obj/main.o: main.cpp $(HEADERS) net.h market.h sha.h
|
obj/main.o: main.cpp $(HEADERS) sha.h
|
||||||
g++ -c $(CFLAGS) -o $@ $<
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
obj/market.o: market.cpp $(HEADERS) market.h
|
obj/market.o: market.cpp $(HEADERS)
|
||||||
g++ -c $(CFLAGS) -o $@ $<
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
obj/ui.o: ui.cpp $(HEADERS) net.h uibase.h ui.h market.h
|
obj/ui.o: ui.cpp $(HEADERS)
|
||||||
g++ -c $(CFLAGS) -o $@ $<
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
obj/uibase.o: uibase.cpp uibase.h
|
obj/uibase.o: uibase.cpp uibase.h
|
||||||
|
@ -75,11 +75,13 @@ obj/sha.o: sha.cpp sha.h
|
||||||
obj/irc.o: irc.cpp $(HEADERS)
|
obj/irc.o: irc.cpp $(HEADERS)
|
||||||
g++ -c $(CFLAGS) -o $@ $<
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
obj/rpc.o: rpc.cpp $(HEADERS)
|
||||||
|
g++ -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
OBJS=obj/util.o obj/script.o obj/db.o obj/net.o obj/main.o obj/market.o \
|
OBJS=obj/util.o obj/script.o obj/db.o obj/net.o obj/main.o obj/market.o \
|
||||||
obj/ui.o obj/uibase.o obj/sha.o obj/irc.o
|
obj/ui.o obj/uibase.o obj/sha.o obj/irc.o obj/rpc.o
|
||||||
|
|
||||||
bitcoin: headers.h.gch $(OBJS)
|
bitcoin: headers.h.gch $(OBJS)
|
||||||
g++ $(CFLAGS) -o $@ $(LIBPATHS) $(OBJS) $(LIBS)
|
g++ $(CFLAGS) -o $@ $(LIBPATHS) $(OBJS) $(LIBS)
|
||||||
|
|
25
makefile.vc
25
makefile.vc
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2009 Satoshi Nakamoto
|
# Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
# Distributed under the MIT/X11 software license, see the accompanying
|
# Distributed under the MIT/X11 software license, see the accompanying
|
||||||
# file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
# file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
@ -14,15 +14,16 @@ DEBUGFLAGS=/Zi /Od /D__WXDEBUG__
|
||||||
|
|
||||||
|
|
||||||
INCLUDEPATHS=/I"/boost" /I"/db/build_windows" /I"/openssl/include" /I"/wxwidgets/lib/vc_lib/mswd" /I"/wxwidgets/include"
|
INCLUDEPATHS=/I"/boost" /I"/db/build_windows" /I"/openssl/include" /I"/wxwidgets/lib/vc_lib/mswd" /I"/wxwidgets/include"
|
||||||
LIBPATHS=/LIBPATH:"/db/build_windows/$(BUILD)" /LIBPATH:"/openssl/out" /LIBPATH:"/wxwidgets/lib/vc_lib"
|
LIBPATHS=/LIBPATH:"/boost/stage/lib" /LIBPATH:"/db/build_windows/$(BUILD)" /LIBPATH:"/openssl/out" /LIBPATH:"/wxwidgets/lib/vc_lib"
|
||||||
LIBS= \
|
LIBS= \
|
||||||
|
libboost_system-vc80-mt-gd.lib libboost_filesystem-vc80-mt-gd.lib \
|
||||||
libdb47s$(D).lib \
|
libdb47s$(D).lib \
|
||||||
libeay32.lib \
|
libeay32.lib \
|
||||||
wxmsw28$(D)_richtext.lib wxmsw28$(D)_html.lib wxmsw28$(D)_core.lib wxmsw28$(D)_adv.lib wxbase28$(D).lib wxtiff$(D).lib wxjpeg$(D).lib wxpng$(D).lib wxzlib$(D).lib wxregex$(D).lib wxexpat$(D).lib \
|
wxmsw28$(D)_richtext.lib wxmsw28$(D)_html.lib wxmsw28$(D)_core.lib wxmsw28$(D)_adv.lib wxbase28$(D).lib wxtiff$(D).lib wxjpeg$(D).lib wxpng$(D).lib wxzlib$(D).lib wxregex$(D).lib wxexpat$(D).lib \
|
||||||
kernel32.lib user32.lib gdi32.lib comdlg32.lib winspool.lib winmm.lib shell32.lib comctl32.lib ole32.lib oleaut32.lib uuid.lib rpcrt4.lib advapi32.lib ws2_32.lib shlwapi.lib
|
kernel32.lib user32.lib gdi32.lib comdlg32.lib winspool.lib winmm.lib shell32.lib comctl32.lib ole32.lib oleaut32.lib uuid.lib rpcrt4.lib advapi32.lib ws2_32.lib shlwapi.lib
|
||||||
WXDEFS=/DWIN32 /D__WXMSW__ /D_WINDOWS /DNOPCH
|
WXDEFS=/DWIN32 /D__WXMSW__ /D_WINDOWS /DNOPCH
|
||||||
CFLAGS=/c /nologo /Ob0 /MD$(D) /EHsc /GR /Zm300 /YX /Fpobj/headers.pch $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
|
CFLAGS=/c /nologo /Ob0 /MD$(D) /EHsc /GR /Zm300 /YX /Fpobj/headers.pch $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
|
||||||
HEADERS=headers.h util.h main.h serialize.h uint256.h key.h bignum.h script.h db.h base58.h
|
HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h script.h db.h net.h irc.h main.h market.h rpc.h uibase.h ui.h
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,37 +36,41 @@ obj\util.obj: util.cpp $(HEADERS)
|
||||||
obj\script.obj: script.cpp $(HEADERS)
|
obj\script.obj: script.cpp $(HEADERS)
|
||||||
cl $(CFLAGS) /Fo$@ %s
|
cl $(CFLAGS) /Fo$@ %s
|
||||||
|
|
||||||
obj\db.obj: db.cpp $(HEADERS) market.h
|
obj\db.obj: db.cpp $(HEADERS)
|
||||||
cl $(CFLAGS) /Fo$@ %s
|
cl $(CFLAGS) /Fo$@ %s
|
||||||
|
|
||||||
obj\net.obj: net.cpp $(HEADERS) net.h
|
obj\net.obj: net.cpp $(HEADERS)
|
||||||
cl $(CFLAGS) /Fo$@ %s
|
cl $(CFLAGS) /Fo$@ %s
|
||||||
|
|
||||||
obj\main.obj: main.cpp $(HEADERS) net.h market.h
|
obj\main.obj: main.cpp $(HEADERS) sha.h
|
||||||
cl $(CFLAGS) /Fo$@ %s
|
cl $(CFLAGS) /Fo$@ %s
|
||||||
|
|
||||||
obj\market.obj: market.cpp $(HEADERS) market.h
|
obj\market.obj: market.cpp $(HEADERS)
|
||||||
cl $(CFLAGS) /Fo$@ %s
|
cl $(CFLAGS) /Fo$@ %s
|
||||||
|
|
||||||
obj\ui.obj: ui.cpp $(HEADERS) net.h uibase.h ui.h market.h
|
obj\ui.obj: ui.cpp $(HEADERS)
|
||||||
cl $(CFLAGS) /Fo$@ %s
|
cl $(CFLAGS) /Fo$@ %s
|
||||||
|
|
||||||
obj\uibase.obj: uibase.cpp uibase.h
|
obj\uibase.obj: uibase.cpp uibase.h
|
||||||
cl $(CFLAGS) /Fo$@ %s
|
cl $(CFLAGS) /Fo$@ %s
|
||||||
|
|
||||||
obj\sha.obj: sha.cpp sha.h
|
obj\sha.obj: sha.cpp sha.h
|
||||||
cl $(CFLAGS) /O2 /Fo$@ %s
|
cl $(CFLAGS) /O2 /Fo$@ %s
|
||||||
|
|
||||||
obj\irc.obj: irc.cpp $(HEADERS)
|
obj\irc.obj: irc.cpp $(HEADERS)
|
||||||
cl $(CFLAGS) /Fo$@ %s
|
cl $(CFLAGS) /Fo$@ %s
|
||||||
|
|
||||||
|
obj\rpc.obj: rpc.cpp $(HEADERS)
|
||||||
|
cl $(CFLAGS) /Fo$@ %s
|
||||||
|
|
||||||
obj\ui.res: ui.rc rc/bitcoin.ico rc/check.ico rc/send16.bmp rc/send16mask.bmp rc/send16masknoshadow.bmp rc/send20.bmp rc/send20mask.bmp rc/addressbook16.bmp rc/addressbook16mask.bmp rc/addressbook20.bmp rc/addressbook20mask.bmp
|
obj\ui.res: ui.rc rc/bitcoin.ico rc/check.ico rc/send16.bmp rc/send16mask.bmp rc/send16masknoshadow.bmp rc/send20.bmp rc/send20mask.bmp rc/addressbook16.bmp rc/addressbook16mask.bmp rc/addressbook20.bmp rc/addressbook20mask.bmp
|
||||||
rc $(INCLUDEPATHS) $(WXDEFS) /Fo$@ %s
|
rc $(INCLUDEPATHS) $(WXDEFS) /Fo$@ %s
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
OBJS=obj\util.obj obj\script.obj obj\db.obj obj\net.obj obj\main.obj obj\market.obj \
|
OBJS=obj\util.obj obj\script.obj obj\db.obj obj\net.obj obj\main.obj obj\market.obj \
|
||||||
obj\ui.obj obj\uibase.obj obj\sha.obj obj\irc.obj obj\ui.res
|
obj\ui.obj obj\uibase.obj obj\sha.obj obj\irc.obj obj\rpc.obj \
|
||||||
|
obj\ui.res
|
||||||
|
|
||||||
bitcoin.exe: $(OBJS)
|
bitcoin.exe: $(OBJS)
|
||||||
-kill /f bitcoin.exe & sleep 1
|
-kill /f bitcoin.exe & sleep 1
|
||||||
|
|
15
net.cpp
15
net.cpp
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2009 Satoshi Nakamoto
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
@ -522,7 +522,6 @@ void CNode::Cleanup()
|
||||||
void ThreadSocketHandler(void* parg)
|
void ThreadSocketHandler(void* parg)
|
||||||
{
|
{
|
||||||
IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
|
IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
vnThreadsRunning[0]++;
|
vnThreadsRunning[0]++;
|
||||||
|
@ -536,7 +535,6 @@ void ThreadSocketHandler(void* parg)
|
||||||
vnThreadsRunning[0]--;
|
vnThreadsRunning[0]--;
|
||||||
throw; // support pthread_cancel()
|
throw; // support pthread_cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("ThreadSocketHandler exiting\n");
|
printf("ThreadSocketHandler exiting\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -816,7 +814,6 @@ void ThreadSocketHandler2(void* parg)
|
||||||
void ThreadOpenConnections(void* parg)
|
void ThreadOpenConnections(void* parg)
|
||||||
{
|
{
|
||||||
IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
|
IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
vnThreadsRunning[1]++;
|
vnThreadsRunning[1]++;
|
||||||
|
@ -830,7 +827,6 @@ void ThreadOpenConnections(void* parg)
|
||||||
vnThreadsRunning[1]--;
|
vnThreadsRunning[1]--;
|
||||||
PrintException(NULL, "ThreadOpenConnections()");
|
PrintException(NULL, "ThreadOpenConnections()");
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("ThreadOpenConnections exiting\n");
|
printf("ThreadOpenConnections exiting\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -928,7 +924,7 @@ void ThreadOpenConnections2(void* parg)
|
||||||
// 30 days 27 hours
|
// 30 days 27 hours
|
||||||
// 90 days 46 hours
|
// 90 days 46 hours
|
||||||
// 365 days 93 hours
|
// 365 days 93 hours
|
||||||
int64 nDelay = (int64)(3600.0 * sqrt(fabs(nSinceLastSeen) / 3600.0) + nRandomizer);
|
int64 nDelay = (int64)(3600.0 * sqrt(fabs((double)nSinceLastSeen) / 3600.0) + nRandomizer);
|
||||||
|
|
||||||
// Fast reconnect for one hour after last seen
|
// Fast reconnect for one hour after last seen
|
||||||
if (nSinceLastSeen < 60 * 60)
|
if (nSinceLastSeen < 60 * 60)
|
||||||
|
@ -1016,7 +1012,6 @@ bool OpenNetworkConnection(const CAddress& addrConnect)
|
||||||
void ThreadMessageHandler(void* parg)
|
void ThreadMessageHandler(void* parg)
|
||||||
{
|
{
|
||||||
IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
|
IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
vnThreadsRunning[2]++;
|
vnThreadsRunning[2]++;
|
||||||
|
@ -1030,7 +1025,6 @@ void ThreadMessageHandler(void* parg)
|
||||||
vnThreadsRunning[2]--;
|
vnThreadsRunning[2]--;
|
||||||
PrintException(NULL, "ThreadMessageHandler()");
|
PrintException(NULL, "ThreadMessageHandler()");
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("ThreadMessageHandler exiting\n");
|
printf("ThreadMessageHandler exiting\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1329,7 +1323,7 @@ bool StopNode()
|
||||||
fShutdown = true;
|
fShutdown = true;
|
||||||
nTransactionsUpdated++;
|
nTransactionsUpdated++;
|
||||||
int64 nStart = GetTime();
|
int64 nStart = GetTime();
|
||||||
while (vnThreadsRunning[0] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0)
|
while (vnThreadsRunning[0] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0)
|
||||||
{
|
{
|
||||||
if (GetTime() - nStart > 20)
|
if (GetTime() - nStart > 20)
|
||||||
break;
|
break;
|
||||||
|
@ -1339,7 +1333,8 @@ bool StopNode()
|
||||||
if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
|
if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
|
||||||
if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
|
if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
|
||||||
if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
|
if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
|
||||||
while (vnThreadsRunning[2] > 0)
|
if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n");
|
||||||
|
while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
|
||||||
Sleep(20);
|
Sleep(20);
|
||||||
Sleep(50);
|
Sleep(50);
|
||||||
|
|
||||||
|
|
3
net.h
3
net.h
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2009 Satoshi Nakamoto
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
@ -518,6 +518,7 @@ public:
|
||||||
vector<CInv> vInventoryToSend;
|
vector<CInv> vInventoryToSend;
|
||||||
CCriticalSection cs_inventory;
|
CCriticalSection cs_inventory;
|
||||||
multimap<int64, CInv> mapAskFor;
|
multimap<int64, CInv> mapAskFor;
|
||||||
|
int64 nLastSentTxInv;
|
||||||
|
|
||||||
// publish and subscription
|
// publish and subscription
|
||||||
vector<char> vfSubscribe;
|
vector<char> vfSubscribe;
|
||||||
|
|
641
rpc.cpp
Normal file
641
rpc.cpp
Normal file
|
@ -0,0 +1,641 @@
|
||||||
|
// Copyright (c) 2010 Satoshi Nakamoto
|
||||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
|
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include "headers.h"
|
||||||
|
#undef printf
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
#include "json/json_spirit_reader_template.h"
|
||||||
|
#include "json/json_spirit_writer_template.h"
|
||||||
|
#include "json/json_spirit_utils.h"
|
||||||
|
#define printf OutputDebugStringF
|
||||||
|
// MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
|
||||||
|
// precompiled in headers.h. The problem might be when the pch file goes over
|
||||||
|
// 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 json_spirit;
|
||||||
|
|
||||||
|
void ThreadRPCServer2(void* parg);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Note: I'm not finished designing this interface, it's still subject to change.
|
||||||
|
///
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Value stop(const Array& params)
|
||||||
|
{
|
||||||
|
if (params.size() != 0)
|
||||||
|
throw runtime_error(
|
||||||
|
"stop (no parameters)\n"
|
||||||
|
"Stop bitcoin server.");
|
||||||
|
|
||||||
|
// Shutdown will take long enough that the response should get back
|
||||||
|
CreateThread(Shutdown, NULL);
|
||||||
|
return "bitcoin server stopping";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Value getblockcount(const Array& params)
|
||||||
|
{
|
||||||
|
if (params.size() != 0)
|
||||||
|
throw runtime_error(
|
||||||
|
"getblockcount (no parameters)\n"
|
||||||
|
"Returns the number of blocks in the longest block chain.");
|
||||||
|
|
||||||
|
return nBestHeight + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Value getblocknumber(const Array& params)
|
||||||
|
{
|
||||||
|
if (params.size() != 0)
|
||||||
|
throw runtime_error(
|
||||||
|
"getblocknumber (no parameters)\n"
|
||||||
|
"Returns the block number of the latest block in the longest block chain.");
|
||||||
|
|
||||||
|
return nBestHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Value getdifficulty(const Array& params)
|
||||||
|
{
|
||||||
|
if (params.size() != 0)
|
||||||
|
throw runtime_error(
|
||||||
|
"getdifficulty (no parameters)\n"
|
||||||
|
"Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
|
||||||
|
|
||||||
|
if (pindexBest == NULL)
|
||||||
|
throw runtime_error("block chain not loaded");
|
||||||
|
|
||||||
|
// Floating point number that is a multiple of the minimum difficulty,
|
||||||
|
// minimum difficulty = 1.0.
|
||||||
|
int nShift = 256 - 32 - 31; // to fit in a uint
|
||||||
|
double dMinimum = (CBigNum().SetCompact(bnProofOfWorkLimit.GetCompact()) >> nShift).getuint();
|
||||||
|
double dCurrently = (CBigNum().SetCompact(pindexBest->nBits) >> nShift).getuint();
|
||||||
|
return dMinimum / dCurrently;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Value getnewaddress(const Array& params)
|
||||||
|
{
|
||||||
|
if (params.size() > 1)
|
||||||
|
throw runtime_error(
|
||||||
|
"getnewaddress [label]\n"
|
||||||
|
"Returns a new bitcoin address for receiving payments. "
|
||||||
|
"If [label] is specified (recommended), it is added to the address book "
|
||||||
|
"so payments received with the address will be labeled.");
|
||||||
|
|
||||||
|
// Parse the label first so we don't generate a key if there's an error
|
||||||
|
string strLabel;
|
||||||
|
if (params.size() > 0)
|
||||||
|
strLabel = params[0].get_str();
|
||||||
|
|
||||||
|
// Generate a new key that is added to wallet
|
||||||
|
string strAddress = PubKeyToAddress(GenerateNewKey());
|
||||||
|
|
||||||
|
if (params.size() > 0)
|
||||||
|
SetAddressBookName(strAddress, strLabel);
|
||||||
|
return strAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Value sendtoaddress(const Array& params)
|
||||||
|
{
|
||||||
|
if (params.size() < 2 || params.size() > 4)
|
||||||
|
throw runtime_error(
|
||||||
|
"sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
|
||||||
|
"<amount> is a real and is rounded to the nearest 0.01");
|
||||||
|
|
||||||
|
string strAddress = params[0].get_str();
|
||||||
|
|
||||||
|
// Amount
|
||||||
|
if (params[1].get_real() <= 0.0 || params[1].get_real() > 21000000.0)
|
||||||
|
throw runtime_error("Invalid amount");
|
||||||
|
int64 nAmount = roundint64(params[1].get_real() * 100.00) * CENT;
|
||||||
|
|
||||||
|
// Wallet comments
|
||||||
|
CWalletTx wtx;
|
||||||
|
if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
|
||||||
|
wtx.mapValue["message"] = params[2].get_str();
|
||||||
|
if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
|
||||||
|
wtx.mapValue["to"] = params[3].get_str();
|
||||||
|
|
||||||
|
string strError = SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
|
||||||
|
if (strError != "")
|
||||||
|
throw runtime_error(strError);
|
||||||
|
return "sent";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Value listtransactions(const Array& params)
|
||||||
|
{
|
||||||
|
if (params.size() > 2)
|
||||||
|
throw runtime_error(
|
||||||
|
"listtransactions [count=10] [includegenerated=false]\n"
|
||||||
|
"Returns up to [count] most recent transactions.");
|
||||||
|
|
||||||
|
int64 nCount = 10;
|
||||||
|
if (params.size() > 0)
|
||||||
|
nCount = params[0].get_int64();
|
||||||
|
bool fGenerated = false;
|
||||||
|
if (params.size() > 1)
|
||||||
|
fGenerated = params[1].get_bool();
|
||||||
|
|
||||||
|
Array ret;
|
||||||
|
//// not finished
|
||||||
|
ret.push_back("not implemented yet");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Value getamountpaid(const Array& params)
|
||||||
|
{
|
||||||
|
if (params.size() < 1 || params.size() > 2)
|
||||||
|
throw runtime_error(
|
||||||
|
"getamountpaid <bitcoinaddress> [minconf=1]\n"
|
||||||
|
"Returns the total amount paid to <bitcoinaddress> in transactions with at least [minconf] confirmations.");
|
||||||
|
|
||||||
|
// Bitcoin address
|
||||||
|
string strAddress = params[0].get_str();
|
||||||
|
CScript scriptPubKey;
|
||||||
|
if (!scriptPubKey.SetBitcoinAddress(strAddress))
|
||||||
|
throw runtime_error("Invalid bitcoin address");
|
||||||
|
|
||||||
|
// Minimum confirmations
|
||||||
|
int nMinDepth = 1;
|
||||||
|
if (params.size() > 1)
|
||||||
|
nMinDepth = params[1].get_int();
|
||||||
|
|
||||||
|
// Tally
|
||||||
|
int64 nAmount = 0;
|
||||||
|
CRITICAL_BLOCK(cs_mapWallet)
|
||||||
|
{
|
||||||
|
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||||
|
{
|
||||||
|
const CWalletTx& wtx = (*it).second;
|
||||||
|
if (wtx.IsCoinBase() || !wtx.IsFinal())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
foreach(const CTxOut& txout, wtx.vout)
|
||||||
|
if (txout.scriptPubKey == scriptPubKey)
|
||||||
|
if (wtx.GetDepthInMainChain() >= nMinDepth)
|
||||||
|
nAmount += txout.nValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (double)nAmount / (double)COIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct tallyitem
|
||||||
|
{
|
||||||
|
int64 nAmount;
|
||||||
|
int nConf;
|
||||||
|
tallyitem()
|
||||||
|
{
|
||||||
|
nAmount = 0;
|
||||||
|
nConf = INT_MAX;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Value getallpayments(const Array& params)
|
||||||
|
{
|
||||||
|
if (params.size() > 1)
|
||||||
|
throw runtime_error(
|
||||||
|
"getallpayments [minconf=1]\n"
|
||||||
|
"[minconf] is the minimum number of confirmations before payments are included.\n"
|
||||||
|
"Returns an array of objects containing:\n"
|
||||||
|
" \"address\" : bitcoin address\n"
|
||||||
|
" \"amount\" : total amount paid to the address\n"
|
||||||
|
" \"conf\" : number of confirmations\n"
|
||||||
|
" \"label\" : the label set for this address when it was created by getnewaddress");
|
||||||
|
|
||||||
|
// Minimum confirmations
|
||||||
|
int nMinDepth = 1;
|
||||||
|
if (params.size() > 0)
|
||||||
|
nMinDepth = params[0].get_int();
|
||||||
|
|
||||||
|
// Tally
|
||||||
|
map<uint160, tallyitem> mapTally;
|
||||||
|
CRITICAL_BLOCK(cs_mapWallet)
|
||||||
|
{
|
||||||
|
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||||
|
{
|
||||||
|
const CWalletTx& wtx = (*it).second;
|
||||||
|
if (wtx.IsCoinBase() || !wtx.IsFinal())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int nDepth = wtx.GetDepthInMainChain();
|
||||||
|
if (nDepth >= nMinDepth)
|
||||||
|
{
|
||||||
|
foreach(const CTxOut& txout, wtx.vout)
|
||||||
|
{
|
||||||
|
uint160 hash160 = txout.scriptPubKey.GetBitcoinAddressHash160();
|
||||||
|
if (hash160 == 0 || !mapPubKeys.count(hash160))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
tallyitem& item = mapTally[hash160];
|
||||||
|
item.nAmount += txout.nValue;
|
||||||
|
item.nConf = min(item.nConf, nDepth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reply
|
||||||
|
Array ret;
|
||||||
|
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||||
|
{
|
||||||
|
for (map<uint160, tallyitem>::iterator it = mapTally.begin(); it != mapTally.end(); ++it)
|
||||||
|
{
|
||||||
|
string strAddress = Hash160ToAddress((*it).first);
|
||||||
|
string strLabel;
|
||||||
|
map<string, string>::iterator mi = mapAddressBook.find(strAddress);
|
||||||
|
if (mi != mapAddressBook.end())
|
||||||
|
strLabel = (*mi).second;
|
||||||
|
|
||||||
|
Object obj;
|
||||||
|
obj.push_back(Pair("address", strAddress));
|
||||||
|
obj.push_back(Pair("amount", (double)(*it).second.nAmount / (double)COIN));
|
||||||
|
obj.push_back(Pair("conf", (*it).second.nConf));
|
||||||
|
obj.push_back(Pair("label", strLabel));
|
||||||
|
ret.push_back(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Call Table
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef Value(*rpcfn_type)(const Array& params);
|
||||||
|
pair<string, rpcfn_type> pCallTable[] =
|
||||||
|
{
|
||||||
|
make_pair("stop", &stop),
|
||||||
|
make_pair("getblockcount", &getblockcount),
|
||||||
|
make_pair("getblocknumber", &getblocknumber),
|
||||||
|
make_pair("getdifficulty", &getdifficulty),
|
||||||
|
make_pair("getnewaddress", &getnewaddress),
|
||||||
|
make_pair("sendtoaddress", &sendtoaddress),
|
||||||
|
make_pair("listtransactions", &listtransactions),
|
||||||
|
make_pair("getamountpaid", &getamountpaid),
|
||||||
|
make_pair("getallpayments", &getallpayments),
|
||||||
|
};
|
||||||
|
map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// HTTP protocol
|
||||||
|
//
|
||||||
|
// This ain't Apache. We're just using HTTP header for the length field
|
||||||
|
// and to be compatible with other JSON-RPC implementations.
|
||||||
|
//
|
||||||
|
|
||||||
|
string HTTPPost(const string& strMsg)
|
||||||
|
{
|
||||||
|
return strprintf(
|
||||||
|
"POST / HTTP/1.1\r\n"
|
||||||
|
"User-Agent: json-rpc/1.0\r\n"
|
||||||
|
"Host: 127.0.0.1\r\n"
|
||||||
|
"Content-Type: application/json\r\n"
|
||||||
|
"Content-Length: %d\r\n"
|
||||||
|
"Accept: application/json\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"%s",
|
||||||
|
strMsg.size(),
|
||||||
|
strMsg.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
string HTTPReply(const string& strMsg, int nStatus=200)
|
||||||
|
{
|
||||||
|
string strStatus;
|
||||||
|
if (nStatus == 200) strStatus = "OK";
|
||||||
|
if (nStatus == 500) strStatus = "Internal Server Error";
|
||||||
|
return strprintf(
|
||||||
|
"HTTP/1.1 %d %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"
|
||||||
|
"\r\n"
|
||||||
|
"%s",
|
||||||
|
nStatus,
|
||||||
|
strStatus.c_str(),
|
||||||
|
strMsg.size(),
|
||||||
|
strMsg.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
int ReadHTTPHeader(tcp::iostream& stream)
|
||||||
|
{
|
||||||
|
int nLen = 0;
|
||||||
|
loop
|
||||||
|
{
|
||||||
|
string str;
|
||||||
|
std::getline(stream, str);
|
||||||
|
if (str.empty() || str == "\r")
|
||||||
|
break;
|
||||||
|
if (str.substr(0,15) == "Content-Length:")
|
||||||
|
nLen = atoi(str.substr(15));
|
||||||
|
}
|
||||||
|
return nLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline string ReadHTTP(tcp::iostream& stream)
|
||||||
|
{
|
||||||
|
// Read header
|
||||||
|
int nLen = ReadHTTPHeader(stream);
|
||||||
|
if (nLen <= 0)
|
||||||
|
return string();
|
||||||
|
|
||||||
|
// Read message
|
||||||
|
vector<char> vch(nLen);
|
||||||
|
stream.read(&vch[0], nLen);
|
||||||
|
return string(vch.begin(), vch.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// JSON-RPC protocol
|
||||||
|
//
|
||||||
|
// http://json-rpc.org/wiki/specification
|
||||||
|
// http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
|
||||||
|
//
|
||||||
|
|
||||||
|
string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
|
||||||
|
{
|
||||||
|
Object request;
|
||||||
|
request.push_back(Pair("method", strMethod));
|
||||||
|
request.push_back(Pair("params", params));
|
||||||
|
request.push_back(Pair("id", id));
|
||||||
|
return write_string(Value(request), false) + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
string JSONRPCReply(const Value& result, const Value& error, const Value& id)
|
||||||
|
{
|
||||||
|
Object reply;
|
||||||
|
if (error.type() != null_type)
|
||||||
|
reply.push_back(Pair("result", Value::null));
|
||||||
|
else
|
||||||
|
reply.push_back(Pair("result", result));
|
||||||
|
reply.push_back(Pair("error", error));
|
||||||
|
reply.push_back(Pair("id", id));
|
||||||
|
return write_string(Value(reply), false) + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ThreadRPCServer(void* parg)
|
||||||
|
{
|
||||||
|
IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
|
||||||
|
try
|
||||||
|
{
|
||||||
|
vnThreadsRunning[4]++;
|
||||||
|
ThreadRPCServer2(parg);
|
||||||
|
vnThreadsRunning[4]--;
|
||||||
|
}
|
||||||
|
catch (std::exception& e) {
|
||||||
|
vnThreadsRunning[4]--;
|
||||||
|
PrintException(&e, "ThreadRPCServer()");
|
||||||
|
} catch (...) {
|
||||||
|
vnThreadsRunning[4]--;
|
||||||
|
PrintException(NULL, "ThreadRPCServer()");
|
||||||
|
}
|
||||||
|
printf("ThreadRPCServer exiting\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThreadRPCServer2(void* parg)
|
||||||
|
{
|
||||||
|
printf("ThreadRPCServer started\n");
|
||||||
|
|
||||||
|
// Bind to loopback 127.0.0.1 so the socket can only be accessed locally
|
||||||
|
boost::asio::io_service io_service;
|
||||||
|
tcp::endpoint endpoint(boost::asio::ip::address_v4::loopback(), 8332);
|
||||||
|
tcp::acceptor acceptor(io_service, endpoint);
|
||||||
|
|
||||||
|
loop
|
||||||
|
{
|
||||||
|
// Accept connection
|
||||||
|
tcp::iostream stream;
|
||||||
|
tcp::endpoint peer;
|
||||||
|
vnThreadsRunning[4]--;
|
||||||
|
acceptor.accept(*stream.rdbuf(), peer);
|
||||||
|
vnThreadsRunning[4]++;
|
||||||
|
if (fShutdown)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Shouldn't be possible for anyone else to connect, but just in case
|
||||||
|
if (peer.address().to_string() != "127.0.0.1")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Receive request
|
||||||
|
string strRequest = ReadHTTP(stream);
|
||||||
|
printf("ThreadRPCServer request=%s", strRequest.c_str());
|
||||||
|
|
||||||
|
// Handle multiple invocations per request
|
||||||
|
string::iterator begin = strRequest.begin();
|
||||||
|
while (skipspaces(begin), begin != strRequest.end())
|
||||||
|
{
|
||||||
|
string::iterator prev = begin;
|
||||||
|
Value id;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Parse request
|
||||||
|
Value valRequest;
|
||||||
|
if (!read_range(begin, strRequest.end(), valRequest))
|
||||||
|
throw runtime_error("Parse error.");
|
||||||
|
const Object& request = valRequest.get_obj();
|
||||||
|
if (find_value(request, "method").type() != str_type ||
|
||||||
|
find_value(request, "params").type() != array_type)
|
||||||
|
throw runtime_error("Invalid request.");
|
||||||
|
|
||||||
|
string strMethod = find_value(request, "method").get_str();
|
||||||
|
const Array& params = find_value(request, "params").get_array();
|
||||||
|
id = find_value(request, "id");
|
||||||
|
|
||||||
|
// Execute
|
||||||
|
map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
|
||||||
|
if (mi == mapCallTable.end())
|
||||||
|
throw runtime_error("Method not found.");
|
||||||
|
Value result = (*(*mi).second)(params);
|
||||||
|
|
||||||
|
// Send reply
|
||||||
|
string strReply = JSONRPCReply(result, Value::null, id);
|
||||||
|
stream << HTTPReply(strReply, 200) << std::flush;
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
// Send error reply
|
||||||
|
string strReply = JSONRPCReply(Value::null, e.what(), id);
|
||||||
|
stream << HTTPReply(strReply, 500) << std::flush;
|
||||||
|
}
|
||||||
|
if (begin == prev)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Value CallRPC(const string& strMethod, const Array& params)
|
||||||
|
{
|
||||||
|
// Connect to localhost
|
||||||
|
tcp::iostream stream("127.0.0.1", "8332");
|
||||||
|
if (stream.fail())
|
||||||
|
throw runtime_error("unable to connect to server");
|
||||||
|
|
||||||
|
// Send request
|
||||||
|
string strRequest = JSONRPCRequest(strMethod, params, 1);
|
||||||
|
stream << HTTPPost(strRequest) << std::flush;
|
||||||
|
|
||||||
|
// Receive reply
|
||||||
|
string strReply = ReadHTTP(stream);
|
||||||
|
if (strReply.empty())
|
||||||
|
throw runtime_error("no response from server");
|
||||||
|
|
||||||
|
// Parse reply
|
||||||
|
Value valReply;
|
||||||
|
if (!read_string(strReply, valReply))
|
||||||
|
throw runtime_error("couldn't parse reply from server");
|
||||||
|
const Object& reply = valReply.get_obj();
|
||||||
|
if (reply.empty())
|
||||||
|
throw runtime_error("expected reply to have result, error and id properties");
|
||||||
|
|
||||||
|
const Value& result = find_value(reply, "result");
|
||||||
|
const Value& error = find_value(reply, "error");
|
||||||
|
const Value& id = find_value(reply, "id");
|
||||||
|
|
||||||
|
if (error.type() == str_type)
|
||||||
|
throw runtime_error(error.get_str());
|
||||||
|
else if (error.type() != null_type)
|
||||||
|
throw runtime_error(write_string(error, false));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void ConvertTo(Value& value)
|
||||||
|
{
|
||||||
|
if (value.type() == str_type)
|
||||||
|
{
|
||||||
|
// reinterpret string as unquoted json value
|
||||||
|
Value value2;
|
||||||
|
if (!read_string(value.get_str(), value2))
|
||||||
|
throw runtime_error("type mismatch");
|
||||||
|
value = value2.get_value<T>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = value.get_value<T>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int CommandLineRPC(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Check that method exists
|
||||||
|
if (argc < 2)
|
||||||
|
throw runtime_error("too few parameters");
|
||||||
|
string strMethod = argv[1];
|
||||||
|
if (!mapCallTable.count(strMethod))
|
||||||
|
throw runtime_error(strprintf("unknown command: %s", strMethod.c_str()));
|
||||||
|
|
||||||
|
// Parameters default to strings
|
||||||
|
Array params;
|
||||||
|
for (int i = 2; i < argc; i++)
|
||||||
|
params.push_back(argv[i]);
|
||||||
|
|
||||||
|
// Special case other types
|
||||||
|
int n = params.size();
|
||||||
|
if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
|
||||||
|
if (strMethod == "listtransactions" && n > 0) ConvertTo<boost::int64_t>(params[0]);
|
||||||
|
if (strMethod == "listtransactions" && n > 1) ConvertTo<bool>(params[1]);
|
||||||
|
if (strMethod == "getamountpaid" && n > 1) ConvertTo<boost::int64_t>(params[1]);
|
||||||
|
if (strMethod == "getallpayments" && n > 0) ConvertTo<boost::int64_t>(params[0]);
|
||||||
|
|
||||||
|
// Execute
|
||||||
|
Value result = CallRPC(strMethod, params);
|
||||||
|
|
||||||
|
// Print result
|
||||||
|
string strResult = (result.type() == str_type ? result.get_str() : write_string(result, true));
|
||||||
|
if (result.type() != null_type)
|
||||||
|
{
|
||||||
|
if (fWindows)
|
||||||
|
// Windows GUI apps can't print to command line,
|
||||||
|
// so for now settle for a message box yuck
|
||||||
|
wxMessageBox(strResult.c_str(), "Bitcoin", wxOK);
|
||||||
|
else
|
||||||
|
fprintf(stdout, "%s\n", strResult.c_str());
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
catch (std::exception& e) {
|
||||||
|
if (fWindows)
|
||||||
|
wxMessageBox(strprintf("error: %s\n", e.what()).c_str(), "Bitcoin", wxOK);
|
||||||
|
else
|
||||||
|
fprintf(stderr, "error: %s\n", e.what());
|
||||||
|
} catch (...) {
|
||||||
|
PrintException(NULL, "CommandLineRPC()");
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TEST
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
// Turn off microsoft heap dump noise
|
||||||
|
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
|
||||||
|
_CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
|
||||||
|
#endif
|
||||||
|
setbuf(stdin, NULL);
|
||||||
|
setbuf(stdout, NULL);
|
||||||
|
setbuf(stderr, NULL);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (argc >= 2 && string(argv[1]) == "-server")
|
||||||
|
{
|
||||||
|
printf("server ready\n");
|
||||||
|
ThreadRPCServer(NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return CommandLineRPC(argc, argv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::exception& e) {
|
||||||
|
PrintException(&e, "main()");
|
||||||
|
} catch (...) {
|
||||||
|
PrintException(NULL, "main()");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
6
rpc.h
Normal file
6
rpc.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
// Copyright (c) 2010 Satoshi Nakamoto
|
||||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
|
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
void ThreadRPCServer(void* parg);
|
||||||
|
int CommandLineRPC(int argc, char *argv[]);
|
|
@ -660,7 +660,7 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI
|
||||||
if (stack.size() < 1)
|
if (stack.size() < 1)
|
||||||
return false;
|
return false;
|
||||||
valtype& vch = stacktop(-1);
|
valtype& vch = stacktop(-1);
|
||||||
valtype vchHash(opcode == OP_RIPEMD160 || opcode == OP_SHA1 || opcode == OP_HASH160 ? 20 : 32);
|
valtype vchHash((opcode == OP_RIPEMD160 || opcode == OP_SHA1 || opcode == OP_HASH160) ? 20 : 32);
|
||||||
if (opcode == OP_RIPEMD160)
|
if (opcode == OP_RIPEMD160)
|
||||||
RIPEMD160(&vch[0], vch.size(), &vchHash[0]);
|
RIPEMD160(&vch[0], vch.size(), &vchHash[0]);
|
||||||
else if (opcode == OP_SHA1)
|
else if (opcode == OP_SHA1)
|
||||||
|
@ -753,9 +753,9 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI
|
||||||
CScript scriptCode(pbegincodehash, pend);
|
CScript scriptCode(pbegincodehash, pend);
|
||||||
|
|
||||||
// Drop the signatures, since there's no way for a signature to sign itself
|
// Drop the signatures, since there's no way for a signature to sign itself
|
||||||
for (int i = 0; i < nSigsCount; i++)
|
for (int k = 0; k < nSigsCount; k++)
|
||||||
{
|
{
|
||||||
valtype& vchSig = stacktop(-isig-i);
|
valtype& vchSig = stacktop(-isig-k);
|
||||||
scriptCode.FindAndDelete(CScript(vchSig));
|
scriptCode.FindAndDelete(CScript(vchSig));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -909,7 +909,6 @@ bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CSc
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool Solver(const CScript& scriptPubKey, vector<pair<opcodetype, valtype> >& vSolutionRet)
|
bool Solver(const CScript& scriptPubKey, vector<pair<opcodetype, valtype> >& vSolutionRet)
|
||||||
{
|
{
|
||||||
// Templates
|
// Templates
|
||||||
|
@ -919,7 +918,7 @@ bool Solver(const CScript& scriptPubKey, vector<pair<opcodetype, valtype> >& vSo
|
||||||
// Standard tx, sender provides pubkey, receiver adds signature
|
// Standard tx, sender provides pubkey, receiver adds signature
|
||||||
vTemplates.push_back(CScript() << OP_PUBKEY << OP_CHECKSIG);
|
vTemplates.push_back(CScript() << OP_PUBKEY << OP_CHECKSIG);
|
||||||
|
|
||||||
// Short account number tx, sender provides hash of pubkey, receiver provides signature and pubkey
|
// Bitcoin address tx, sender provides hash of pubkey, receiver provides signature and pubkey
|
||||||
vTemplates.push_back(CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG);
|
vTemplates.push_back(CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
44
script.h
44
script.h
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2009 Satoshi Nakamoto
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
@ -472,7 +472,7 @@ public:
|
||||||
|
|
||||||
bool GetOp(iterator& pc, opcodetype& opcodeRet, vector<unsigned char>& vchRet)
|
bool GetOp(iterator& pc, opcodetype& opcodeRet, vector<unsigned char>& vchRet)
|
||||||
{
|
{
|
||||||
// This is why people hate C++
|
// Wrapper so it can be called with either iterator or const_iterator
|
||||||
const_iterator pc2 = pc;
|
const_iterator pc2 = pc;
|
||||||
bool fRet = GetOp(pc2, opcodeRet, vchRet);
|
bool fRet = GetOp(pc2, opcodeRet, vchRet);
|
||||||
pc = begin() + (pc2 - begin());
|
pc = begin() + (pc2 - begin());
|
||||||
|
@ -551,6 +551,46 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint160 GetBitcoinAddressHash160() const
|
||||||
|
{
|
||||||
|
opcodetype opcode;
|
||||||
|
vector<unsigned char> vch;
|
||||||
|
CScript::const_iterator pc = begin();
|
||||||
|
if (!GetOp(pc, opcode, vch) || opcode != OP_DUP) return 0;
|
||||||
|
if (!GetOp(pc, opcode, vch) || opcode != OP_HASH160) return 0;
|
||||||
|
if (!GetOp(pc, opcode, vch) || vch.size() != sizeof(uint160)) return 0;
|
||||||
|
uint160 hash160 = uint160(vch);
|
||||||
|
if (!GetOp(pc, opcode, vch) || opcode != OP_EQUALVERIFY) return 0;
|
||||||
|
if (!GetOp(pc, opcode, vch) || opcode != OP_CHECKSIG) return 0;
|
||||||
|
if (pc != end()) return 0;
|
||||||
|
return hash160;
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetBitcoinAddress() const
|
||||||
|
{
|
||||||
|
uint160 hash160 = GetBitcoinAddressHash160();
|
||||||
|
if (hash160 == 0)
|
||||||
|
return "";
|
||||||
|
return Hash160ToAddress(hash160);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetBitcoinAddress(const uint160& hash160)
|
||||||
|
{
|
||||||
|
this->clear();
|
||||||
|
*this << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SetBitcoinAddress(const string& strAddress)
|
||||||
|
{
|
||||||
|
this->clear();
|
||||||
|
uint160 hash160;
|
||||||
|
if (!AddressToHash160(strAddress, hash160))
|
||||||
|
return false;
|
||||||
|
SetBitcoinAddress(hash160);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PrintHex() const
|
void PrintHex() const
|
||||||
{
|
{
|
||||||
printf("CScript(%s)\n", HexStr(begin(), end()).c_str());
|
printf("CScript(%s)\n", HexStr(begin(), end()).c_str());
|
||||||
|
|
|
@ -19,8 +19,8 @@ class CScript;
|
||||||
class CDataStream;
|
class CDataStream;
|
||||||
class CAutoFile;
|
class CAutoFile;
|
||||||
|
|
||||||
static const int VERSION = 200;
|
static const int VERSION = 201;
|
||||||
static const char* pszSubVer = " test2";
|
static const char* pszSubVer = ".0";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
468
ui.cpp
468
ui.cpp
|
@ -21,7 +21,6 @@ DEFINE_EVENT_TYPE(wxEVT_REPLY3)
|
||||||
|
|
||||||
CMainFrame* pframeMain = NULL;
|
CMainFrame* pframeMain = NULL;
|
||||||
CMyTaskBarIcon* ptaskbaricon = NULL;
|
CMyTaskBarIcon* ptaskbaricon = NULL;
|
||||||
map<string, string> mapAddressBook;
|
|
||||||
bool fRandSendTest = false;
|
bool fRandSendTest = false;
|
||||||
void RandSend();
|
void RandSend();
|
||||||
extern int g_isPainting;
|
extern int g_isPainting;
|
||||||
|
@ -177,8 +176,11 @@ void CalledMessageBox(const string& message, const string& caption, int style, w
|
||||||
|
|
||||||
int ThreadSafeMessageBox(const string& message, const string& caption, int style, wxWindow* parent, int x, int y)
|
int ThreadSafeMessageBox(const string& message, const string& caption, int style, wxWindow* parent, int x, int y)
|
||||||
{
|
{
|
||||||
if (mapArgs.count("-noui"))
|
if (fDaemon)
|
||||||
|
{
|
||||||
|
printf("wxMessageBox %s: %s\n", caption.c_str(), message.c_str());
|
||||||
return wxOK;
|
return wxOK;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
return wxMessageBox(message, caption, style, parent, x, y);
|
return wxMessageBox(message, caption, style, parent, x, y);
|
||||||
|
@ -413,7 +415,7 @@ void Shutdown(void* parg)
|
||||||
StopNode();
|
StopNode();
|
||||||
DBFlush(true);
|
DBFlush(true);
|
||||||
CreateThread(ExitTimeout, NULL);
|
CreateThread(ExitTimeout, NULL);
|
||||||
Sleep(10);
|
Sleep(50);
|
||||||
printf("Bitcoin exiting\n\n");
|
printf("Bitcoin exiting\n\n");
|
||||||
fExit = true;
|
fExit = true;
|
||||||
exit(0);
|
exit(0);
|
||||||
|
@ -697,19 +699,22 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
|
||||||
vector<unsigned char> vchPubKey;
|
vector<unsigned char> vchPubKey;
|
||||||
if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey))
|
if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey))
|
||||||
{
|
{
|
||||||
string strAddress = PubKeyToAddress(vchPubKey);
|
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||||
if (mapAddressBook.count(strAddress))
|
|
||||||
{
|
{
|
||||||
//strDescription += "Received payment to ";
|
string strAddress = PubKeyToAddress(vchPubKey);
|
||||||
//strDescription += "Received with address ";
|
if (mapAddressBook.count(strAddress))
|
||||||
strDescription += "From: unknown, To: ";
|
{
|
||||||
strDescription += strAddress;
|
//strDescription += "Received payment to ";
|
||||||
/// The labeling feature is just too confusing, so I hid it
|
//strDescription += "Received with address ";
|
||||||
/// by putting it at the end where it runs off the screen.
|
strDescription += "From: unknown, To: ";
|
||||||
/// It can still be seen by widening the column, or in the
|
strDescription += strAddress;
|
||||||
/// details dialog.
|
/// The labeling feature is just too confusing, so I hid it
|
||||||
if (!mapAddressBook[strAddress].empty())
|
/// by putting it at the end where it runs off the screen.
|
||||||
strDescription += " (" + mapAddressBook[strAddress] + ")";
|
/// It can still be seen by widening the column, or in the
|
||||||
|
/// details dialog.
|
||||||
|
if (!mapAddressBook[strAddress].empty())
|
||||||
|
strDescription += " (" + mapAddressBook[strAddress] + ")";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -776,8 +781,9 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
string strDescription = "To: ";
|
string strDescription = "To: ";
|
||||||
if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
|
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||||
strDescription += mapAddressBook[strAddress] + " ";
|
if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
|
||||||
|
strDescription += mapAddressBook[strAddress] + " ";
|
||||||
strDescription += strAddress;
|
strDescription += strAddress;
|
||||||
if (!mapValue["message"].empty())
|
if (!mapValue["message"].empty())
|
||||||
{
|
{
|
||||||
|
@ -1273,238 +1279,241 @@ void CMainFrame::OnListItemActivatedOrdersReceived(wxListEvent& event)
|
||||||
|
|
||||||
CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetailsDialogBase(parent)
|
CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetailsDialogBase(parent)
|
||||||
{
|
{
|
||||||
string strHTML;
|
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||||
strHTML.reserve(4000);
|
|
||||||
strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";
|
|
||||||
|
|
||||||
int64 nTime = wtx.GetTxTime();
|
|
||||||
int64 nCredit = wtx.GetCredit();
|
|
||||||
int64 nDebit = wtx.GetDebit();
|
|
||||||
int64 nNet = nCredit - nDebit;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
strHTML += "<b>Status:</b> " + FormatTxStatus(wtx);
|
|
||||||
int nRequests = wtx.GetRequestCount();
|
|
||||||
if (nRequests != -1)
|
|
||||||
{
|
{
|
||||||
if (nRequests == 0)
|
string strHTML;
|
||||||
strHTML += ", has not been successfully broadcast yet";
|
strHTML.reserve(4000);
|
||||||
else if (nRequests == 1)
|
strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";
|
||||||
strHTML += strprintf(", broadcast through %d node", nRequests);
|
|
||||||
else
|
|
||||||
strHTML += strprintf(", broadcast through %d nodes", nRequests);
|
|
||||||
}
|
|
||||||
strHTML += "<br>";
|
|
||||||
|
|
||||||
strHTML += "<b>Date:</b> " + (nTime ? DateTimeStr(nTime) : "") + "<br>";
|
int64 nTime = wtx.GetTxTime();
|
||||||
|
int64 nCredit = wtx.GetCredit();
|
||||||
|
int64 nDebit = wtx.GetDebit();
|
||||||
|
int64 nNet = nCredit - nDebit;
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// From
|
strHTML += "<b>Status:</b> " + FormatTxStatus(wtx);
|
||||||
//
|
int nRequests = wtx.GetRequestCount();
|
||||||
if (wtx.IsCoinBase())
|
if (nRequests != -1)
|
||||||
{
|
|
||||||
strHTML += "<b>Source:</b> Generated<br>";
|
|
||||||
}
|
|
||||||
else if (!wtx.mapValue["from"].empty())
|
|
||||||
{
|
|
||||||
// Online transaction
|
|
||||||
if (!wtx.mapValue["from"].empty())
|
|
||||||
strHTML += "<b>From:</b> " + HtmlEscape(wtx.mapValue["from"]) + "<br>";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Offline transaction
|
|
||||||
if (nNet > 0)
|
|
||||||
{
|
{
|
||||||
// Credit
|
if (nRequests == 0)
|
||||||
foreach(const CTxOut& txout, wtx.vout)
|
strHTML += ", has not been successfully broadcast yet";
|
||||||
|
else if (nRequests == 1)
|
||||||
|
strHTML += strprintf(", broadcast through %d node", nRequests);
|
||||||
|
else
|
||||||
|
strHTML += strprintf(", broadcast through %d nodes", nRequests);
|
||||||
|
}
|
||||||
|
strHTML += "<br>";
|
||||||
|
|
||||||
|
strHTML += "<b>Date:</b> " + (nTime ? DateTimeStr(nTime) : "") + "<br>";
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// From
|
||||||
|
//
|
||||||
|
if (wtx.IsCoinBase())
|
||||||
|
{
|
||||||
|
strHTML += "<b>Source:</b> Generated<br>";
|
||||||
|
}
|
||||||
|
else if (!wtx.mapValue["from"].empty())
|
||||||
|
{
|
||||||
|
// Online transaction
|
||||||
|
if (!wtx.mapValue["from"].empty())
|
||||||
|
strHTML += "<b>From:</b> " + HtmlEscape(wtx.mapValue["from"]) + "<br>";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Offline transaction
|
||||||
|
if (nNet > 0)
|
||||||
{
|
{
|
||||||
if (txout.IsMine())
|
// Credit
|
||||||
|
foreach(const CTxOut& txout, wtx.vout)
|
||||||
{
|
{
|
||||||
vector<unsigned char> vchPubKey;
|
if (txout.IsMine())
|
||||||
if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey))
|
|
||||||
{
|
{
|
||||||
string strAddress = PubKeyToAddress(vchPubKey);
|
vector<unsigned char> vchPubKey;
|
||||||
if (mapAddressBook.count(strAddress))
|
if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey))
|
||||||
{
|
{
|
||||||
strHTML += "<b>From:</b> unknown<br>";
|
string strAddress = PubKeyToAddress(vchPubKey);
|
||||||
|
if (mapAddressBook.count(strAddress))
|
||||||
|
{
|
||||||
|
strHTML += "<b>From:</b> unknown<br>";
|
||||||
|
strHTML += "<b>To:</b> ";
|
||||||
|
strHTML += HtmlEscape(strAddress);
|
||||||
|
if (!mapAddressBook[strAddress].empty())
|
||||||
|
strHTML += " (yours, label: " + mapAddressBook[strAddress] + ")";
|
||||||
|
else
|
||||||
|
strHTML += " (yours)";
|
||||||
|
strHTML += "<br>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// To
|
||||||
|
//
|
||||||
|
string strAddress;
|
||||||
|
if (!wtx.mapValue["to"].empty())
|
||||||
|
{
|
||||||
|
// Online transaction
|
||||||
|
strAddress = wtx.mapValue["to"];
|
||||||
|
strHTML += "<b>To:</b> ";
|
||||||
|
if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
|
||||||
|
strHTML += mapAddressBook[strAddress] + " ";
|
||||||
|
strHTML += HtmlEscape(strAddress) + "<br>";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Amount
|
||||||
|
//
|
||||||
|
if (wtx.IsCoinBase() && nCredit == 0)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Coinbase
|
||||||
|
//
|
||||||
|
int64 nUnmatured = 0;
|
||||||
|
foreach(const CTxOut& txout, wtx.vout)
|
||||||
|
nUnmatured += txout.GetCredit();
|
||||||
|
if (wtx.IsInMainChain())
|
||||||
|
strHTML += strprintf("<b>Credit:</b> (%s matures in %d more blocks)<br>", FormatMoney(nUnmatured).c_str(), wtx.GetBlocksToMaturity());
|
||||||
|
else
|
||||||
|
strHTML += "<b>Credit:</b> (not accepted)<br>";
|
||||||
|
}
|
||||||
|
else if (nNet > 0)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Credit
|
||||||
|
//
|
||||||
|
strHTML += "<b>Credit:</b> " + FormatMoney(nNet) + "<br>";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool fAllFromMe = true;
|
||||||
|
foreach(const CTxIn& txin, wtx.vin)
|
||||||
|
fAllFromMe = fAllFromMe && txin.IsMine();
|
||||||
|
|
||||||
|
bool fAllToMe = true;
|
||||||
|
foreach(const CTxOut& txout, wtx.vout)
|
||||||
|
fAllToMe = fAllToMe && txout.IsMine();
|
||||||
|
|
||||||
|
if (fAllFromMe)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Debit
|
||||||
|
//
|
||||||
|
foreach(const CTxOut& txout, wtx.vout)
|
||||||
|
{
|
||||||
|
if (txout.IsMine())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (wtx.mapValue["to"].empty())
|
||||||
|
{
|
||||||
|
// Offline transaction
|
||||||
|
uint160 hash160;
|
||||||
|
if (ExtractHash160(txout.scriptPubKey, hash160))
|
||||||
|
{
|
||||||
|
string strAddress = Hash160ToAddress(hash160);
|
||||||
strHTML += "<b>To:</b> ";
|
strHTML += "<b>To:</b> ";
|
||||||
strHTML += HtmlEscape(strAddress);
|
if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
|
||||||
if (!mapAddressBook[strAddress].empty())
|
strHTML += mapAddressBook[strAddress] + " ";
|
||||||
strHTML += " (yours, label: " + mapAddressBook[strAddress] + ")";
|
strHTML += strAddress;
|
||||||
else
|
|
||||||
strHTML += " (yours)";
|
|
||||||
strHTML += "<br>";
|
strHTML += "<br>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
strHTML += "<b>Debit:</b> " + FormatMoney(-txout.nValue) + "<br>";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (fAllToMe)
|
||||||
//
|
|
||||||
// To
|
|
||||||
//
|
|
||||||
string strAddress;
|
|
||||||
if (!wtx.mapValue["to"].empty())
|
|
||||||
{
|
|
||||||
// Online transaction
|
|
||||||
strAddress = wtx.mapValue["to"];
|
|
||||||
strHTML += "<b>To:</b> ";
|
|
||||||
if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
|
|
||||||
strHTML += mapAddressBook[strAddress] + " ";
|
|
||||||
strHTML += HtmlEscape(strAddress) + "<br>";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Amount
|
|
||||||
//
|
|
||||||
if (wtx.IsCoinBase() && nCredit == 0)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Coinbase
|
|
||||||
//
|
|
||||||
int64 nUnmatured = 0;
|
|
||||||
foreach(const CTxOut& txout, wtx.vout)
|
|
||||||
nUnmatured += txout.GetCredit();
|
|
||||||
if (wtx.IsInMainChain())
|
|
||||||
strHTML += strprintf("<b>Credit:</b> (%s matures in %d more blocks)<br>", FormatMoney(nUnmatured).c_str(), wtx.GetBlocksToMaturity());
|
|
||||||
else
|
|
||||||
strHTML += "<b>Credit:</b> (not accepted)<br>";
|
|
||||||
}
|
|
||||||
else if (nNet > 0)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Credit
|
|
||||||
//
|
|
||||||
strHTML += "<b>Credit:</b> " + FormatMoney(nNet) + "<br>";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool fAllFromMe = true;
|
|
||||||
foreach(const CTxIn& txin, wtx.vin)
|
|
||||||
fAllFromMe = fAllFromMe && txin.IsMine();
|
|
||||||
|
|
||||||
bool fAllToMe = true;
|
|
||||||
foreach(const CTxOut& txout, wtx.vout)
|
|
||||||
fAllToMe = fAllToMe && txout.IsMine();
|
|
||||||
|
|
||||||
if (fAllFromMe)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Debit
|
|
||||||
//
|
|
||||||
foreach(const CTxOut& txout, wtx.vout)
|
|
||||||
{
|
|
||||||
if (txout.IsMine())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (wtx.mapValue["to"].empty())
|
|
||||||
{
|
{
|
||||||
// Offline transaction
|
// Payment to self
|
||||||
uint160 hash160;
|
/// issue: can't tell which is the payment and which is the change anymore
|
||||||
if (ExtractHash160(txout.scriptPubKey, hash160))
|
//int64 nValue = wtx.vout[0].nValue;
|
||||||
{
|
//strHTML += "<b>Debit:</b> " + FormatMoney(-nValue) + "<br>";
|
||||||
string strAddress = Hash160ToAddress(hash160);
|
//strHTML += "<b>Credit:</b> " + FormatMoney(nValue) + "<br>";
|
||||||
strHTML += "<b>To:</b> ";
|
|
||||||
if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
|
|
||||||
strHTML += mapAddressBook[strAddress] + " ";
|
|
||||||
strHTML += strAddress;
|
|
||||||
strHTML += "<br>";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
strHTML += "<b>Debit:</b> " + FormatMoney(-txout.nValue) + "<br>";
|
int64 nTxFee = nDebit - wtx.GetValueOut();
|
||||||
|
if (nTxFee > 0)
|
||||||
|
strHTML += "<b>Transaction fee:</b> " + FormatMoney(-nTxFee) + "<br>";
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (fAllToMe)
|
|
||||||
{
|
{
|
||||||
// Payment to self
|
//
|
||||||
/// issue: can't tell which is the payment and which is the change anymore
|
// Mixed debit transaction
|
||||||
//int64 nValue = wtx.vout[0].nValue;
|
//
|
||||||
//strHTML += "<b>Debit:</b> " + FormatMoney(-nValue) + "<br>";
|
foreach(const CTxIn& txin, wtx.vin)
|
||||||
//strHTML += "<b>Credit:</b> " + FormatMoney(nValue) + "<br>";
|
if (txin.IsMine())
|
||||||
|
strHTML += "<b>Debit:</b> " + FormatMoney(-txin.GetDebit()) + "<br>";
|
||||||
|
foreach(const CTxOut& txout, wtx.vout)
|
||||||
|
if (txout.IsMine())
|
||||||
|
strHTML += "<b>Credit:</b> " + FormatMoney(txout.GetCredit()) + "<br>";
|
||||||
}
|
}
|
||||||
|
|
||||||
int64 nTxFee = nDebit - wtx.GetValueOut();
|
|
||||||
if (nTxFee > 0)
|
|
||||||
strHTML += "<b>Transaction fee:</b> " + FormatMoney(-nTxFee) + "<br>";
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
strHTML += "<b>Net amount:</b> " + FormatMoney(nNet, true) + "<br>";
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Message
|
||||||
|
//
|
||||||
|
if (!wtx.mapValue["message"].empty())
|
||||||
|
strHTML += "<br><b>Message:</b><br>" + HtmlEscape(wtx.mapValue["message"], true) + "<br>";
|
||||||
|
|
||||||
|
if (wtx.IsCoinBase())
|
||||||
|
strHTML += "<br>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.<br>";
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Debug view
|
||||||
|
//
|
||||||
|
if (fDebug)
|
||||||
{
|
{
|
||||||
//
|
strHTML += "<hr><br>debug print<br><br>";
|
||||||
// Mixed debit transaction
|
|
||||||
//
|
|
||||||
foreach(const CTxIn& txin, wtx.vin)
|
foreach(const CTxIn& txin, wtx.vin)
|
||||||
if (txin.IsMine())
|
if (txin.IsMine())
|
||||||
strHTML += "<b>Debit:</b> " + FormatMoney(-txin.GetDebit()) + "<br>";
|
strHTML += "<b>Debit:</b> " + FormatMoney(-txin.GetDebit()) + "<br>";
|
||||||
foreach(const CTxOut& txout, wtx.vout)
|
foreach(const CTxOut& txout, wtx.vout)
|
||||||
if (txout.IsMine())
|
if (txout.IsMine())
|
||||||
strHTML += "<b>Credit:</b> " + FormatMoney(txout.GetCredit()) + "<br>";
|
strHTML += "<b>Credit:</b> " + FormatMoney(txout.GetCredit()) + "<br>";
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
strHTML += "<b>Net amount:</b> " + FormatMoney(nNet, true) + "<br>";
|
strHTML += "<b>Inputs:</b><br>";
|
||||||
|
CRITICAL_BLOCK(cs_mapWallet)
|
||||||
|
|
||||||
//
|
|
||||||
// Message
|
|
||||||
//
|
|
||||||
if (!wtx.mapValue["message"].empty())
|
|
||||||
strHTML += "<br><b>Message:</b><br>" + HtmlEscape(wtx.mapValue["message"], true) + "<br>";
|
|
||||||
|
|
||||||
if (wtx.IsCoinBase())
|
|
||||||
strHTML += "<br>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.<br>";
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Debug view
|
|
||||||
//
|
|
||||||
if (fDebug)
|
|
||||||
{
|
|
||||||
strHTML += "<hr><br>debug print<br><br>";
|
|
||||||
foreach(const CTxIn& txin, wtx.vin)
|
|
||||||
if (txin.IsMine())
|
|
||||||
strHTML += "<b>Debit:</b> " + FormatMoney(-txin.GetDebit()) + "<br>";
|
|
||||||
foreach(const CTxOut& txout, wtx.vout)
|
|
||||||
if (txout.IsMine())
|
|
||||||
strHTML += "<b>Credit:</b> " + FormatMoney(txout.GetCredit()) + "<br>";
|
|
||||||
|
|
||||||
strHTML += "<b>Inputs:</b><br>";
|
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
|
||||||
{
|
|
||||||
foreach(const CTxIn& txin, wtx.vin)
|
|
||||||
{
|
{
|
||||||
COutPoint prevout = txin.prevout;
|
foreach(const CTxIn& txin, wtx.vin)
|
||||||
map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
|
|
||||||
if (mi != mapWallet.end())
|
|
||||||
{
|
{
|
||||||
const CWalletTx& prev = (*mi).second;
|
COutPoint prevout = txin.prevout;
|
||||||
if (prevout.n < prev.vout.size())
|
map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
|
||||||
|
if (mi != mapWallet.end())
|
||||||
{
|
{
|
||||||
strHTML += HtmlEscape(prev.ToString(), true);
|
const CWalletTx& prev = (*mi).second;
|
||||||
strHTML += " " + FormatTxStatus(prev) + ", ";
|
if (prevout.n < prev.vout.size())
|
||||||
strHTML = strHTML + "IsMine=" + (prev.vout[prevout.n].IsMine() ? "true" : "false") + "<br>";
|
{
|
||||||
|
strHTML += HtmlEscape(prev.ToString(), true);
|
||||||
|
strHTML += " " + FormatTxStatus(prev) + ", ";
|
||||||
|
strHTML = strHTML + "IsMine=" + (prev.vout[prevout.n].IsMine() ? "true" : "false") + "<br>";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
strHTML += "<br><hr><br><b>Transaction:</b><br>";
|
||||||
|
strHTML += HtmlEscape(wtx.ToString(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
strHTML += "<br><hr><br><b>Transaction:</b><br>";
|
|
||||||
strHTML += HtmlEscape(wtx.ToString(), true);
|
|
||||||
|
strHTML += "</font></html>";
|
||||||
|
string(strHTML.begin(), strHTML.end()).swap(strHTML);
|
||||||
|
m_htmlWin->SetPage(strHTML);
|
||||||
|
m_buttonOK->SetFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
strHTML += "</font></html>";
|
|
||||||
string(strHTML.begin(), strHTML.end()).swap(strHTML);
|
|
||||||
m_htmlWin->SetPage(strHTML);
|
|
||||||
m_buttonOK->SetFocus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTxDetailsDialog::OnButtonOK(wxCommandEvent& event)
|
void CTxDetailsDialog::OnButtonOK(wxCommandEvent& event)
|
||||||
|
@ -1686,9 +1695,10 @@ CAboutDialog::CAboutDialog(wxWindow* parent) : CAboutDialogBase(parent)
|
||||||
|
|
||||||
#if !wxUSE_UNICODE
|
#if !wxUSE_UNICODE
|
||||||
// Workaround until upgrade to wxWidgets supporting UTF-8
|
// Workaround until upgrade to wxWidgets supporting UTF-8
|
||||||
|
// Hack to change the (c) character from UTF-8 back to ANSI
|
||||||
wxString str = m_staticTextMain->GetLabel();
|
wxString str = m_staticTextMain->GetLabel();
|
||||||
if (str.Find('Â') != wxNOT_FOUND)
|
if (str.Find('\xC2') != wxNOT_FOUND)
|
||||||
str.Remove(str.Find('Â'), 1);
|
str.Remove(str.Find('\xC2'), 1);
|
||||||
m_staticTextMain->SetLabel(str);
|
m_staticTextMain->SetLabel(str);
|
||||||
#endif
|
#endif
|
||||||
#ifndef __WXMSW__
|
#ifndef __WXMSW__
|
||||||
|
@ -1843,10 +1853,11 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event)
|
||||||
CScript scriptPubKey;
|
CScript scriptPubKey;
|
||||||
scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG;
|
scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG;
|
||||||
|
|
||||||
if (!SendMoney(scriptPubKey, nValue, wtx))
|
string strError = SendMoney(scriptPubKey, nValue, wtx);
|
||||||
return;
|
if (strError != "")
|
||||||
|
wxMessageBox(strError + " ", "Sending...");
|
||||||
wxMessageBox("Payment sent ", "Sending...");
|
else
|
||||||
|
wxMessageBox("Payment sent ", "Sending...");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1869,8 +1880,9 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mapAddressBook.count(strAddress))
|
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||||
SetAddressBookName(strAddress, "");
|
if (!mapAddressBook.count(strAddress))
|
||||||
|
SetAddressBookName(strAddress, "");
|
||||||
|
|
||||||
EndModal(true);
|
EndModal(true);
|
||||||
}
|
}
|
||||||
|
@ -2227,6 +2239,7 @@ CYourAddressDialog::CYourAddressDialog(wxWindow* parent, const string& strInitSe
|
||||||
|
|
||||||
// Fill listctrl with address book data
|
// Fill listctrl with address book data
|
||||||
CRITICAL_BLOCK(cs_mapKeys)
|
CRITICAL_BLOCK(cs_mapKeys)
|
||||||
|
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||||
{
|
{
|
||||||
foreach(const PAIRTYPE(string, string)& item, mapAddressBook)
|
foreach(const PAIRTYPE(string, string)& item, mapAddressBook)
|
||||||
{
|
{
|
||||||
|
@ -2366,6 +2379,7 @@ CAddressBookDialog::CAddressBookDialog(wxWindow* parent, const wxString& strInit
|
||||||
|
|
||||||
// Fill listctrl with address book data
|
// Fill listctrl with address book data
|
||||||
CRITICAL_BLOCK(cs_mapKeys)
|
CRITICAL_BLOCK(cs_mapKeys)
|
||||||
|
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||||
{
|
{
|
||||||
foreach(const PAIRTYPE(string, string)& item, mapAddressBook)
|
foreach(const PAIRTYPE(string, string)& item, mapAddressBook)
|
||||||
{
|
{
|
||||||
|
@ -3515,6 +3529,12 @@ bool CMyApp::OnInit2()
|
||||||
//
|
//
|
||||||
// Parameters
|
// Parameters
|
||||||
//
|
//
|
||||||
|
if (argc > 1 && argv[1][0] != '-' && argv[1][0] != '/')
|
||||||
|
{
|
||||||
|
int ret = CommandLineRPC(argc, argv);
|
||||||
|
exit(ret);
|
||||||
|
}
|
||||||
|
|
||||||
ParseParameters(argc, argv);
|
ParseParameters(argc, argv);
|
||||||
if (mapArgs.count("-?") || mapArgs.count("--help"))
|
if (mapArgs.count("-?") || mapArgs.count("--help"))
|
||||||
{
|
{
|
||||||
|
@ -3557,6 +3577,13 @@ bool CMyApp::OnInit2()
|
||||||
if (mapArgs.count("-printtodebugger"))
|
if (mapArgs.count("-printtodebugger"))
|
||||||
fPrintToDebugger = true;
|
fPrintToDebugger = true;
|
||||||
|
|
||||||
|
if (mapArgs.count("-daemon") || mapArgs.count("-d"))
|
||||||
|
{
|
||||||
|
fDaemon = true;
|
||||||
|
/// todo: need to fork
|
||||||
|
/// should it fork after the bind/single instance stuff?
|
||||||
|
}
|
||||||
|
|
||||||
if (!fDebug && !pszSetDataDir[0])
|
if (!fDebug && !pszSetDataDir[0])
|
||||||
ShrinkDebugFile();
|
ShrinkDebugFile();
|
||||||
printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
|
printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
|
||||||
|
@ -3730,7 +3757,7 @@ bool CMyApp::OnInit2()
|
||||||
//
|
//
|
||||||
// Create the main frame window
|
// Create the main frame window
|
||||||
//
|
//
|
||||||
if (!mapArgs.count("-noui"))
|
if (!fDaemon)
|
||||||
{
|
{
|
||||||
pframeMain = new CMainFrame(NULL);
|
pframeMain = new CMainFrame(NULL);
|
||||||
if (mapArgs.count("-min"))
|
if (mapArgs.count("-min"))
|
||||||
|
@ -3752,6 +3779,9 @@ bool CMyApp::OnInit2()
|
||||||
if (!CreateThread(StartNode, NULL))
|
if (!CreateThread(StartNode, NULL))
|
||||||
wxMessageBox("Error: CreateThread(StartNode) failed", "Bitcoin");
|
wxMessageBox("Error: CreateThread(StartNode) failed", "Bitcoin");
|
||||||
|
|
||||||
|
if (mapArgs.count("-server") || fDaemon)
|
||||||
|
CreateThread(ThreadRPCServer, NULL);
|
||||||
|
|
||||||
if (fFirstRun)
|
if (fFirstRun)
|
||||||
SetStartOnSystemStartup(true);
|
SetStartOnSystemStartup(true);
|
||||||
|
|
||||||
|
|
3
util.cpp
3
util.cpp
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2009 Satoshi Nakamoto
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ bool fPrintToConsole = false;
|
||||||
bool fPrintToDebugger = false;
|
bool fPrintToDebugger = false;
|
||||||
char pszSetDataDir[MAX_PATH] = "";
|
char pszSetDataDir[MAX_PATH] = "";
|
||||||
bool fShutdown = false;
|
bool fShutdown = false;
|
||||||
|
bool fDaemon = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
18
util.h
18
util.h
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2009 Satoshi Nakamoto
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
@ -55,6 +55,7 @@ inline T& REF(const T& val)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
|
static const bool fWindows = true;
|
||||||
#define MSG_NOSIGNAL 0
|
#define MSG_NOSIGNAL 0
|
||||||
#define MSG_DONTWAIT 0
|
#define MSG_DONTWAIT 0
|
||||||
#ifndef UINT64_MAX
|
#ifndef UINT64_MAX
|
||||||
|
@ -66,7 +67,9 @@ inline T& REF(const T& val)
|
||||||
#define S_IRUSR 0400
|
#define S_IRUSR 0400
|
||||||
#define S_IWUSR 0200
|
#define S_IWUSR 0200
|
||||||
#endif
|
#endif
|
||||||
|
#define unlink _unlink
|
||||||
#else
|
#else
|
||||||
|
static const bool fWindows = false;
|
||||||
#define WSAGetLastError() errno
|
#define WSAGetLastError() errno
|
||||||
#define WSAEWOULDBLOCK EWOULDBLOCK
|
#define WSAEWOULDBLOCK EWOULDBLOCK
|
||||||
#define WSAEMSGSIZE EMSGSIZE
|
#define WSAEMSGSIZE EMSGSIZE
|
||||||
|
@ -116,6 +119,7 @@ extern bool fPrintToConsole;
|
||||||
extern bool fPrintToDebugger;
|
extern bool fPrintToDebugger;
|
||||||
extern char pszSetDataDir[MAX_PATH];
|
extern char pszSetDataDir[MAX_PATH];
|
||||||
extern bool fShutdown;
|
extern bool fShutdown;
|
||||||
|
extern bool fDaemon;
|
||||||
|
|
||||||
void RandAddSeed();
|
void RandAddSeed();
|
||||||
void RandAddSeedPerfmon();
|
void RandAddSeedPerfmon();
|
||||||
|
@ -258,6 +262,11 @@ inline int roundint(double d)
|
||||||
return (int)(d > 0 ? d + 0.5 : d - 0.5);
|
return (int)(d > 0 ? d + 0.5 : d - 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline int64 roundint64(double d)
|
||||||
|
{
|
||||||
|
return (int64)(d > 0 ? d + 0.5 : d - 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
string HexStr(const T itbegin, const T itend, bool fSpaces=true)
|
string HexStr(const T itbegin, const T itend, bool fSpaces=true)
|
||||||
{
|
{
|
||||||
|
@ -323,7 +332,12 @@ inline string DateTimeStrFormat(const char* pszFormat, int64 nTime)
|
||||||
return pszTime;
|
return pszTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void skipspaces(T& it)
|
||||||
|
{
|
||||||
|
while (isspace(*it))
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue