Merge pull request #3332
5094f8d
Split off rpc_wallet_tests (Wladimir J. van der Laan)829c920
Move CCryptoKeyStore to crypter.cpp (Wladimir J. van der Laan)ae6ea5a
Update build-unix.md to mention --disable-wallet (Wladimir J. van der Laan)4f9e993
Add --disable-wallet option to build system (Wladimir J. van der Laan)d004d72
Move CAddrDB frrom db to net (Wladimir J. van der Laan)48ba56c
Delimit code with #ifdef ENABLE_WALLET (Wladimir J. van der Laan)991685d
Move getinfo to rpcnet.cpp (Wladimir J. van der Laan)bbb0936
Move HelpExample* from rpcwallet to rpcserver (Wladimir J. van der Laan)
This commit is contained in:
commit
05e27c6641
23 changed files with 687 additions and 537 deletions
28
configure.ac
28
configure.ac
|
@ -37,6 +37,13 @@ AM_MAINTAINER_MODE([enable])
|
|||
dnl make the compilation flags quiet unless V=1 is used
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
|
||||
# Enable wallet
|
||||
AC_ARG_ENABLE([wallet],
|
||||
[AS_HELP_STRING([--enable-wallet],
|
||||
[enable wallet (default is yes)])],
|
||||
[enable_wallet=$enableval],
|
||||
[enable_wallet=yes])
|
||||
|
||||
AC_ARG_WITH([miniupnpc],
|
||||
[AS_HELP_STRING([--with-miniupnpc],
|
||||
[enable UPNP (default is yes if libminiupnpc is found)])],
|
||||
|
@ -362,8 +369,10 @@ AC_TRY_COMPILE([#include <sys/socket.h>],
|
|||
[ AC_MSG_RESULT(no)]
|
||||
)
|
||||
|
||||
dnl Check for libdb_cxx
|
||||
BITCOIN_FIND_BDB48
|
||||
if test x$enable_wallet != xno; then
|
||||
dnl Check for libdb_cxx only if wallet enabled
|
||||
BITCOIN_FIND_BDB48
|
||||
fi
|
||||
|
||||
dnl Check for libminiupnpc (optional)
|
||||
if test x$use_upnp != xno; then
|
||||
|
@ -593,6 +602,20 @@ if test "x$use_ccache" != "xno"; then
|
|||
AC_MSG_RESULT($use_ccache)
|
||||
fi
|
||||
|
||||
dnl enable wallet
|
||||
AC_MSG_CHECKING([if wallet should be enabled])
|
||||
if test x$enable_wallet != xno; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE_UNQUOTED([ENABLE_WALLET],[1],[Define to 1 to enable wallet functions])
|
||||
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
|
||||
if test "x$use_qt" != "xno"; then
|
||||
AC_MSG_ERROR([Cannot currently build Qt GUI with wallet disabled. Use --without-qt.])
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl enable ipv6 support
|
||||
AC_MSG_CHECKING([if ipv6 should be enabled])
|
||||
if test x$have_ipv6 = xno; then
|
||||
|
@ -705,6 +728,7 @@ fi
|
|||
|
||||
AM_CONDITIONAL([TARGET_DARWIN], [test x$TARGET_OS = xdarwin])
|
||||
AM_CONDITIONAL([TARGET_WINDOWS], [test x$TARGET_OS = xwindows])
|
||||
AM_CONDITIONAL([ENABLE_WALLET],[test x$enable_wallet == xyes])
|
||||
AM_CONDITIONAL([USE_QRCODE], [test x$use_qr = xyes])
|
||||
AM_CONDITIONAL([USE_LCOV],[test x$use_lcov == xyes])
|
||||
AM_CONDITIONAL([USE_COMPARISON_TOOL],[test x$use_comparison_tool != xno])
|
||||
|
|
|
@ -22,7 +22,7 @@ Dependencies
|
|||
Library Purpose Description
|
||||
------- ------- -----------
|
||||
libssl SSL Support Secure communications
|
||||
libdb4.8 Berkeley DB Blockchain & wallet storage
|
||||
libdb4.8 Berkeley DB Wallet storage
|
||||
libboost Boost C++ Library
|
||||
miniupnpc UPnP Support Optional firewall-jumping support
|
||||
qt GUI GUI toolkit
|
||||
|
@ -178,3 +178,12 @@ Hardening enables the following features:
|
|||
RW- R-- RW-
|
||||
|
||||
The STK RW- means that the stack is readable and writeable but not executable.
|
||||
|
||||
Disable-wallet mode
|
||||
--------------------
|
||||
When the intention is to run only a P2P node without a wallet, bitcoin may be compiled in
|
||||
disable-wallet mode with:
|
||||
|
||||
./configure --disable-wallet
|
||||
|
||||
In this case there is no dependency on Berkeley DB 4.8.
|
||||
|
|
|
@ -4,6 +4,9 @@ AM_CPPFLAGS += -I$(top_srcdir)/src/leveldb/helpers/memenv \
|
|||
-I$(builddir)
|
||||
|
||||
noinst_LIBRARIES = libbitcoin_server.a libbitcoin_common.a libbitcoin_cli.a
|
||||
if ENABLE_WALLET
|
||||
noinst_LIBRARIES += libbitcoin_wallet.a
|
||||
endif
|
||||
|
||||
bin_PROGRAMS = bitcoind bitcoin-cli
|
||||
|
||||
|
@ -33,14 +36,37 @@ obj/build.h: FORCE
|
|||
$(abs_top_srcdir)
|
||||
version.o: obj/build.h
|
||||
|
||||
libbitcoin_server_a_SOURCES = addrman.cpp alert.cpp \
|
||||
libbitcoin_server_a_SOURCES = \
|
||||
addrman.cpp \
|
||||
alert.cpp \
|
||||
rpcserver.cpp \
|
||||
bloom.cpp \
|
||||
chainparams.cpp checkpoints.cpp coins.cpp crypter.cpp db.cpp \
|
||||
init.cpp keystore.cpp leveldbwrapper.cpp main.cpp miner.cpp \
|
||||
net.cpp noui.cpp rpcblockchain.cpp rpcdump.cpp \
|
||||
rpcmining.cpp rpcnet.cpp rpcrawtransaction.cpp rpcwallet.cpp \
|
||||
txdb.cpp txmempool.cpp wallet.cpp walletdb.cpp $(JSON_H) \
|
||||
chainparams.cpp \
|
||||
checkpoints.cpp \
|
||||
coins.cpp \
|
||||
init.cpp \
|
||||
keystore.cpp \
|
||||
leveldbwrapper.cpp \
|
||||
main.cpp \
|
||||
net.cpp \
|
||||
noui.cpp \
|
||||
rpcblockchain.cpp \
|
||||
rpcnet.cpp \
|
||||
rpcrawtransaction.cpp \
|
||||
txdb.cpp \
|
||||
txmempool.cpp \
|
||||
$(JSON_H) \
|
||||
$(BITCOIN_CORE_H)
|
||||
|
||||
libbitcoin_wallet_a_SOURCES = \
|
||||
db.cpp \
|
||||
crypter.cpp \
|
||||
miner.cpp \
|
||||
rpcdump.cpp \
|
||||
rpcmining.cpp \
|
||||
rpcwallet.cpp \
|
||||
wallet.cpp \
|
||||
walletdb.cpp \
|
||||
$(BITCOIN_CORE_H)
|
||||
|
||||
libbitcoin_common_a_SOURCES = \
|
||||
|
@ -68,6 +94,9 @@ nodist_libbitcoin_common_a_SOURCES = $(top_srcdir)/src/obj/build.h
|
|||
# bitcoind binary #
|
||||
bitcoind_LDADD = libbitcoin_server.a libbitcoin_cli.a libbitcoin_common.a leveldb/libleveldb.a leveldb/libmemenv.a \
|
||||
$(BOOST_LIBS)
|
||||
if ENABLE_WALLET
|
||||
bitcoind_LDADD += libbitcoin_wallet.a
|
||||
endif
|
||||
bitcoind_SOURCES = bitcoind.cpp
|
||||
#
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ AM_CPPFLAGS = $(INCLUDES) \
|
|||
AM_LDFLAGS = $(PTHREAD_CFLAGS)
|
||||
|
||||
LIBBITCOIN_SERVER=$(top_builddir)/src/libbitcoin_server.a
|
||||
LIBBITCOIN_WALLET=$(top_builddir)/src/libbitcoin_wallet.a
|
||||
LIBBITCOIN_COMMON=$(top_builddir)/src/libbitcoin_common.a
|
||||
LIBBITCOIN_CLI=$(top_builddir)/src/libbitcoin_cli.a
|
||||
LIBLEVELDB=$(top_builddir)/src/leveldb/libleveldb.a
|
||||
|
|
157
src/crypter.cpp
157
src/crypter.cpp
|
@ -4,9 +4,11 @@
|
|||
|
||||
#include "crypter.h"
|
||||
|
||||
#include "script.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
|
@ -117,3 +119,156 @@ bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned
|
|||
return false;
|
||||
return cKeyCrypter.Decrypt(vchCiphertext, *((CKeyingMaterial*)&vchPlaintext));
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::SetCrypted()
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (fUseCrypto)
|
||||
return true;
|
||||
if (!mapKeys.empty())
|
||||
return false;
|
||||
fUseCrypto = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::Lock()
|
||||
{
|
||||
if (!SetCrypted())
|
||||
return false;
|
||||
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
vMasterKey.clear();
|
||||
}
|
||||
|
||||
NotifyStatusChanged(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!SetCrypted())
|
||||
return false;
|
||||
|
||||
CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
|
||||
for (; mi != mapCryptedKeys.end(); ++mi)
|
||||
{
|
||||
const CPubKey &vchPubKey = (*mi).second.first;
|
||||
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
|
||||
CKeyingMaterial vchSecret;
|
||||
if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
|
||||
return false;
|
||||
if (vchSecret.size() != 32)
|
||||
return false;
|
||||
CKey key;
|
||||
key.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed());
|
||||
if (key.GetPubKey() == vchPubKey)
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
vMasterKey = vMasterKeyIn;
|
||||
}
|
||||
NotifyStatusChanged(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey)
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted())
|
||||
return CBasicKeyStore::AddKeyPubKey(key, pubkey);
|
||||
|
||||
if (IsLocked())
|
||||
return false;
|
||||
|
||||
std::vector<unsigned char> vchCryptedSecret;
|
||||
CKeyingMaterial vchSecret(key.begin(), key.end());
|
||||
if (!EncryptSecret(vMasterKey, vchSecret, pubkey.GetHash(), vchCryptedSecret))
|
||||
return false;
|
||||
|
||||
if (!AddCryptedKey(pubkey, vchCryptedSecret))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CCryptoKeyStore::AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!SetCrypted())
|
||||
return false;
|
||||
|
||||
mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted())
|
||||
return CBasicKeyStore::GetKey(address, keyOut);
|
||||
|
||||
CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
|
||||
if (mi != mapCryptedKeys.end())
|
||||
{
|
||||
const CPubKey &vchPubKey = (*mi).second.first;
|
||||
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
|
||||
CKeyingMaterial vchSecret;
|
||||
if (!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
|
||||
return false;
|
||||
if (vchSecret.size() != 32)
|
||||
return false;
|
||||
keyOut.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted())
|
||||
return CKeyStore::GetPubKey(address, vchPubKeyOut);
|
||||
|
||||
CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
|
||||
if (mi != mapCryptedKeys.end())
|
||||
{
|
||||
vchPubKeyOut = (*mi).second.first;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!mapCryptedKeys.empty() || IsCrypted())
|
||||
return false;
|
||||
|
||||
fUseCrypto = true;
|
||||
BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys)
|
||||
{
|
||||
const CKey &key = mKey.second;
|
||||
CPubKey vchPubKey = key.GetPubKey();
|
||||
CKeyingMaterial vchSecret(key.begin(), key.end());
|
||||
std::vector<unsigned char> vchCryptedSecret;
|
||||
if (!EncryptSecret(vMasterKeyIn, vchSecret, vchPubKey.GetHash(), vchCryptedSecret))
|
||||
return false;
|
||||
if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
|
||||
return false;
|
||||
}
|
||||
mapKeys.clear();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "allocators.h"
|
||||
#include "serialize.h"
|
||||
#include "keystore.h"
|
||||
|
||||
class uint256;
|
||||
|
||||
|
@ -106,4 +107,86 @@ public:
|
|||
bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext);
|
||||
bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext);
|
||||
|
||||
/** Keystore which keeps the private keys encrypted.
|
||||
* It derives from the basic key store, which is used if no encryption is active.
|
||||
*/
|
||||
class CCryptoKeyStore : public CBasicKeyStore
|
||||
{
|
||||
private:
|
||||
CryptedKeyMap mapCryptedKeys;
|
||||
|
||||
CKeyingMaterial vMasterKey;
|
||||
|
||||
// if fUseCrypto is true, mapKeys must be empty
|
||||
// if fUseCrypto is false, vMasterKey must be empty
|
||||
bool fUseCrypto;
|
||||
|
||||
protected:
|
||||
bool SetCrypted();
|
||||
|
||||
// will encrypt previously unencrypted keys
|
||||
bool EncryptKeys(CKeyingMaterial& vMasterKeyIn);
|
||||
|
||||
bool Unlock(const CKeyingMaterial& vMasterKeyIn);
|
||||
|
||||
public:
|
||||
CCryptoKeyStore() : fUseCrypto(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool IsCrypted() const
|
||||
{
|
||||
return fUseCrypto;
|
||||
}
|
||||
|
||||
bool IsLocked() const
|
||||
{
|
||||
if (!IsCrypted())
|
||||
return false;
|
||||
bool result;
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
result = vMasterKey.empty();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Lock();
|
||||
|
||||
virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
|
||||
bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey);
|
||||
bool HaveKey(const CKeyID &address) const
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted())
|
||||
return CBasicKeyStore::HaveKey(address);
|
||||
return mapCryptedKeys.count(address) > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool GetKey(const CKeyID &address, CKey& keyOut) const;
|
||||
bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const;
|
||||
void GetKeys(std::set<CKeyID> &setAddress) const
|
||||
{
|
||||
if (!IsCrypted())
|
||||
{
|
||||
CBasicKeyStore::GetKeys(setAddress);
|
||||
return;
|
||||
}
|
||||
setAddress.clear();
|
||||
CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
|
||||
while (mi != mapCryptedKeys.end())
|
||||
{
|
||||
setAddress.insert((*mi).first);
|
||||
mi++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wallet status (encrypted, locked) changed.
|
||||
* Note: Called without locks held.
|
||||
*/
|
||||
boost::signals2::signal<void (CCryptoKeyStore* wallet)> NotifyStatusChanged;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
110
src/db.cpp
110
src/db.cpp
|
@ -479,113 +479,3 @@ void CDBEnv::Flush(bool fShutdown)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// CAddrDB
|
||||
//
|
||||
|
||||
CAddrDB::CAddrDB()
|
||||
{
|
||||
pathAddr = GetDataDir() / "peers.dat";
|
||||
}
|
||||
|
||||
bool CAddrDB::Write(const CAddrMan& addr)
|
||||
{
|
||||
// Generate random temporary filename
|
||||
unsigned short randv = 0;
|
||||
RAND_bytes((unsigned char *)&randv, sizeof(randv));
|
||||
std::string tmpfn = strprintf("peers.dat.%04x", randv);
|
||||
|
||||
// serialize addresses, checksum data up to that point, then append csum
|
||||
CDataStream ssPeers(SER_DISK, CLIENT_VERSION);
|
||||
ssPeers << FLATDATA(Params().MessageStart());
|
||||
ssPeers << addr;
|
||||
uint256 hash = Hash(ssPeers.begin(), ssPeers.end());
|
||||
ssPeers << hash;
|
||||
|
||||
// open temp output file, and associate with CAutoFile
|
||||
boost::filesystem::path pathTmp = GetDataDir() / tmpfn;
|
||||
FILE *file = fopen(pathTmp.string().c_str(), "wb");
|
||||
CAutoFile fileout = CAutoFile(file, SER_DISK, CLIENT_VERSION);
|
||||
if (!fileout)
|
||||
return error("CAddrman::Write() : open failed");
|
||||
|
||||
// Write and commit header, data
|
||||
try {
|
||||
fileout << ssPeers;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
return error("CAddrman::Write() : I/O error");
|
||||
}
|
||||
FileCommit(fileout);
|
||||
fileout.fclose();
|
||||
|
||||
// replace existing peers.dat, if any, with new peers.dat.XXXX
|
||||
if (!RenameOver(pathTmp, pathAddr))
|
||||
return error("CAddrman::Write() : Rename-into-place failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAddrDB::Read(CAddrMan& addr)
|
||||
{
|
||||
// open input file, and associate with CAutoFile
|
||||
FILE *file = fopen(pathAddr.string().c_str(), "rb");
|
||||
CAutoFile filein = CAutoFile(file, SER_DISK, CLIENT_VERSION);
|
||||
if (!filein)
|
||||
return error("CAddrman::Read() : open failed");
|
||||
|
||||
// use file size to size memory buffer
|
||||
int fileSize = GetFilesize(filein);
|
||||
int dataSize = fileSize - sizeof(uint256);
|
||||
//Don't try to resize to a negative number if file is small
|
||||
if ( dataSize < 0 ) dataSize = 0;
|
||||
vector<unsigned char> vchData;
|
||||
vchData.resize(dataSize);
|
||||
uint256 hashIn;
|
||||
|
||||
// read data and checksum from file
|
||||
try {
|
||||
filein.read((char *)&vchData[0], dataSize);
|
||||
filein >> hashIn;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
return error("CAddrman::Read() 2 : I/O error or stream data corrupted");
|
||||
}
|
||||
filein.fclose();
|
||||
|
||||
CDataStream ssPeers(vchData, SER_DISK, CLIENT_VERSION);
|
||||
|
||||
// verify stored checksum matches input data
|
||||
uint256 hashTmp = Hash(ssPeers.begin(), ssPeers.end());
|
||||
if (hashIn != hashTmp)
|
||||
return error("CAddrman::Read() : checksum mismatch; data corrupted");
|
||||
|
||||
unsigned char pchMsgTmp[4];
|
||||
try {
|
||||
// de-serialize file header (network specific magic number) and ..
|
||||
ssPeers >> FLATDATA(pchMsgTmp);
|
||||
|
||||
// ... verify the network matches ours
|
||||
if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
|
||||
return error("CAddrman::Read() : invalid network magic number");
|
||||
|
||||
// de-serialize address data into one CAddrMan object
|
||||
ssPeers >> addr;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
return error("CAddrman::Read() : I/O error or stream data corrupted");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
18
src/db.h
18
src/db.h
|
@ -305,22 +305,4 @@ public:
|
|||
bool static Rewrite(const std::string& strFile, const char* pszSkip = NULL);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Access to the (IP) address database (peers.dat) */
|
||||
class CAddrDB
|
||||
{
|
||||
private:
|
||||
boost::filesystem::path pathAddr;
|
||||
public:
|
||||
CAddrDB();
|
||||
bool Write(const CAddrMan& addr);
|
||||
bool Read(CAddrMan& addr);
|
||||
};
|
||||
|
||||
#endif // BITCOIN_DB_H
|
||||
|
|
41
src/init.cpp
41
src/init.cpp
|
@ -10,6 +10,7 @@
|
|||
#include "init.h"
|
||||
|
||||
#include "addrman.h"
|
||||
#include "db.h"
|
||||
#include "rpcserver.h"
|
||||
#include "checkpoints.h"
|
||||
#include "miner.h"
|
||||
|
@ -17,8 +18,10 @@
|
|||
#include "txdb.h"
|
||||
#include "ui_interface.h"
|
||||
#include "util.h"
|
||||
#ifdef ENABLE_WALLET
|
||||
#include "wallet.h"
|
||||
#include "walletdb.h"
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
|
@ -35,8 +38,10 @@
|
|||
using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
std::string strWalletFile;
|
||||
CWallet* pwalletMain;
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
// Win32 LevelDB doesn't use filedescriptors, and the ones used for
|
||||
|
@ -108,15 +113,19 @@ void Shutdown()
|
|||
RenameThread("bitcoin-shutoff");
|
||||
mempool.AddTransactionsUpdated(1);
|
||||
StopRPCThreads();
|
||||
#ifdef ENABLE_WALLET
|
||||
ShutdownRPCMining();
|
||||
if (pwalletMain)
|
||||
bitdb.Flush(false);
|
||||
GenerateBitcoins(false, NULL, 0);
|
||||
#endif
|
||||
StopNode();
|
||||
{
|
||||
LOCK(cs_main);
|
||||
#ifdef ENABLE_WALLET
|
||||
if (pwalletMain)
|
||||
pwalletMain->SetBestChain(chainActive.GetLocator());
|
||||
#endif
|
||||
if (pblocktree)
|
||||
pblocktree->Flush();
|
||||
if (pcoinsTip)
|
||||
|
@ -125,12 +134,16 @@ void Shutdown()
|
|||
delete pcoinsdbview; pcoinsdbview = NULL;
|
||||
delete pblocktree; pblocktree = NULL;
|
||||
}
|
||||
#ifdef ENABLE_WALLET
|
||||
if (pwalletMain)
|
||||
bitdb.Flush(true);
|
||||
#endif
|
||||
boost::filesystem::remove(GetPidFile());
|
||||
UnregisterAllWallets();
|
||||
#ifdef ENABLE_WALLET
|
||||
if (pwalletMain)
|
||||
delete pwalletMain;
|
||||
#endif
|
||||
LogPrintf("Shutdown : done\n");
|
||||
}
|
||||
|
||||
|
@ -479,7 +492,9 @@ bool AppInit2(boost::thread_group& threadGroup, bool fForceServer)
|
|||
fPrintToConsole = GetBoolArg("-printtoconsole", false);
|
||||
fPrintToDebugger = GetBoolArg("-printtodebugger", false);
|
||||
fLogTimestamps = GetBoolArg("-logtimestamps", true);
|
||||
#ifdef ENABLE_WALLET
|
||||
bool fDisableWallet = GetBoolArg("-disablewallet", false);
|
||||
#endif
|
||||
|
||||
if (mapArgs.count("-timeout"))
|
||||
{
|
||||
|
@ -525,16 +540,17 @@ bool AppInit2(boost::thread_group& threadGroup, bool fForceServer)
|
|||
InitWarning(_("Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction."));
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
strWalletFile = GetArg("-wallet", "wallet.dat");
|
||||
|
||||
#endif
|
||||
// ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log
|
||||
|
||||
std::string strDataDir = GetDataDir().string();
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
// Wallet file must be a plain filename without a directory
|
||||
if (strWalletFile != boost::filesystem::basename(strWalletFile) + boost::filesystem::extension(strWalletFile))
|
||||
return InitError(strprintf(_("Wallet %s resides outside data directory %s"), strWalletFile.c_str(), strDataDir.c_str()));
|
||||
|
||||
#endif
|
||||
// Make sure only a single Bitcoin process is using the data directory.
|
||||
boost::filesystem::path pathLockFile = GetDataDir() / ".lock";
|
||||
FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist.
|
||||
|
@ -567,7 +583,7 @@ bool AppInit2(boost::thread_group& threadGroup, bool fForceServer)
|
|||
int64_t nStart;
|
||||
|
||||
// ********************************************************* Step 5: verify wallet database integrity
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
if (!fDisableWallet) {
|
||||
uiInterface.InitMessage(_("Verifying wallet..."));
|
||||
|
||||
|
@ -613,7 +629,7 @@ bool AppInit2(boost::thread_group& threadGroup, bool fForceServer)
|
|||
return InitError(_("wallet.dat corrupt, salvage failed"));
|
||||
}
|
||||
} // (!fDisableWallet)
|
||||
|
||||
#endif // ENABLE_WALLET
|
||||
// ********************************************************* Step 6: network initialization
|
||||
|
||||
RegisterNodeSignals(GetNodeSignals());
|
||||
|
@ -880,7 +896,7 @@ bool AppInit2(boost::thread_group& threadGroup, bool fForceServer)
|
|||
}
|
||||
|
||||
// ********************************************************* Step 8: load wallet
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
if (fDisableWallet) {
|
||||
pwalletMain = NULL;
|
||||
LogPrintf("Wallet disabled!\n");
|
||||
|
@ -972,7 +988,9 @@ bool AppInit2(boost::thread_group& threadGroup, bool fForceServer)
|
|||
nWalletDBUpdated++;
|
||||
}
|
||||
} // (!fDisableWallet)
|
||||
|
||||
#else // ENABLE_WALLET
|
||||
LogPrintf("No wallet compiled in!\n");
|
||||
#endif // !ENABLE_WALLET
|
||||
// ********************************************************* Step 9: import blocks
|
||||
|
||||
// scan for better chains in the block chain database, that are not yet connected in the active best chain
|
||||
|
@ -1016,25 +1034,31 @@ bool AppInit2(boost::thread_group& threadGroup, bool fForceServer)
|
|||
//// debug print
|
||||
LogPrintf("mapBlockIndex.size() = %"PRIszu"\n", mapBlockIndex.size());
|
||||
LogPrintf("nBestHeight = %d\n", chainActive.Height());
|
||||
#ifdef ENABLE_WALLET
|
||||
LogPrintf("setKeyPool.size() = %"PRIszu"\n", pwalletMain ? pwalletMain->setKeyPool.size() : 0);
|
||||
LogPrintf("mapWallet.size() = %"PRIszu"\n", pwalletMain ? pwalletMain->mapWallet.size() : 0);
|
||||
LogPrintf("mapAddressBook.size() = %"PRIszu"\n", pwalletMain ? pwalletMain->mapAddressBook.size() : 0);
|
||||
#endif
|
||||
|
||||
StartNode(threadGroup);
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
// InitRPCMining is needed here so getwork/getblocktemplate in the GUI debug console works properly.
|
||||
InitRPCMining();
|
||||
#endif
|
||||
if (fServer)
|
||||
StartRPCThreads();
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
// Generate coins in the background
|
||||
if (pwalletMain)
|
||||
GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain, GetArg("-genproclimit", -1));
|
||||
#endif
|
||||
|
||||
// ********************************************************* Step 12: finished
|
||||
|
||||
uiInterface.InitMessage(_("Done loading"));
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
if (pwalletMain) {
|
||||
// Add wallet transactions that aren't already in a block to mapTransactions
|
||||
pwalletMain->ReacceptWalletTransactions();
|
||||
|
@ -1042,6 +1066,7 @@ bool AppInit2(boost::thread_group& threadGroup, bool fForceServer)
|
|||
// Run a thread to flush wallet periodically
|
||||
threadGroup.create_thread(boost::bind(&ThreadFlushWalletDB, boost::ref(pwalletMain->strWalletFile)));
|
||||
}
|
||||
#endif
|
||||
|
||||
return !fRequestShutdown;
|
||||
}
|
||||
|
|
152
src/keystore.cpp
152
src/keystore.cpp
|
@ -56,155 +56,3 @@ bool CBasicKeyStore::GetCScript(const CScriptID &hash, CScript& redeemScriptOut)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::SetCrypted()
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (fUseCrypto)
|
||||
return true;
|
||||
if (!mapKeys.empty())
|
||||
return false;
|
||||
fUseCrypto = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::Lock()
|
||||
{
|
||||
if (!SetCrypted())
|
||||
return false;
|
||||
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
vMasterKey.clear();
|
||||
}
|
||||
|
||||
NotifyStatusChanged(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!SetCrypted())
|
||||
return false;
|
||||
|
||||
CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
|
||||
for (; mi != mapCryptedKeys.end(); ++mi)
|
||||
{
|
||||
const CPubKey &vchPubKey = (*mi).second.first;
|
||||
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
|
||||
CKeyingMaterial vchSecret;
|
||||
if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
|
||||
return false;
|
||||
if (vchSecret.size() != 32)
|
||||
return false;
|
||||
CKey key;
|
||||
key.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed());
|
||||
if (key.GetPubKey() == vchPubKey)
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
vMasterKey = vMasterKeyIn;
|
||||
}
|
||||
NotifyStatusChanged(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey)
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted())
|
||||
return CBasicKeyStore::AddKeyPubKey(key, pubkey);
|
||||
|
||||
if (IsLocked())
|
||||
return false;
|
||||
|
||||
std::vector<unsigned char> vchCryptedSecret;
|
||||
CKeyingMaterial vchSecret(key.begin(), key.end());
|
||||
if (!EncryptSecret(vMasterKey, vchSecret, pubkey.GetHash(), vchCryptedSecret))
|
||||
return false;
|
||||
|
||||
if (!AddCryptedKey(pubkey, vchCryptedSecret))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CCryptoKeyStore::AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!SetCrypted())
|
||||
return false;
|
||||
|
||||
mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted())
|
||||
return CBasicKeyStore::GetKey(address, keyOut);
|
||||
|
||||
CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
|
||||
if (mi != mapCryptedKeys.end())
|
||||
{
|
||||
const CPubKey &vchPubKey = (*mi).second.first;
|
||||
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
|
||||
CKeyingMaterial vchSecret;
|
||||
if (!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
|
||||
return false;
|
||||
if (vchSecret.size() != 32)
|
||||
return false;
|
||||
keyOut.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted())
|
||||
return CKeyStore::GetPubKey(address, vchPubKeyOut);
|
||||
|
||||
CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
|
||||
if (mi != mapCryptedKeys.end())
|
||||
{
|
||||
vchPubKeyOut = (*mi).second.first;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!mapCryptedKeys.empty() || IsCrypted())
|
||||
return false;
|
||||
|
||||
fUseCrypto = true;
|
||||
BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys)
|
||||
{
|
||||
const CKey &key = mKey.second;
|
||||
CPubKey vchPubKey = key.GetPubKey();
|
||||
CKeyingMaterial vchSecret(key.begin(), key.end());
|
||||
std::vector<unsigned char> vchCryptedSecret;
|
||||
if (!EncryptSecret(vMasterKeyIn, vchSecret, vchPubKey.GetHash(), vchCryptedSecret))
|
||||
return false;
|
||||
if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
|
||||
return false;
|
||||
}
|
||||
mapKeys.clear();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -93,87 +93,4 @@ public:
|
|||
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
|
||||
typedef std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char> > > CryptedKeyMap;
|
||||
|
||||
|
||||
/** Keystore which keeps the private keys encrypted.
|
||||
* It derives from the basic key store, which is used if no encryption is active.
|
||||
*/
|
||||
class CCryptoKeyStore : public CBasicKeyStore
|
||||
{
|
||||
private:
|
||||
CryptedKeyMap mapCryptedKeys;
|
||||
|
||||
CKeyingMaterial vMasterKey;
|
||||
|
||||
// if fUseCrypto is true, mapKeys must be empty
|
||||
// if fUseCrypto is false, vMasterKey must be empty
|
||||
bool fUseCrypto;
|
||||
|
||||
protected:
|
||||
bool SetCrypted();
|
||||
|
||||
// will encrypt previously unencrypted keys
|
||||
bool EncryptKeys(CKeyingMaterial& vMasterKeyIn);
|
||||
|
||||
bool Unlock(const CKeyingMaterial& vMasterKeyIn);
|
||||
|
||||
public:
|
||||
CCryptoKeyStore() : fUseCrypto(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool IsCrypted() const
|
||||
{
|
||||
return fUseCrypto;
|
||||
}
|
||||
|
||||
bool IsLocked() const
|
||||
{
|
||||
if (!IsCrypted())
|
||||
return false;
|
||||
bool result;
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
result = vMasterKey.empty();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Lock();
|
||||
|
||||
virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
|
||||
bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey);
|
||||
bool HaveKey(const CKeyID &address) const
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted())
|
||||
return CBasicKeyStore::HaveKey(address);
|
||||
return mapCryptedKeys.count(address) > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool GetKey(const CKeyID &address, CKey& keyOut) const;
|
||||
bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const;
|
||||
void GetKeys(std::set<CKeyID> &setAddress) const
|
||||
{
|
||||
if (!IsCrypted())
|
||||
{
|
||||
CBasicKeyStore::GetKeys(setAddress);
|
||||
return;
|
||||
}
|
||||
setAddress.clear();
|
||||
CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
|
||||
while (mi != mapCryptedKeys.end())
|
||||
{
|
||||
setAddress.insert((*mi).first);
|
||||
mi++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wallet status (encrypted, locked) changed.
|
||||
* Note: Called without locks held.
|
||||
*/
|
||||
boost::signals2::signal<void (CCryptoKeyStore* wallet)> NotifyStatusChanged;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
100
src/net.cpp
100
src/net.cpp
|
@ -1942,3 +1942,103 @@ void CNode::Fuzz(int nChance)
|
|||
// (more changes exponentially less likely):
|
||||
Fuzz(2);
|
||||
}
|
||||
|
||||
//
|
||||
// CAddrDB
|
||||
//
|
||||
|
||||
CAddrDB::CAddrDB()
|
||||
{
|
||||
pathAddr = GetDataDir() / "peers.dat";
|
||||
}
|
||||
|
||||
bool CAddrDB::Write(const CAddrMan& addr)
|
||||
{
|
||||
// Generate random temporary filename
|
||||
unsigned short randv = 0;
|
||||
RAND_bytes((unsigned char *)&randv, sizeof(randv));
|
||||
std::string tmpfn = strprintf("peers.dat.%04x", randv);
|
||||
|
||||
// serialize addresses, checksum data up to that point, then append csum
|
||||
CDataStream ssPeers(SER_DISK, CLIENT_VERSION);
|
||||
ssPeers << FLATDATA(Params().MessageStart());
|
||||
ssPeers << addr;
|
||||
uint256 hash = Hash(ssPeers.begin(), ssPeers.end());
|
||||
ssPeers << hash;
|
||||
|
||||
// open temp output file, and associate with CAutoFile
|
||||
boost::filesystem::path pathTmp = GetDataDir() / tmpfn;
|
||||
FILE *file = fopen(pathTmp.string().c_str(), "wb");
|
||||
CAutoFile fileout = CAutoFile(file, SER_DISK, CLIENT_VERSION);
|
||||
if (!fileout)
|
||||
return error("CAddrman::Write() : open failed");
|
||||
|
||||
// Write and commit header, data
|
||||
try {
|
||||
fileout << ssPeers;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
return error("CAddrman::Write() : I/O error");
|
||||
}
|
||||
FileCommit(fileout);
|
||||
fileout.fclose();
|
||||
|
||||
// replace existing peers.dat, if any, with new peers.dat.XXXX
|
||||
if (!RenameOver(pathTmp, pathAddr))
|
||||
return error("CAddrman::Write() : Rename-into-place failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAddrDB::Read(CAddrMan& addr)
|
||||
{
|
||||
// open input file, and associate with CAutoFile
|
||||
FILE *file = fopen(pathAddr.string().c_str(), "rb");
|
||||
CAutoFile filein = CAutoFile(file, SER_DISK, CLIENT_VERSION);
|
||||
if (!filein)
|
||||
return error("CAddrman::Read() : open failed");
|
||||
|
||||
// use file size to size memory buffer
|
||||
int fileSize = GetFilesize(filein);
|
||||
int dataSize = fileSize - sizeof(uint256);
|
||||
//Don't try to resize to a negative number if file is small
|
||||
if ( dataSize < 0 ) dataSize = 0;
|
||||
vector<unsigned char> vchData;
|
||||
vchData.resize(dataSize);
|
||||
uint256 hashIn;
|
||||
|
||||
// read data and checksum from file
|
||||
try {
|
||||
filein.read((char *)&vchData[0], dataSize);
|
||||
filein >> hashIn;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
return error("CAddrman::Read() 2 : I/O error or stream data corrupted");
|
||||
}
|
||||
filein.fclose();
|
||||
|
||||
CDataStream ssPeers(vchData, SER_DISK, CLIENT_VERSION);
|
||||
|
||||
// verify stored checksum matches input data
|
||||
uint256 hashTmp = Hash(ssPeers.begin(), ssPeers.end());
|
||||
if (hashIn != hashTmp)
|
||||
return error("CAddrman::Read() : checksum mismatch; data corrupted");
|
||||
|
||||
unsigned char pchMsgTmp[4];
|
||||
try {
|
||||
// de-serialize file header (network specific magic number) and ..
|
||||
ssPeers >> FLATDATA(pchMsgTmp);
|
||||
|
||||
// ... verify the network matches ours
|
||||
if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
|
||||
return error("CAddrman::Read() : invalid network magic number");
|
||||
|
||||
// de-serialize address data into one CAddrMan object
|
||||
ssPeers >> addr;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
return error("CAddrman::Read() : I/O error or stream data corrupted");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
11
src/net.h
11
src/net.h
|
@ -690,4 +690,15 @@ class CTransaction;
|
|||
void RelayTransaction(const CTransaction& tx, const uint256& hash);
|
||||
void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss);
|
||||
|
||||
/** Access to the (IP) address database (peers.dat) */
|
||||
class CAddrDB
|
||||
{
|
||||
private:
|
||||
boost::filesystem::path pathAddr;
|
||||
public:
|
||||
CAddrDB();
|
||||
bool Write(const CAddrMan& addr);
|
||||
bool Read(CAddrMan& addr);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -197,7 +197,7 @@ endif
|
|||
bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(QT_INCLUDES) \
|
||||
-I$(top_srcdir)/src/qt/forms
|
||||
bitcoin_qt_SOURCES = bitcoin.cpp
|
||||
bitcoin_qt_LDADD = libbitcoinqt.a $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) $(LIBMEMENV) \
|
||||
bitcoin_qt_LDADD = libbitcoinqt.a $(LIBBITCOIN_SERVER) $(LIBBITCOIN_WALLET) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) $(LIBMEMENV) \
|
||||
$(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS)
|
||||
|
||||
# forms/foo.h -> forms/ui_foo.h
|
||||
|
|
|
@ -17,7 +17,7 @@ BUILT_SOURCES = $(TEST_QT_MOC_CPP)
|
|||
test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(QT_INCLUDES) $(QT_TEST_INCLUDES)
|
||||
test_bitcoin_qt_SOURCES = test_main.cpp uritests.cpp paymentservertests.cpp $(TEST_QT_H)
|
||||
nodist_test_bitcoin_qt_SOURCES = $(TEST_QT_MOC_CPP)
|
||||
test_bitcoin_qt_LDADD = $(LIBBITCOINQT) $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) \
|
||||
test_bitcoin_qt_LDADD = $(LIBBITCOINQT) $(LIBBITCOIN_SERVER) $(LIBBITCOIN_WALLET) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) \
|
||||
$(LIBMEMENV) $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) \
|
||||
$(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS)
|
||||
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
// Copyright (c) 2009-2013 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "rpcserver.h"
|
||||
#include "net.h"
|
||||
#include "netbase.h"
|
||||
#include "protocol.h"
|
||||
#include "sync.h"
|
||||
#include "util.h"
|
||||
#ifdef ENABLE_WALLET
|
||||
#include "wallet.h" // for getinfo
|
||||
#include "init.h" // for getinfo
|
||||
#endif
|
||||
#include "main.h" // for getinfo
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
|
@ -329,3 +333,65 @@ Value getnettotals(const Array& params, bool fHelp)
|
|||
obj.push_back(Pair("timemillis", static_cast<boost::int64_t>(GetTimeMillis())));
|
||||
return obj;
|
||||
}
|
||||
|
||||
Value getinfo(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 0)
|
||||
throw runtime_error(
|
||||
"getinfo\n"
|
||||
"Returns an object containing various state info.\n"
|
||||
"\nResult:\n"
|
||||
"{\n"
|
||||
" \"version\": xxxxx, (numeric) the server version\n"
|
||||
" \"protocolversion\": xxxxx, (numeric) the protocol version\n"
|
||||
" \"walletversion\": xxxxx, (numeric) the wallet version\n"
|
||||
" \"balance\": xxxxxxx, (numeric) the total bitcoin balance of the wallet\n"
|
||||
" \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n"
|
||||
" \"timeoffset\": xxxxx, (numeric) the time offset\n"
|
||||
" \"connections\": xxxxx, (numeric) the number of connections\n"
|
||||
" \"proxy\": \"host:port\", (string, optional) the proxy used by the server\n"
|
||||
" \"difficulty\": xxxxxx, (numeric) the current difficulty\n"
|
||||
" \"testnet\": true|false, (boolean) if the server is using testnet or not\n"
|
||||
" \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
|
||||
" \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
|
||||
" \"paytxfee\": x.xxxx, (numeric) the transaction fee set in btc\n"
|
||||
" \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n"
|
||||
" \"errors\": \"...\" (string) any error messages\n"
|
||||
"}\n"
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("getinfo", "")
|
||||
+ HelpExampleRpc("getinfo", "")
|
||||
);
|
||||
|
||||
proxyType proxy;
|
||||
GetProxy(NET_IPV4, proxy);
|
||||
|
||||
Object obj;
|
||||
obj.push_back(Pair("version", (int)CLIENT_VERSION));
|
||||
obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
|
||||
#ifdef ENABLE_WALLET
|
||||
if (pwalletMain) {
|
||||
obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
|
||||
obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
|
||||
}
|
||||
#endif
|
||||
obj.push_back(Pair("blocks", (int)chainActive.Height()));
|
||||
obj.push_back(Pair("timeoffset", (boost::int64_t)GetTimeOffset()));
|
||||
obj.push_back(Pair("connections", (int)vNodes.size()));
|
||||
obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string())));
|
||||
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
|
||||
obj.push_back(Pair("testnet", TestNet()));
|
||||
#ifdef ENABLE_WALLET
|
||||
if (pwalletMain) {
|
||||
obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
|
||||
obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
|
||||
}
|
||||
#endif
|
||||
obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
|
||||
#ifdef ENABLE_WALLET
|
||||
if (pwalletMain && pwalletMain->IsCrypted())
|
||||
obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
|
||||
#endif
|
||||
obj.push_back(Pair("errors", GetWarnings("statusbar")));
|
||||
return obj;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,12 @@
|
|||
#include "init.h"
|
||||
#include "net.h"
|
||||
#include "uint256.h"
|
||||
#include "core.h"
|
||||
#include "main.h"
|
||||
#include "keystore.h"
|
||||
#ifdef ENABLE_WALLET
|
||||
#include "wallet.h"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
@ -190,6 +195,7 @@ Value getrawtransaction(const Array& params, bool fHelp)
|
|||
return result;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
Value listunspent(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() > 3)
|
||||
|
@ -303,6 +309,7 @@ Value listunspent(const Array& params, bool fHelp)
|
|||
|
||||
return results;
|
||||
}
|
||||
#endif
|
||||
|
||||
Value createrawtransaction(const Array& params, bool fHelp)
|
||||
{
|
||||
|
@ -508,7 +515,9 @@ Value signrawtransaction(const Array& params, bool fHelp)
|
|||
"this transaction depends on but may not yet be in the block chain.\n"
|
||||
"The third optional argument (may be null) is an array of base58-encoded private\n"
|
||||
"keys that, if given, will be the only keys used to sign the transaction.\n"
|
||||
#ifdef ENABLE_WALLET
|
||||
+ HelpRequiringPassphrase() + "\n"
|
||||
#endif
|
||||
|
||||
"\nArguments:\n"
|
||||
"1. \"hexstring\" (string, required) The transaction hex string\n"
|
||||
|
@ -605,8 +614,10 @@ Value signrawtransaction(const Array& params, bool fHelp)
|
|||
tempKeystore.AddKey(key);
|
||||
}
|
||||
}
|
||||
#ifdef ENABLE_WALLET
|
||||
else
|
||||
EnsureWalletIsUnlocked();
|
||||
#endif
|
||||
|
||||
// Add previous txouts given in the RPC call:
|
||||
if (params.size() > 1 && params[1].type() != null_type)
|
||||
|
@ -662,7 +673,11 @@ Value signrawtransaction(const Array& params, bool fHelp)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
const CKeyStore& keystore = ((fGivenKeys || !pwalletMain) ? tempKeystore : *pwalletMain);
|
||||
#else
|
||||
const CKeyStore& keystore = tempKeystore;
|
||||
#endif
|
||||
|
||||
int nHashType = SIGHASH_ALL;
|
||||
if (params.size() > 3 && params[3].type() != null_type)
|
||||
|
|
|
@ -9,7 +9,10 @@
|
|||
#include "init.h"
|
||||
#include "main.h"
|
||||
#include "util.h"
|
||||
#include "ui_interface.h"
|
||||
#ifdef ENABLE_WALLET
|
||||
#include "wallet.h"
|
||||
#endif
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
|
@ -149,8 +152,10 @@ string CRPCTable::help(string strCommand) const
|
|||
continue;
|
||||
if (strCommand != "" && strMethod != strCommand)
|
||||
continue;
|
||||
#ifdef ENABLE_WALLET
|
||||
if (pcmd->reqWallet && !pwalletMain)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -228,11 +233,26 @@ static const CRPCCommand vRPCCommands[] =
|
|||
{ "getaddednodeinfo", &getaddednodeinfo, true, true, false },
|
||||
{ "getnettotals", &getnettotals, true, true, false },
|
||||
{ "getdifficulty", &getdifficulty, true, false, false },
|
||||
{ "getinfo", &getinfo, true, false, false },
|
||||
{ "getrawmempool", &getrawmempool, true, false, false },
|
||||
{ "getblock", &getblock, false, false, false },
|
||||
{ "getblockhash", &getblockhash, false, false, false },
|
||||
{ "settxfee", &settxfee, false, false, true },
|
||||
{ "getrawtransaction", &getrawtransaction, false, false, false },
|
||||
{ "createrawtransaction", &createrawtransaction, false, false, false },
|
||||
{ "decoderawtransaction", &decoderawtransaction, false, false, false },
|
||||
{ "decodescript", &decodescript, false, false, false },
|
||||
{ "signrawtransaction", &signrawtransaction, false, false, false },
|
||||
{ "sendrawtransaction", &sendrawtransaction, false, false, false },
|
||||
{ "gettxoutsetinfo", &gettxoutsetinfo, true, false, false },
|
||||
{ "gettxout", &gettxout, true, false, false },
|
||||
{ "verifychain", &verifychain, true, false, false },
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
{ "getnetworkhashps", &getnetworkhashps, true, false, false },
|
||||
{ "getgenerate", &getgenerate, true, false, false },
|
||||
{ "setgenerate", &setgenerate, true, true, false },
|
||||
{ "gethashespersec", &gethashespersec, true, false, false },
|
||||
{ "getinfo", &getinfo, true, false, false },
|
||||
{ "getmininginfo", &getmininginfo, true, false, false },
|
||||
{ "getnewaddress", &getnewaddress, true, false, true },
|
||||
{ "getaccountaddress", &getaccountaddress, true, false, true },
|
||||
|
@ -258,9 +278,6 @@ static const CRPCCommand vRPCCommands[] =
|
|||
{ "sendmany", &sendmany, false, false, true },
|
||||
{ "addmultisigaddress", &addmultisigaddress, false, false, true },
|
||||
{ "createmultisig", &createmultisig, true, true , false },
|
||||
{ "getrawmempool", &getrawmempool, true, false, false },
|
||||
{ "getblock", &getblock, false, false, false },
|
||||
{ "getblockhash", &getblockhash, false, false, false },
|
||||
{ "gettransaction", &gettransaction, false, false, true },
|
||||
{ "listtransactions", &listtransactions, false, false, true },
|
||||
{ "listaddressgroupings", &listaddressgroupings, false, false, true },
|
||||
|
@ -268,7 +285,6 @@ static const CRPCCommand vRPCCommands[] =
|
|||
{ "verifymessage", &verifymessage, false, false, false },
|
||||
{ "getwork", &getwork, true, false, true },
|
||||
{ "listaccounts", &listaccounts, false, false, true },
|
||||
{ "settxfee", &settxfee, false, false, true },
|
||||
{ "getblocktemplate", &getblocktemplate, true, false, false },
|
||||
{ "submitblock", &submitblock, false, false, false },
|
||||
{ "listsinceblock", &listsinceblock, false, false, true },
|
||||
|
@ -277,17 +293,9 @@ static const CRPCCommand vRPCCommands[] =
|
|||
{ "importprivkey", &importprivkey, false, false, true },
|
||||
{ "importwallet", &importwallet, false, false, true },
|
||||
{ "listunspent", &listunspent, false, false, true },
|
||||
{ "getrawtransaction", &getrawtransaction, false, false, false },
|
||||
{ "createrawtransaction", &createrawtransaction, false, false, false },
|
||||
{ "decoderawtransaction", &decoderawtransaction, false, false, false },
|
||||
{ "decodescript", &decodescript, false, false, false },
|
||||
{ "signrawtransaction", &signrawtransaction, false, false, false },
|
||||
{ "sendrawtransaction", &sendrawtransaction, false, false, false },
|
||||
{ "gettxoutsetinfo", &gettxoutsetinfo, true, false, false },
|
||||
{ "gettxout", &gettxout, true, false, false },
|
||||
{ "lockunspent", &lockunspent, false, false, true },
|
||||
{ "listlockunspent", &listlockunspent, false, false, true },
|
||||
{ "verifychain", &verifychain, true, false, false },
|
||||
#endif // ENABLE_WALLET
|
||||
};
|
||||
|
||||
CRPCTable::CRPCTable()
|
||||
|
@ -788,8 +796,10 @@ json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_s
|
|||
const CRPCCommand *pcmd = tableRPC[strMethod];
|
||||
if (!pcmd)
|
||||
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found");
|
||||
#ifdef ENABLE_WALLET
|
||||
if (pcmd->reqWallet && !pwalletMain)
|
||||
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
|
||||
#endif
|
||||
|
||||
// Observe safe mode
|
||||
string strWarning = GetWarnings("rpc");
|
||||
|
@ -804,6 +814,7 @@ json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_s
|
|||
{
|
||||
if (pcmd->threadSafe)
|
||||
result = pcmd->actor(params, false);
|
||||
#ifdef ENABLE_WALLET
|
||||
else if (!pwalletMain) {
|
||||
LOCK(cs_main);
|
||||
result = pcmd->actor(params, false);
|
||||
|
@ -811,6 +822,12 @@ json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_s
|
|||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
result = pcmd->actor(params, false);
|
||||
}
|
||||
#else // ENABLE_WALLET
|
||||
else {
|
||||
LOCK(cs_main);
|
||||
result = pcmd->actor(params, false);
|
||||
}
|
||||
#endif // !ENABLE_WALLET
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -820,4 +837,13 @@ json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_s
|
|||
}
|
||||
}
|
||||
|
||||
std::string HelpExampleCli(string methodname, string args){
|
||||
return "> bitcoin-cli " + methodname + " " + args + "\n";
|
||||
}
|
||||
|
||||
std::string HelpExampleRpc(string methodname, string args){
|
||||
return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", "
|
||||
"\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;' http://127.0.0.1:8332/\n";
|
||||
}
|
||||
|
||||
const CRPCTable tableRPC;
|
||||
|
|
|
@ -33,15 +33,6 @@ std::string HelpRequiringPassphrase()
|
|||
: "";
|
||||
}
|
||||
|
||||
std::string HelpExampleCli(string methodname, string args){
|
||||
return "> bitcoin-cli " + methodname + " " + args + "\n";
|
||||
}
|
||||
|
||||
std::string HelpExampleRpc(string methodname, string args){
|
||||
return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", "
|
||||
"\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;' http://127.0.0.1:8332/\n";
|
||||
}
|
||||
|
||||
void EnsureWalletIsUnlocked()
|
||||
{
|
||||
if (pwalletMain->IsLocked())
|
||||
|
@ -75,64 +66,6 @@ string AccountFromValue(const Value& value)
|
|||
return strAccount;
|
||||
}
|
||||
|
||||
Value getinfo(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 0)
|
||||
throw runtime_error(
|
||||
"getinfo\n"
|
||||
"Returns an object containing various state info.\n"
|
||||
"\nResult:\n"
|
||||
"{\n"
|
||||
" \"version\": xxxxx, (numeric) the server version\n"
|
||||
" \"protocolversion\": xxxxx, (numeric) the protocol version\n"
|
||||
" \"walletversion\": xxxxx, (numeric) the wallet version\n"
|
||||
" \"balance\": xxxxxxx, (numeric) the total bitcoin balance of the wallet\n"
|
||||
" \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n"
|
||||
" \"timeoffset\": xxxxx, (numeric) the time offset\n"
|
||||
" \"connections\": xxxxx, (numeric) the number of connections\n"
|
||||
" \"proxy\": \"host:port\", (string, optional) the proxy used by the server\n"
|
||||
" \"difficulty\": xxxxxx, (numeric) the current difficulty\n"
|
||||
" \"testnet\": true|false, (boolean) if the server is using testnet or not\n"
|
||||
" \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
|
||||
" \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
|
||||
" \"paytxfee\": x.xxxx, (numeric) the transaction fee set in btc\n"
|
||||
" \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n"
|
||||
" \"errors\": \"...\" (string) any error messages\n"
|
||||
"}\n"
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("getinfo", "")
|
||||
+ HelpExampleRpc("getinfo", "")
|
||||
);
|
||||
|
||||
proxyType proxy;
|
||||
GetProxy(NET_IPV4, proxy);
|
||||
|
||||
Object obj;
|
||||
obj.push_back(Pair("version", (int)CLIENT_VERSION));
|
||||
obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
|
||||
if (pwalletMain) {
|
||||
obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
|
||||
obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
|
||||
}
|
||||
obj.push_back(Pair("blocks", (int)chainActive.Height()));
|
||||
obj.push_back(Pair("timeoffset", (boost::int64_t)GetTimeOffset()));
|
||||
obj.push_back(Pair("connections", (int)vNodes.size()));
|
||||
obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string())));
|
||||
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
|
||||
obj.push_back(Pair("testnet", TestNet()));
|
||||
if (pwalletMain) {
|
||||
obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
|
||||
obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
|
||||
}
|
||||
obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
|
||||
if (pwalletMain && pwalletMain->IsCrypted())
|
||||
obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
|
||||
obj.push_back(Pair("errors", GetWarnings("statusbar")));
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Value getnewaddress(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() > 1)
|
||||
|
|
|
@ -21,16 +21,25 @@ BUILT_SOURCES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h)
|
|||
# test_bitcoin binary #
|
||||
test_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(TESTDEFS)
|
||||
test_bitcoin_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) $(LIBMEMENV) \
|
||||
$(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(BDB_LIBS)
|
||||
test_bitcoin_SOURCES = accounting_tests.cpp alert_tests.cpp \
|
||||
$(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB)
|
||||
if ENABLE_WALLET
|
||||
test_bitcoin_LDADD += $(LIBBITCOIN_WALLET)
|
||||
endif
|
||||
test_bitcoin_LDADD += $(BDB_LIBS)
|
||||
|
||||
test_bitcoin_SOURCES = alert_tests.cpp \
|
||||
allocator_tests.cpp base32_tests.cpp base58_tests.cpp base64_tests.cpp \
|
||||
bignum_tests.cpp bloom_tests.cpp canonical_tests.cpp checkblock_tests.cpp \
|
||||
Checkpoints_tests.cpp compress_tests.cpp DoS_tests.cpp getarg_tests.cpp \
|
||||
key_tests.cpp miner_tests.cpp mruset_tests.cpp multisig_tests.cpp \
|
||||
key_tests.cpp mruset_tests.cpp multisig_tests.cpp \
|
||||
netbase_tests.cpp pmt_tests.cpp rpc_tests.cpp script_P2SH_tests.cpp \
|
||||
script_tests.cpp serialize_tests.cpp sigopcount_tests.cpp test_bitcoin.cpp \
|
||||
transaction_tests.cpp uint160_tests.cpp uint256_tests.cpp util_tests.cpp \
|
||||
wallet_tests.cpp sighash_tests.cpp $(JSON_TEST_FILES) $(RAW_TEST_FILES)
|
||||
sighash_tests.cpp $(JSON_TEST_FILES) $(RAW_TEST_FILES)
|
||||
|
||||
if ENABLE_WALLET
|
||||
test_bitcoin_SOURCES += accounting_tests.cpp wallet_tests.cpp miner_tests.cpp rpc_wallet_tests.cpp
|
||||
endif
|
||||
|
||||
nodist_test_bitcoin_SOURCES = $(BUILT_SOURCES)
|
||||
|
||||
|
|
|
@ -9,9 +9,7 @@
|
|||
using namespace std;
|
||||
using namespace json_spirit;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(rpc_tests)
|
||||
|
||||
static Array
|
||||
Array
|
||||
createArgs(int nRequired, const char* address1=NULL, const char* address2=NULL)
|
||||
{
|
||||
Array result;
|
||||
|
@ -23,44 +21,7 @@ createArgs(int nRequired, const char* address1=NULL, const char* address2=NULL)
|
|||
return result;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(rpc_addmultisig)
|
||||
{
|
||||
rpcfn_type addmultisig = tableRPC["addmultisigaddress"]->actor;
|
||||
|
||||
// old, 65-byte-long:
|
||||
const char address1Hex[] = "0434e3e09f49ea168c5bbf53f877ff4206923858aab7c7e1df25bc263978107c95e35065a27ef6f1b27222db0ec97e0e895eaca603d3ee0d4c060ce3d8a00286c8";
|
||||
// new, compressed:
|
||||
const char address2Hex[] = "0388c2037017c62240b6b72ac1a2a5f94da790596ebd06177c8572752922165cb4";
|
||||
|
||||
Value v;
|
||||
CBitcoinAddress address;
|
||||
BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex), false));
|
||||
address.SetString(v.get_str());
|
||||
BOOST_CHECK(address.IsValid() && address.IsScript());
|
||||
|
||||
BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex, address2Hex), false));
|
||||
address.SetString(v.get_str());
|
||||
BOOST_CHECK(address.IsValid() && address.IsScript());
|
||||
|
||||
BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(2, address1Hex, address2Hex), false));
|
||||
address.SetString(v.get_str());
|
||||
BOOST_CHECK(address.IsValid() && address.IsScript());
|
||||
|
||||
BOOST_CHECK_THROW(addmultisig(createArgs(0), false), runtime_error);
|
||||
BOOST_CHECK_THROW(addmultisig(createArgs(1), false), runtime_error);
|
||||
BOOST_CHECK_THROW(addmultisig(createArgs(2, address1Hex), false), runtime_error);
|
||||
|
||||
BOOST_CHECK_THROW(addmultisig(createArgs(1, ""), false), runtime_error);
|
||||
BOOST_CHECK_THROW(addmultisig(createArgs(1, "NotAValidPubkey"), false), runtime_error);
|
||||
|
||||
string short1(address1Hex, address1Hex+sizeof(address1Hex)-2); // last byte missing
|
||||
BOOST_CHECK_THROW(addmultisig(createArgs(2, short1.c_str()), false), runtime_error);
|
||||
|
||||
string short2(address1Hex+1, address1Hex+sizeof(address1Hex)); // first byte missing
|
||||
BOOST_CHECK_THROW(addmultisig(createArgs(2, short2.c_str()), false), runtime_error);
|
||||
}
|
||||
|
||||
static Value CallRPC(string args)
|
||||
Value CallRPC(string args)
|
||||
{
|
||||
vector<string> vArgs;
|
||||
boost::split(vArgs, args, boost::is_any_of(" \t"));
|
||||
|
@ -79,34 +40,8 @@ static Value CallRPC(string args)
|
|||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(rpc_wallet)
|
||||
{
|
||||
// Test RPC calls for various wallet statistics
|
||||
Value r;
|
||||
|
||||
BOOST_CHECK_NO_THROW(CallRPC("listunspent"));
|
||||
BOOST_CHECK_THROW(CallRPC("listunspent string"), runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("listunspent 0 string"), runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("listunspent 0 1 not_array"), runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("listunspent 0 1 [] extra"), runtime_error);
|
||||
BOOST_CHECK_NO_THROW(r=CallRPC("listunspent 0 1 []"));
|
||||
BOOST_CHECK(r.get_array().empty());
|
||||
|
||||
BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress"));
|
||||
BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0"));
|
||||
BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress not_int"), runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 not_bool"), runtime_error);
|
||||
BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0 true"));
|
||||
BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 true extra"), runtime_error);
|
||||
|
||||
BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount"));
|
||||
BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0"));
|
||||
BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount not_int"), runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 not_bool"), runtime_error);
|
||||
BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0 true"));
|
||||
BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 true extra"), runtime_error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(rpc_tests)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(rpc_rawparams)
|
||||
{
|
||||
|
|
82
src/test/rpc_wallet_tests.cpp
Normal file
82
src/test/rpc_wallet_tests.cpp
Normal file
|
@ -0,0 +1,82 @@
|
|||
#include "rpcserver.h"
|
||||
#include "rpcclient.h"
|
||||
|
||||
#include "base58.h"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace json_spirit;
|
||||
|
||||
extern Array createArgs(int nRequired, const char* address1=NULL, const char* address2=NULL);
|
||||
extern Value CallRPC(string args);
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(rpc_wallet_tests)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(rpc_addmultisig)
|
||||
{
|
||||
rpcfn_type addmultisig = tableRPC["addmultisigaddress"]->actor;
|
||||
|
||||
// old, 65-byte-long:
|
||||
const char address1Hex[] = "0434e3e09f49ea168c5bbf53f877ff4206923858aab7c7e1df25bc263978107c95e35065a27ef6f1b27222db0ec97e0e895eaca603d3ee0d4c060ce3d8a00286c8";
|
||||
// new, compressed:
|
||||
const char address2Hex[] = "0388c2037017c62240b6b72ac1a2a5f94da790596ebd06177c8572752922165cb4";
|
||||
|
||||
Value v;
|
||||
CBitcoinAddress address;
|
||||
BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex), false));
|
||||
address.SetString(v.get_str());
|
||||
BOOST_CHECK(address.IsValid() && address.IsScript());
|
||||
|
||||
BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex, address2Hex), false));
|
||||
address.SetString(v.get_str());
|
||||
BOOST_CHECK(address.IsValid() && address.IsScript());
|
||||
|
||||
BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(2, address1Hex, address2Hex), false));
|
||||
address.SetString(v.get_str());
|
||||
BOOST_CHECK(address.IsValid() && address.IsScript());
|
||||
|
||||
BOOST_CHECK_THROW(addmultisig(createArgs(0), false), runtime_error);
|
||||
BOOST_CHECK_THROW(addmultisig(createArgs(1), false), runtime_error);
|
||||
BOOST_CHECK_THROW(addmultisig(createArgs(2, address1Hex), false), runtime_error);
|
||||
|
||||
BOOST_CHECK_THROW(addmultisig(createArgs(1, ""), false), runtime_error);
|
||||
BOOST_CHECK_THROW(addmultisig(createArgs(1, "NotAValidPubkey"), false), runtime_error);
|
||||
|
||||
string short1(address1Hex, address1Hex+sizeof(address1Hex)-2); // last byte missing
|
||||
BOOST_CHECK_THROW(addmultisig(createArgs(2, short1.c_str()), false), runtime_error);
|
||||
|
||||
string short2(address1Hex+1, address1Hex+sizeof(address1Hex)); // first byte missing
|
||||
BOOST_CHECK_THROW(addmultisig(createArgs(2, short2.c_str()), false), runtime_error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(rpc_wallet)
|
||||
{
|
||||
// Test RPC calls for various wallet statistics
|
||||
Value r;
|
||||
|
||||
BOOST_CHECK_NO_THROW(CallRPC("listunspent"));
|
||||
BOOST_CHECK_THROW(CallRPC("listunspent string"), runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("listunspent 0 string"), runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("listunspent 0 1 not_array"), runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("listunspent 0 1 [] extra"), runtime_error);
|
||||
BOOST_CHECK_NO_THROW(r=CallRPC("listunspent 0 1 []"));
|
||||
BOOST_CHECK(r.get_array().empty());
|
||||
|
||||
BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress"));
|
||||
BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0"));
|
||||
BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress not_int"), runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 not_bool"), runtime_error);
|
||||
BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0 true"));
|
||||
BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 true extra"), runtime_error);
|
||||
|
||||
BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount"));
|
||||
BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0"));
|
||||
BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount not_int"), runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 not_bool"), runtime_error);
|
||||
BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0 true"));
|
||||
BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 true extra"), runtime_error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
|
@ -7,7 +7,9 @@
|
|||
#include "txdb.h"
|
||||
#include "ui_interface.h"
|
||||
#include "util.h"
|
||||
#ifdef ENABLE_WALLET
|
||||
#include "wallet.h"
|
||||
#endif
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
@ -26,7 +28,9 @@ struct TestingSetup {
|
|||
TestingSetup() {
|
||||
fPrintToDebugger = true; // don't want to write to debug.log file
|
||||
noui_connect();
|
||||
#ifdef ENABLE_WALLET
|
||||
bitdb.MakeMock();
|
||||
#endif
|
||||
pathTemp = GetTempPath() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000)));
|
||||
boost::filesystem::create_directories(pathTemp);
|
||||
mapArgs["-datadir"] = pathTemp.string();
|
||||
|
@ -34,10 +38,12 @@ struct TestingSetup {
|
|||
pcoinsdbview = new CCoinsViewDB(1 << 23, true);
|
||||
pcoinsTip = new CCoinsViewCache(*pcoinsdbview);
|
||||
InitBlockIndex();
|
||||
#ifdef ENABLE_WALLET
|
||||
bool fFirstRun;
|
||||
pwalletMain = new CWallet("wallet.dat");
|
||||
pwalletMain->LoadWallet(fFirstRun);
|
||||
RegisterWallet(pwalletMain);
|
||||
#endif
|
||||
nScriptCheckThreads = 3;
|
||||
for (int i=0; i < nScriptCheckThreads-1; i++)
|
||||
threadGroup.create_thread(&ThreadScriptCheck);
|
||||
|
@ -46,12 +52,16 @@ struct TestingSetup {
|
|||
{
|
||||
threadGroup.interrupt_all();
|
||||
threadGroup.join_all();
|
||||
#ifdef ENABLE_WALLET
|
||||
delete pwalletMain;
|
||||
pwalletMain = NULL;
|
||||
#endif
|
||||
delete pcoinsTip;
|
||||
delete pcoinsdbview;
|
||||
delete pblocktree;
|
||||
#ifdef ENABLE_WALLET
|
||||
bitdb.Flush(true);
|
||||
#endif
|
||||
boost::filesystem::remove_all(pathTemp);
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue