Browse Source

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
pull/1/head
s_nakamoto 13 years ago
parent
commit
22f721dbf2
  1. 33
      bignum.h
  2. 27
      build-msw.txt
  3. 10
      db.h
  4. 9
      headers.h
  5. 2
      irc.cpp
  6. 6
      irc.h
  7. 2
      license.txt
  8. 151
      main.cpp
  9. 9
      main.h
  10. 25
      makefile
  11. 20
      makefile.unix.wx2.8
  12. 20
      makefile.unix.wx2.9
  13. 25
      makefile.vc
  14. 15
      net.cpp
  15. 3
      net.h
  16. 641
      rpc.cpp
  17. 6
      rpc.h
  18. 9
      script.cpp
  19. 44
      script.h
  20. 4
      serialize.h
  21. 436
      ui.cpp
  22. 3
      util.cpp
  23. 18
      util.h

33
bignum.h

@ -1,4 +1,4 @@ @@ -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
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
@ -309,6 +309,37 @@ public: @@ -309,6 +309,37 @@ public:
*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
{
return ::GetSerializeSize(getvch(), nType, nVersion);

27
build-msw.txt

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
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
file license.txt or http://www.opensource.org/licenses/mit-license.php.
This product includes software developed by the OpenSSL Project for use in
@ -13,8 +13,16 @@ WINDOWS BUILD NOTES @@ -13,8 +13,16 @@ WINDOWS BUILD NOTES
Compilers Supported
-------------------
MinGW GCC
Microsoft Visual C++ 6.0 SP6
MinGW GCC (recommended)
MSVC 6.0 SP6: You'll need Boost version 1.34 because they dropped support
for MSVC 6.0 after that. However, they didn't add Asio until 1.35.
You should still be able to build with MSVC 6.0 by adding Asio to 1.34 by
unpacking boost_asio_*.zip into the boost directory:
http://sourceforge.net/projects/asio/files/asio
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
@ -22,8 +30,7 @@ Dependencies @@ -22,8 +30,7 @@ Dependencies
Libraries you need to download separately and build:
default path download
wxWidgets \wxwidgets http://www.wxwidgets.org/downloads/
or prebuilt: http://wxpack.sourceforge.net
wxWidgets \wxwidgets prebuilt: http://wxpack.sourceforge.net
OpenSSL \openssl http://www.openssl.org/source/
Berkeley DB \db http://www.oracle.com/technology/software/products/berkeley-db/index.html
Boost \boost http://www.boost.org/users/download/
@ -89,3 +96,13 @@ Using MinGW and MSYS: @@ -89,3 +96,13 @@ Using MinGW and MSYS:
cd \db\build_unix
sh ../dist/configure --enable-mingw --enable-cxx
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

@ -1,8 +1,7 @@ @@ -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
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
#include <db_cxx.h>
class CTransaction;
class CTxIndex;
class CDiskBlockIndex;
@ -14,6 +13,7 @@ class CAddress; @@ -14,6 +13,7 @@ class CAddress;
class CWalletTx;
extern map<string, string> mapAddressBook;
extern CCriticalSection cs_mapAddressBook;
extern bool fClient;
@ -359,15 +359,17 @@ public: @@ -359,15 +359,17 @@ public:
bool WriteName(const string& strAddress, const string& strName)
{
CRITICAL_BLOCK(cs_mapAddressBook)
mapAddressBook[strAddress] = strName;
nWalletDBUpdated++;
mapAddressBook[strAddress] = strName;
return Write(make_pair(string("name"), strAddress), strName);
}
bool EraseName(const string& strAddress)
{
CRITICAL_BLOCK(cs_mapAddressBook)
mapAddressBook.erase(strAddress);
nWalletDBUpdated++;
mapAddressBook.erase(strAddress);
return Erase(make_pair(string("name"), strAddress));
}

9
headers.h

@ -29,6 +29,7 @@ @@ -29,6 +29,7 @@
#include <openssl/rand.h>
#include <openssl/sha.h>
#include <openssl/ripemd.h>
#include <db_cxx.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
@ -36,6 +37,7 @@ @@ -36,6 +37,7 @@
#include <float.h>
#include <assert.h>
#include <memory>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
@ -53,6 +55,8 @@ @@ -53,6 +55,8 @@
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
#ifdef __WXMSW__
#include <windows.h>
@ -73,8 +77,6 @@ @@ -73,8 +77,6 @@
#include <errno.h>
#include <net/if.h>
#include <ifaddrs.h>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
#endif
#ifdef __BSD__
#include <netinet/in.h>
@ -85,8 +87,6 @@ @@ -85,8 +87,6 @@
using namespace std;
using namespace boost;
#include "strlcpy.h"
#include "serialize.h"
#include "uint256.h"
@ -100,6 +100,7 @@ using namespace boost; @@ -100,6 +100,7 @@ using namespace boost;
#include "irc.h"
#include "main.h"
#include "market.h"
#include "rpc.h"
#include "uibase.h"
#include "ui.h"

2
irc.cpp

@ -1,4 +1,4 @@ @@ -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
// file license.txt or http://www.opensource.org/licenses/mit-license.php.

6
irc.h

@ -1,8 +1,8 @@ @@ -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
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
extern bool RecvLine(SOCKET hSocket, string& strLine);
extern void ThreadIRCSeed(void* parg);
bool RecvLine(SOCKET hSocket, string& strLine);
void ThreadIRCSeed(void* parg);
extern int nGotIRCAddresses;

2
license.txt

@ -1,4 +1,4 @@ @@ -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
of this software and associated documentation files (the "Software"), to deal

151
main.cpp

@ -26,6 +26,7 @@ CBlockIndex* pindexGenesisBlock = NULL; @@ -26,6 +26,7 @@ CBlockIndex* pindexGenesisBlock = NULL;
int nBestHeight = -1;
uint256 hashBestChain = 0;
CBlockIndex* pindexBest = NULL;
int64 nTimeBestReceived = 0;
map<uint256, CBlock*> mapOrphanBlocks;
multimap<uint256, CBlock*> mapOrphanBlocksByPrev;
@ -45,6 +46,9 @@ CKey keyUser; @@ -45,6 +46,9 @@ CKey keyUser;
map<uint256, int> mapRequestCount;
CCriticalSection cs_mapRequestCount;
map<string, string> mapAddressBook;
CCriticalSection cs_mapAddressBook;
// Settings
int fGenerateBitcoins = false;
int64 nTransactionFee = 0;
@ -573,7 +577,7 @@ bool CTransaction::RemoveFromMemoryPool() @@ -573,7 +577,7 @@ bool CTransaction::RemoveFromMemoryPool()
int CMerkleTx::GetDepthInMainChain() const
int CMerkleTx::GetDepthInMainChain(int& nHeightRet) const
{
if (hashBlock == 0 || nIndex == -1)
return 0;
@ -594,6 +598,7 @@ int CMerkleTx::GetDepthInMainChain() const @@ -594,6 +598,7 @@ int CMerkleTx::GetDepthInMainChain() const
fMerkleVerified = true;
}
nHeightRet = pindex->nHeight;
return pindexBest->nHeight - pindex->nHeight + 1;
}
@ -708,15 +713,20 @@ void CWalletTx::RelayWalletTransaction(CTxDB& txdb) @@ -708,15 +713,20 @@ void CWalletTx::RelayWalletTransaction(CTxDB& txdb)
}
}
void RelayWalletTransactions()
void ResendWalletTransactions()
{
static int64 nLastTime;
if (GetTime() - nLastTime < 10 * 60)
// Do this infrequently and randomly to avoid giving away
// that these are our transactions.
static int64 nNextTime;
if (GetTime() < nNextTime)
return;
bool fFirst = (nNextTime == 0);
nNextTime = GetTime() + GetRand(120 * 60);
if (fFirst)
return;
nLastTime = GetTime();
// Rebroadcast any of our txes that aren't in a block yet
printf("RelayWalletTransactions()\n");
printf("ResendWalletTransactions()\n");
CTxDB txdb("r");
CRITICAL_BLOCK(cs_mapWallet)
{
@ -725,7 +735,10 @@ void RelayWalletTransactions() @@ -725,7 +735,10 @@ void RelayWalletTransactions()
foreach(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
{
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)
{
@ -1219,10 +1232,11 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) @@ -1219,10 +1232,11 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
}
}
// New best link
// New best block
hashBestChain = hash;
pindexBest = pindexNew;
nBestHeight = pindexBest->nHeight;
nTimeBestReceived = GetTime();
nTransactionsUpdated++;
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) @@ -1232,9 +1246,6 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
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
static uint256 hashPrevBestCoinBase;
CRITICAL_BLOCK(cs_mapWallet)
@ -2248,7 +2259,7 @@ bool SendMessages(CNode* pto) @@ -2248,7 +2259,7 @@ bool SendMessages(CNode* pto)
return true;
// 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");
// Address refresh broadcast
@ -2270,60 +2281,81 @@ bool SendMessages(CNode* pto) @@ -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
//
vector<CAddress> vAddrToSend;
vAddrToSend.reserve(pto->vAddrToSend.size());
vector<CAddress> vAddr;
vAddr.reserve(pto->vAddrToSend.size());
foreach(const CAddress& addr, pto->vAddrToSend)
{
// returns true if wasn't already contained in the set
if (pto->setAddrKnown.insert(addr).second)
{
vAddrToSend.push_back(addr);
if (vAddrToSend.size() >= 1000)
vAddr.push_back(addr);
if (vAddr.size() >= 1000)
{
pto->PushMessage("addr", vAddrToSend);
vAddrToSend.clear();
pto->PushMessage("addr", vAddr);
vAddr.clear();
}
}
}
pto->vAddrToSend.clear();
if (!vAddrToSend.empty())
pto->PushMessage("addr", vAddrToSend);
if (!vAddr.empty())
pto->PushMessage("addr", vAddr);
//
// Message: inventory
//
vector<CInv> vInventoryToSend;
vector<CInv> vInv;
vector<CInv> vInvWait;
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)
{
// delay txes
if (!fSendTxInv && inv.type == MSG_TX)
{
vInvWait.push_back(inv);
continue;
}
// returns true if wasn't already contained in the set
if (pto->setInventoryKnown.insert(inv).second)
{
vInventoryToSend.push_back(inv);
if (vInventoryToSend.size() >= 1000)
vInv.push_back(inv);
if (vInv.size() >= 1000)
{
pto->PushMessage("inv", vInventoryToSend);
vInventoryToSend.clear();
pto->PushMessage("inv", vInv);
vInv.clear();
}
}
}
pto->vInventoryToSend.clear();
pto->vInventoryToSend = vInvWait;
}
if (!vInventoryToSend.empty())
pto->PushMessage("inv", vInventoryToSend);
if (!vInv.empty())
pto->PushMessage("inv", vInv);
//
// Message: getdata
//
vector<CInv> vAskFor;
vector<CInv> vGetData;
int64 nNow = GetTime() * 1000000;
CTxDB txdb("r");
while (!pto->mapAskFor.empty() && (*pto->mapAskFor.begin()).first <= nNow)
@ -2332,17 +2364,17 @@ bool SendMessages(CNode* pto) @@ -2332,17 +2364,17 @@ bool SendMessages(CNode* pto)
if (!AlreadyHave(txdb, inv))
{
printf("sending getdata: %s\n", inv.ToString().c_str());
vAskFor.push_back(inv);
if (vAskFor.size() >= 1000)
vGetData.push_back(inv);
if (vGetData.size() >= 1000)
{
pto->PushMessage("getdata", vAskFor);
vAskFor.clear();
pto->PushMessage("getdata", vGetData);
vGetData.clear();
}
}
pto->mapAskFor.erase(pto->mapAskFor.begin());
}
if (!vAskFor.empty())
pto->PushMessage("getdata", vAskFor);
if (!vGetData.empty())
pto->PushMessage("getdata", vGetData);
}
return true;
@ -2405,7 +2437,6 @@ void ThreadBitcoinMiner(void* parg) @@ -2405,7 +2437,6 @@ void ThreadBitcoinMiner(void* parg)
vnThreadsRunning[3]--;
PrintException(NULL, "ThreadBitcoinMiner()");
}
printf("ThreadBitcoinMiner exiting, %d threads remaining\n", vnThreadsRunning[3]);
}
@ -2842,6 +2873,13 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CK @@ -2842,6 +2873,13 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CK
// Fill a vout back to self with any change
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
if (keyRet.IsNull())
keyRet.MakeNewKey();
@ -2899,7 +2937,7 @@ bool CommitTransactionSpent(const CWalletTx& wtxNew, const CKey& key) @@ -2899,7 +2937,7 @@ bool CommitTransactionSpent(const CWalletTx& wtxNew, const CKey& key)
//// update: This matters even less now that fSpent can get corrected
//// when transactions are seen in VerifySignature. The remote chance of
//// 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
// duration of this scope. This is the only place where this optimization
@ -2932,7 +2970,7 @@ bool CommitTransactionSpent(const CWalletTx& wtxNew, const CKey& key) @@ -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)
{
@ -2945,13 +2983,13 @@ bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew) @@ -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());
else
strError = "Error: Transaction creation failed ";
wxMessageBox(strError, "Sending...");
return error("SendMoney() : %s", strError.c_str());
printf("SendMoney() : %s", strError.c_str());
return strError;
}
if (!CommitTransactionSpent(wtxNew, key))
{
wxMessageBox("Error finalizing transaction ", "Sending...");
return error("SendMoney() : Error finalizing transaction");
printf("SendMoney() : Error finalizing transaction");
return "Error finalizing transaction";
}
// Track how many getdata requests our transaction gets
@ -2964,11 +3002,32 @@ bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew) @@ -2964,11 +3002,32 @@ bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew)
if (!wtxNew.AcceptTransaction())
{
// 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...");
return error("SendMoney() : Error: Transaction not valid");
printf("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();
}
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

@ -36,6 +36,8 @@ extern CBlockIndex* pindexBest; @@ -36,6 +36,8 @@ extern CBlockIndex* pindexBest;
extern unsigned int nTransactionsUpdated;
extern map<uint256, int> mapRequestCount;
extern CCriticalSection cs_mapRequestCount;
extern map<string, string> mapAddressBook;
extern CCriticalSection cs_mapAddressBook;
// Settings
extern int fGenerateBitcoins;
@ -58,7 +60,6 @@ vector<unsigned char> GenerateNewKey(); @@ -58,7 +60,6 @@ vector<unsigned char> GenerateNewKey();
bool AddToWallet(const CWalletTx& wtxIn);
void WalletUpdateSpent(const COutPoint& prevout);
void ReacceptWalletTransactions();
void RelayWalletTransactions();
bool LoadBlockIndex(bool fAllowNew=true);
void PrintBlockTree();
bool ProcessMessages(CNode* pfrom);
@ -67,7 +68,8 @@ bool SendMessages(CNode* pto); @@ -67,7 +68,8 @@ bool SendMessages(CNode* pto);
int64 GetBalance();
bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CKey& keyRet, int64& nFeeRequiredRet);
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 ThreadBitcoinMiner(void* parg);
void BitcoinMiner();
@ -680,7 +682,8 @@ public: @@ -680,7 +682,8 @@ public:
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; }
int GetBlocksToMaturity() const;
bool AcceptTransaction(CTxDB& txdb, bool fCheckInputs=true);

25
makefile

@ -1,4 +1,4 @@ @@ -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
# file license.txt or http://www.opensource.org/licenses/mit-license.php.
@ -16,22 +16,23 @@ endif @@ -16,22 +16,23 @@ endif
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= \
-l libboost_system-mgw34-mt-d -l libboost_filesystem-mgw34-mt-d \
-l db_cxx \
-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 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
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
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 $@ $<
obj/util.o: util.cpp $(HEADERS)
@ -40,19 +41,19 @@ obj/util.o: util.cpp $(HEADERS) @@ -40,19 +41,19 @@ obj/util.o: util.cpp $(HEADERS)
obj/script.o: script.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/db.o: db.cpp $(HEADERS) market.h
obj/db.o: db.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/net.o: net.cpp $(HEADERS) net.h
obj/net.o: net.cpp $(HEADERS)
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 $@ $<
obj/market.o: market.cpp $(HEADERS) market.h
obj/market.o: market.cpp $(HEADERS)
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 $@ $<
obj/uibase.o: uibase.cpp uibase.h
@ -64,13 +65,17 @@ obj/sha.o: sha.cpp sha.h @@ -64,13 +65,17 @@ obj/sha.o: sha.cpp sha.h
obj/irc.o: irc.cpp $(HEADERS)
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
windres $(WXDEFS) $(INCLUDEPATHS) -o $@ -i $<
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)
-kill /f bitcoin.exe

20
makefile.unix.wx2.8

@ -1,4 +1,4 @@ @@ -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
# file license.txt or http://www.opensource.org/licenses/mit-license.php.
@ -35,14 +35,14 @@ LIBS= \ @@ -35,14 +35,14 @@ LIBS= \
WXDEFS=-D__WXGTK__ -DNOPCH
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
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 $@ $<
obj/util.o: util.cpp $(HEADERS)
@ -51,19 +51,19 @@ obj/util.o: util.cpp $(HEADERS) @@ -51,19 +51,19 @@ obj/util.o: util.cpp $(HEADERS)
obj/script.o: script.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/db.o: db.cpp $(HEADERS) market.h
obj/db.o: db.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/net.o: net.cpp $(HEADERS) net.h
obj/net.o: net.cpp $(HEADERS)
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 $@ $<
obj/market.o: market.cpp $(HEADERS) market.h
obj/market.o: market.cpp $(HEADERS)
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 $@ $<
obj/uibase.o: uibase.cpp uibase.h
@ -75,11 +75,13 @@ obj/sha.o: sha.cpp sha.h @@ -75,11 +75,13 @@ obj/sha.o: sha.cpp sha.h
obj/irc.o: irc.cpp $(HEADERS)
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 \
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)
g++ $(CFLAGS) -o $@ $(LIBPATHS) $(OBJS) $(LIBS)

20
makefile.unix.wx2.9

@ -1,4 +1,4 @@ @@ -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
# file license.txt or http://www.opensource.org/licenses/mit-license.php.
@ -35,14 +35,14 @@ LIBS= \ @@ -35,14 +35,14 @@ LIBS= \
WXDEFS=-D__WXGTK__ -DNOPCH
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
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 $@ $<
obj/util.o: util.cpp $(HEADERS)
@ -51,19 +51,19 @@ obj/util.o: util.cpp $(HEADERS) @@ -51,19 +51,19 @@ obj/util.o: util.cpp $(HEADERS)
obj/script.o: script.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/db.o: db.cpp $(HEADERS) market.h
obj/db.o: db.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/net.o: net.cpp $(HEADERS) net.h
obj/net.o: net.cpp $(HEADERS)
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 $@ $<
obj/market.o: market.cpp $(HEADERS) market.h
obj/market.o: market.cpp $(HEADERS)
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 $@ $<
obj/uibase.o: uibase.cpp uibase.h
@ -75,11 +75,13 @@ obj/sha.o: sha.cpp sha.h @@ -75,11 +75,13 @@ obj/sha.o: sha.cpp sha.h
obj/irc.o: irc.cpp $(HEADERS)
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 \
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)
g++ $(CFLAGS) -o $@ $(LIBPATHS) $(OBJS) $(LIBS)

25
makefile.vc

@ -1,4 +1,4 @@ @@ -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
# file license.txt or http://www.opensource.org/licenses/mit-license.php.
@ -14,15 +14,16 @@ DEBUGFLAGS=/Zi /Od /D__WXDEBUG__ @@ -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"
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= \
libboost_system-vc80-mt-gd.lib libboost_filesystem-vc80-mt-gd.lib \
libdb47s$(D).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 \
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
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) @@ -35,37 +36,41 @@ obj\util.obj: util.cpp $(HEADERS)
obj\script.obj: script.cpp $(HEADERS)
cl $(CFLAGS) /Fo$@ %s
obj\db.obj: db.cpp $(HEADERS) market.h
obj\db.obj: db.cpp $(HEADERS)
cl $(CFLAGS) /Fo$@ %s
obj\net.obj: net.cpp $(HEADERS) net.h
obj\net.obj: net.cpp $(HEADERS)
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
obj\market.obj: market.cpp $(HEADERS) market.h
obj\market.obj: market.cpp $(HEADERS)
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
obj\uibase.obj: uibase.cpp uibase.h
cl $(CFLAGS) /Fo$@ %s
obj\sha.obj: sha.cpp sha.h
obj\sha.obj: sha.cpp sha.h
cl $(CFLAGS) /O2 /Fo$@ %s
obj\irc.obj: irc.cpp $(HEADERS)
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
rc $(INCLUDEPATHS) $(WXDEFS) /Fo$@ %s
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)
-kill /f bitcoin.exe & sleep 1

15
net.cpp

@ -1,4 +1,4 @@ @@ -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
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
@ -522,7 +522,6 @@ void CNode::Cleanup() @@ -522,7 +522,6 @@ void CNode::Cleanup()
void ThreadSocketHandler(void* parg)
{
IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
try
{
vnThreadsRunning[0]++;
@ -536,7 +535,6 @@ void ThreadSocketHandler(void* parg) @@ -536,7 +535,6 @@ void ThreadSocketHandler(void* parg)
vnThreadsRunning[0]--;
throw; // support pthread_cancel()
}
printf("ThreadSocketHandler exiting\n");
}
@ -816,7 +814,6 @@ void ThreadSocketHandler2(void* parg) @@ -816,7 +814,6 @@ void ThreadSocketHandler2(void* parg)
void ThreadOpenConnections(void* parg)
{
IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
try
{
vnThreadsRunning[1]++;
@ -830,7 +827,6 @@ void ThreadOpenConnections(void* parg) @@ -830,7 +827,6 @@ void ThreadOpenConnections(void* parg)
vnThreadsRunning[1]--;
PrintException(NULL, "ThreadOpenConnections()");
}
printf("ThreadOpenConnections exiting\n");
}
@ -928,7 +924,7 @@ void ThreadOpenConnections2(void* parg) @@ -928,7 +924,7 @@ void ThreadOpenConnections2(void* parg)
// 30 days 27 hours
// 90 days 46 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
if (nSinceLastSeen < 60 * 60)
@ -1016,7 +1012,6 @@ bool OpenNetworkConnection(const CAddress& addrConnect) @@ -1016,7 +1012,6 @@ bool OpenNetworkConnection(const CAddress& addrConnect)
void ThreadMessageHandler(void* parg)
{
IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
try
{
vnThreadsRunning[2]++;
@ -1030,7 +1025,6 @@ void ThreadMessageHandler(void* parg) @@ -1030,7 +1025,6 @@ void ThreadMessageHandler(void* parg)
vnThreadsRunning[2]--;
PrintException(NULL, "ThreadMessageHandler()");
}
printf("ThreadMessageHandler exiting\n");
}
@ -1329,7 +1323,7 @@ bool StopNode() @@ -1329,7 +1323,7 @@ bool StopNode()
fShutdown = true;
nTransactionsUpdated++;
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)
break;
@ -1339,7 +1333,8 @@ bool StopNode() @@ -1339,7 +1333,8 @@ bool StopNode()
if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler 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(50);

3
net.h

@ -1,4 +1,4 @@ @@ -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
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
@ -518,6 +518,7 @@ public: @@ -518,6 +518,7 @@ public:
vector<CInv> vInventoryToSend;
CCriticalSection cs_inventory;
multimap<int64, CInv> mapAskFor;
int64 nLastSentTxInv;
// publish and subscription
vector<char> vfSubscribe;

641
rpc.cpp

@ -0,0 +1,641 @@ @@ -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]++;