Browse Source

Merge pull request #574 from sipa/dumpprivkey

Dumpprivkey
miguelfreitas
Gavin Andresen 13 years ago
parent
commit
99a289f531
  1. 2
      bitcoin-qt.pro
  2. 53
      src/base58.h
  3. 9
      src/bitcoinrpc.cpp
  4. 2
      src/db.cpp
  5. 117
      src/key.cpp
  6. 119
      src/key.h
  7. 12
      src/keystore.cpp
  8. 59
      src/keystore.h
  9. 4
      src/main.cpp
  10. 10
      src/main.h
  11. 2
      src/makefile.mingw
  12. 2
      src/makefile.osx
  13. 2
      src/makefile.unix
  14. 101
      src/rpcdump.cpp
  15. 62
      src/wallet.cpp
  16. 15
      src/wallet.h

2
bitcoin-qt.pro

@ -148,6 +148,7 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
src/qt/editaddressdialog.cpp \ src/qt/editaddressdialog.cpp \
src/qt/bitcoinaddressvalidator.cpp \ src/qt/bitcoinaddressvalidator.cpp \
src/util.cpp \ src/util.cpp \
src/key.cpp \
src/script.cpp \ src/script.cpp \
src/main.cpp \ src/main.cpp \
src/init.cpp \ src/init.cpp \
@ -173,6 +174,7 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
src/qt/transactionview.cpp \ src/qt/transactionview.cpp \
src/qt/walletmodel.cpp \ src/qt/walletmodel.cpp \
src/bitcoinrpc.cpp \ src/bitcoinrpc.cpp \
src/rpcdump.cpp \
src/qt/overviewpage.cpp \ src/qt/overviewpage.cpp \
src/qt/csvmodelwriter.cpp \ src/qt/csvmodelwriter.cpp \
src/crypter.cpp \ src/crypter.cpp \

53
src/base58.h

@ -18,6 +18,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "bignum.h" #include "bignum.h"
#include "key.h"
static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
@ -257,15 +258,14 @@ public:
class CBitcoinAddress : public CBase58Data class CBitcoinAddress : public CBase58Data
{ {
public: public:
bool SetHash160(const uint160& hash160) void SetHash160(const uint160& hash160)
{ {
SetData(fTestNet ? 111 : 0, &hash160, 20); SetData(fTestNet ? 111 : 0, &hash160, 20);
return true;
} }
bool SetPubKey(const std::vector<unsigned char>& vchPubKey) void SetPubKey(const std::vector<unsigned char>& vchPubKey)
{ {
return SetHash160(Hash160(vchPubKey)); SetHash160(Hash160(vchPubKey));
} }
bool IsValid() const bool IsValid() const
@ -320,4 +320,49 @@ public:
} }
}; };
class CBitcoinSecret : public CBase58Data
{
public:
void SetSecret(const CSecret& vchSecret)
{
SetData(fTestNet ? 239 : 128, &vchSecret[0], vchSecret.size());
}
CSecret GetSecret()
{
CSecret vchSecret;
vchSecret.resize(vchData.size());
memcpy(&vchSecret[0], &vchData[0], vchData.size());
return vchSecret;
}
bool IsValid() const
{
int nExpectedSize = 32;
bool fExpectTestNet = false;
switch(nVersion)
{
case 128:
break;
case 239:
fExpectTestNet = true;
break;
default:
return false;
}
return fExpectTestNet == fTestNet && vchData.size() == nExpectedSize;
}
CBitcoinSecret(const CSecret& vchSecret)
{
SetSecret(vchSecret);
}
CBitcoinSecret()
{
}
};
#endif #endif

9
src/bitcoinrpc.cpp

@ -9,9 +9,11 @@
#include "init.h" #include "init.h"
#undef printf #undef printf
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <boost/filesystem.hpp>
#include <boost/iostreams/concepts.hpp> #include <boost/iostreams/concepts.hpp>
#include <boost/iostreams/stream.hpp> #include <boost/iostreams/stream.hpp>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#ifdef USE_SSL #ifdef USE_SSL
#include <boost/asio/ssl.hpp> #include <boost/asio/ssl.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
@ -41,6 +43,8 @@ static std::string strRPCUserColonPass;
static int64 nWalletUnlockTime; static int64 nWalletUnlockTime;
static CCriticalSection cs_nWalletUnlockTime; static CCriticalSection cs_nWalletUnlockTime;
extern Value dumpprivkey(const Array& params, bool fHelp);
extern Value importprivkey(const Array& params, bool fHelp);
Object JSONRPCError(int code, const string& message) Object JSONRPCError(int code, const string& message)
{ {
@ -596,7 +600,7 @@ Value verifymessage(const Array& params, bool fHelp)
if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig)) if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
return false; return false;
return (key.GetAddress() == addr); return (CBitcoinAddress(key.GetPubKey()) == addr);
} }
@ -1599,7 +1603,6 @@ Value validateaddress(const Array& params, bool fHelp)
return ret; return ret;
} }
Value getwork(const Array& params, bool fHelp) Value getwork(const Array& params, bool fHelp)
{ {
if (fHelp || params.size() > 1) if (fHelp || params.size() > 1)
@ -1847,6 +1850,8 @@ pair<string, rpcfn_type> pCallTable[] =
make_pair("settxfee", &settxfee), make_pair("settxfee", &settxfee),
make_pair("getmemorypool", &getmemorypool), make_pair("getmemorypool", &getmemorypool),
make_pair("listsinceblock", &listsinceblock), make_pair("listsinceblock", &listsinceblock),
make_pair("dumpprivkey", &dumpprivkey),
make_pair("importprivkey", &importprivkey)
}; };
map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0])); map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));

2
src/db.cpp

@ -810,7 +810,7 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
ssKey >> hash; ssKey >> hash;
CWalletTx& wtx = pwallet->mapWallet[hash]; CWalletTx& wtx = pwallet->mapWallet[hash];
ssValue >> wtx; ssValue >> wtx;
wtx.pwallet = pwallet; wtx.BindWallet(pwallet);
if (wtx.GetHash() != hash) if (wtx.GetHash() != hash)
printf("Error in wallet.dat, hash mismatch\n"); printf("Error in wallet.dat, hash mismatch\n");

117
src/key.cpp

@ -0,0 +1,117 @@
// Copyright (c) 2011 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
// Generate a private key from just the secret parameter
int EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
{
int ok = 0;
BN_CTX *ctx = NULL;
EC_POINT *pub_key = NULL;
if (!eckey) return 0;
const EC_GROUP *group = EC_KEY_get0_group(eckey);
if ((ctx = BN_CTX_new()) == NULL)
goto err;
pub_key = EC_POINT_new(group);
if (pub_key == NULL)
goto err;
if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
goto err;
EC_KEY_set_private_key(eckey,priv_key);
EC_KEY_set_public_key(eckey,pub_key);
ok = 1;
err:
if (pub_key)
EC_POINT_free(pub_key);
if (ctx != NULL)
BN_CTX_free(ctx);
return(ok);
}
// Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields
// recid selects which key is recovered
// if check is nonzero, additional checks are performed
int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check)
{
if (!eckey) return 0;
int ret = 0;
BN_CTX *ctx = NULL;
BIGNUM *x = NULL;
BIGNUM *e = NULL;
BIGNUM *order = NULL;
BIGNUM *sor = NULL;
BIGNUM *eor = NULL;
BIGNUM *field = NULL;
EC_POINT *R = NULL;
EC_POINT *O = NULL;
EC_POINT *Q = NULL;
BIGNUM *rr = NULL;
BIGNUM *zero = NULL;
int n = 0;
int i = recid / 2;
const EC_GROUP *group = EC_KEY_get0_group(eckey);
if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; }
BN_CTX_start(ctx);
order = BN_CTX_get(ctx);
if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; }
x = BN_CTX_get(ctx);
if (!BN_copy(x, order)) { ret=-1; goto err; }
if (!BN_mul_word(x, i)) { ret=-1; goto err; }
if (!BN_add(x, x, ecsig->r)) { ret=-1; goto err; }
field = BN_CTX_get(ctx);
if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; }
if (BN_cmp(x, field) >= 0) { ret=0; goto err; }
if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; }
if (check)
{
if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; }
if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; }
}
if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
n = EC_GROUP_get_degree(group);
e = BN_CTX_get(ctx);
if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; }
if (8*msglen > n) BN_rshift(e, e, 8-(n & 7));
zero = BN_CTX_get(ctx);
if (!BN_zero(zero)) { ret=-1; goto err; }
if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; }
rr = BN_CTX_get(ctx);
if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) { ret=-1; goto err; }
sor = BN_CTX_get(ctx);
if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) { ret=-1; goto err; }
eor = BN_CTX_get(ctx);
if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; }
if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; }
if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; }
ret = 1;
err:
if (ctx) {
BN_CTX_end(ctx);
BN_CTX_free(ctx);
}
if (R != NULL) EC_POINT_free(R);
if (O != NULL) EC_POINT_free(O);
if (Q != NULL) EC_POINT_free(Q);
return ret;
}

119
src/key.h

@ -14,7 +14,6 @@
#include "serialize.h" #include "serialize.h"
#include "uint256.h" #include "uint256.h"
#include "base58.h"
// secp160k1 // secp160k1
// const unsigned int PRIVATE_KEY_SIZE = 192; // const unsigned int PRIVATE_KEY_SIZE = 192;
@ -39,116 +38,8 @@
// see www.keylength.com // see www.keylength.com
// script supports up to 75 for single byte push // script supports up to 75 for single byte push
// Generate a private key from just the secret parameter int extern EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key);
int static inline EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key) int extern ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check);
{
int ok = 0;
BN_CTX *ctx = NULL;
EC_POINT *pub_key = NULL;
if (!eckey) return 0;
const EC_GROUP *group = EC_KEY_get0_group(eckey);
if ((ctx = BN_CTX_new()) == NULL)
goto err;
pub_key = EC_POINT_new(group);
if (pub_key == NULL)
goto err;
if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
goto err;
EC_KEY_set_private_key(eckey,priv_key);
EC_KEY_set_public_key(eckey,pub_key);
ok = 1;
err:
if (pub_key)
EC_POINT_free(pub_key);
if (ctx != NULL)
BN_CTX_free(ctx);
return(ok);
}
// Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields
// recid selects which key is recovered
// if check is nonzero, additional checks are performed
int static inline ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check)
{
if (!eckey) return 0;
int ret = 0;
BN_CTX *ctx = NULL;
BIGNUM *x = NULL;
BIGNUM *e = NULL;
BIGNUM *order = NULL;
BIGNUM *sor = NULL;
BIGNUM *eor = NULL;
BIGNUM *field = NULL;
EC_POINT *R = NULL;
EC_POINT *O = NULL;
EC_POINT *Q = NULL;
BIGNUM *rr = NULL;
BIGNUM *zero = NULL;
int n = 0;
int i = recid / 2;
const EC_GROUP *group = EC_KEY_get0_group(eckey);
if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; }
BN_CTX_start(ctx);
order = BN_CTX_get(ctx);
if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; }
x = BN_CTX_get(ctx);
if (!BN_copy(x, order)) { ret=-1; goto err; }
if (!BN_mul_word(x, i)) { ret=-1; goto err; }
if (!BN_add(x, x, ecsig->r)) { ret=-1; goto err; }
field = BN_CTX_get(ctx);
if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; }
if (BN_cmp(x, field) >= 0) { ret=0; goto err; }
if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; }
if (check)
{
if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; }
if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; }
}
if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
n = EC_GROUP_get_degree(group);
e = BN_CTX_get(ctx);
if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; }
if (8*msglen > n) BN_rshift(e, e, 8-(n & 7));
zero = BN_CTX_get(ctx);
if (!BN_zero(zero)) { ret=-1; goto err; }
if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; }
rr = BN_CTX_get(ctx);
if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) { ret=-1; goto err; }
sor = BN_CTX_get(ctx);
if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) { ret=-1; goto err; }
eor = BN_CTX_get(ctx);
if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; }
if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; }
if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; }
ret = 1;
err:
if (ctx) {
BN_CTX_end(ctx);
BN_CTX_free(ctx);
}
if (R != NULL) EC_POINT_free(R);
if (O != NULL) EC_POINT_free(O);
if (Q != NULL) EC_POINT_free(Q);
return ret;
}
class key_error : public std::runtime_error class key_error : public std::runtime_error
{ {
@ -381,12 +272,6 @@ public:
return false; return false;
return true; return true;
} }
// Get the address corresponding to this key
CBitcoinAddress GetAddress() const
{
return CBitcoinAddress(GetPubKey());
}
}; };
#endif #endif

12
src/keystore.cpp

@ -29,7 +29,7 @@ bool CKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned c
bool CBasicKeyStore::AddKey(const CKey& key) bool CBasicKeyStore::AddKey(const CKey& key)
{ {
CRITICAL_BLOCK(cs_KeyStore) CRITICAL_BLOCK(cs_KeyStore)
mapKeys[key.GetAddress()] = key.GetSecret(); mapKeys[CBitcoinAddress(key.GetPubKey())] = key.GetSecret();
return true; return true;
} }
@ -116,23 +116,19 @@ bool CCryptoKeyStore::AddCryptedKey(const std::vector<unsigned char> &vchPubKey,
return true; return true;
} }
bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const bool CCryptoKeyStore::GetSecret(const CBitcoinAddress &address, CSecret& vchSecretOut) const
{ {
CRITICAL_BLOCK(cs_KeyStore) CRITICAL_BLOCK(cs_KeyStore)
{ {
if (!IsCrypted()) if (!IsCrypted())
return CBasicKeyStore::GetKey(address, keyOut); return CBasicKeyStore::GetSecret(address, vchSecretOut);
CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address); CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
if (mi != mapCryptedKeys.end()) if (mi != mapCryptedKeys.end())
{ {
const std::vector<unsigned char> &vchPubKey = (*mi).second.first; const std::vector<unsigned char> &vchPubKey = (*mi).second.first;
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second; const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
CSecret vchSecret; return DecryptSecret(vMasterKey, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecretOut);
if (!DecryptSecret(vMasterKey, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecret))
return false;
keyOut.SetSecret(vchSecret);
return true;
} }
} }
return false; return false;

59
src/keystore.h

@ -19,17 +19,28 @@ public:
// Check whether a key corresponding to a given address is present in the store. // Check whether a key corresponding to a given address is present in the store.
virtual bool HaveKey(const CBitcoinAddress &address) const =0; virtual bool HaveKey(const CBitcoinAddress &address) const =0;
virtual bool GetKey(const CBitcoinAddress &address, CKey& keyOut) const
// Retrieve a key corresponding to a given address from the store. {
// Return true if succesful. CSecret vchSecret;
virtual bool GetKey(const CBitcoinAddress &address, CKey& keyOut) const =0; if (!GetSecret(address, vchSecret))
return false;
// Retrieve only the public key corresponding to a given address. if (!keyOut.SetSecret(vchSecret))
// This may succeed even if GetKey fails (e.g., encrypted wallets) return false;
return true;
}
virtual void GetKeys(std::set<CBitcoinAddress> &setAddress) const =0;
virtual bool GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const; virtual bool GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const;
// Generate a new key, and add it to the store // Generate a new key, and add it to the store
virtual std::vector<unsigned char> GenerateNewKey(); virtual std::vector<unsigned char> GenerateNewKey();
virtual bool GetSecret(const CBitcoinAddress &address, CSecret& vchSecret) const
{
CKey key;
if (!GetKey(address, key))
return false;
vchSecret = key.GetSecret();
return true;
}
}; };
typedef std::map<CBitcoinAddress, CSecret> KeyMap; typedef std::map<CBitcoinAddress, CSecret> KeyMap;
@ -49,14 +60,27 @@ public:
result = (mapKeys.count(address) > 0); result = (mapKeys.count(address) > 0);
return result; return result;
} }
bool GetKey(const CBitcoinAddress &address, CKey& keyOut) const void GetKeys(std::set<CBitcoinAddress> &setAddress) const
{
setAddress.clear();
CRITICAL_BLOCK(cs_KeyStore)
{
KeyMap::const_iterator mi = mapKeys.begin();
while (mi != mapKeys.end())
{
setAddress.insert((*mi).first);
mi++;
}
}
}
bool GetSecret(const CBitcoinAddress &address, CSecret &vchSecret) const
{ {
CRITICAL_BLOCK(cs_KeyStore) CRITICAL_BLOCK(cs_KeyStore)
{ {
KeyMap::const_iterator mi = mapKeys.find(address); KeyMap::const_iterator mi = mapKeys.find(address);
if (mi != mapKeys.end()) if (mi != mapKeys.end())
{ {
keyOut.SetSecret((*mi).second); vchSecret = (*mi).second;
return true; return true;
} }
} }
@ -131,8 +155,23 @@ public:
} }
return false; return false;
} }
bool GetKey(const CBitcoinAddress &address, CKey& keyOut) const; bool GetSecret(const CBitcoinAddress &address, CSecret& vchSecret) const;
bool GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const; bool GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const;
void GetKeys(std::set<CBitcoinAddress> &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++;
}
}
}; };
#endif #endif

4
src/main.cpp

@ -521,7 +521,7 @@ bool CTransaction::RemoveFromMemoryPool()
int CMerkleTx::GetDepthInMainChain(int& nHeightRet) const int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const
{ {
if (hashBlock == 0 || nIndex == -1) if (hashBlock == 0 || nIndex == -1)
return 0; return 0;
@ -542,7 +542,7 @@ int CMerkleTx::GetDepthInMainChain(int& nHeightRet) const
fMerkleVerified = true; fMerkleVerified = true;
} }
nHeightRet = pindex->nHeight; pindexRet = pindex;
return pindexBest->nHeight - pindex->nHeight + 1; return pindexBest->nHeight - pindex->nHeight + 1;
} }

10
src/main.h

@ -699,8 +699,8 @@ public:
int SetMerkleBranch(const CBlock* pblock=NULL); int SetMerkleBranch(const CBlock* pblock=NULL);
int GetDepthInMainChain(int& nHeightRet) const; int GetDepthInMainChain(CBlockIndex* &pindexRet) const;
int GetDepthInMainChain() const { int nHeight; return GetDepthInMainChain(nHeight); } int GetDepthInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); }
bool IsInMainChain() const { return GetDepthInMainChain() > 0; } bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
int GetBlocksToMaturity() const; int GetBlocksToMaturity() const;
bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true); bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true);
@ -762,6 +762,7 @@ public:
return !(a == b); return !(a == b);
} }
int GetDepthInMainChain() const; int GetDepthInMainChain() const;
}; };
@ -1267,6 +1268,11 @@ public:
Set((*mi).second); Set((*mi).second);
} }
CBlockLocator(const std::vector<uint256>& vHaveIn)
{
vHave = vHaveIn;
}
IMPLEMENT_SERIALIZE IMPLEMENT_SERIALIZE
( (
if (!(nType & SER_GETHASH)) if (!(nType & SER_GETHASH))

2
src/makefile.mingw

@ -61,6 +61,7 @@ LIBS += -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell
OBJS= \ OBJS= \
obj/checkpoints.o \ obj/checkpoints.o \
obj/crypter.o \ obj/crypter.o \
obj/key.o \
obj/db.o \ obj/db.o \
obj/init.o \ obj/init.o \
obj/irc.o \ obj/irc.o \
@ -69,6 +70,7 @@ OBJS= \
obj/net.o \ obj/net.o \
obj/protocol.o \ obj/protocol.o \
obj/bitcoinrpc.o \ obj/bitcoinrpc.o \
obj/rpcdump.o \
obj/script.o \ obj/script.o \
obj/util.o \ obj/util.o \
obj/wallet.o obj/wallet.o

2
src/makefile.osx vendored

@ -72,6 +72,7 @@ HEADERS = \
OBJS= \ OBJS= \
obj/checkpoints.o \ obj/checkpoints.o \
obj/crypter.o \ obj/crypter.o \
obj/key.o \
obj/db.o \ obj/db.o \
obj/init.o \ obj/init.o \
obj/irc.o \ obj/irc.o \
@ -80,6 +81,7 @@ OBJS= \
obj/net.o \ obj/net.o \
obj/protocol.o \ obj/protocol.o \
obj/bitcoinrpc.o \ obj/bitcoinrpc.o \
obj/rpcdump.o \
obj/script.o \ obj/script.o \
obj/util.o \ obj/util.o \
obj/wallet.o obj/wallet.o

2
src/makefile.unix

@ -110,6 +110,7 @@ HEADERS = \
OBJS= \ OBJS= \
obj/checkpoints.o \ obj/checkpoints.o \
obj/crypter.o \ obj/crypter.o \
obj/key.o \
obj/db.o \ obj/db.o \
obj/init.o \ obj/init.o \
obj/irc.o \ obj/irc.o \
@ -118,6 +119,7 @@ OBJS= \
obj/net.o \ obj/net.o \
obj/protocol.o \ obj/protocol.o \
obj/bitcoinrpc.o \ obj/bitcoinrpc.o \
obj/rpcdump.o \
obj/script.o \ obj/script.o \
obj/util.o \ obj/util.o \
obj/wallet.o obj/wallet.o

101
src/rpcdump.cpp

@ -0,0 +1,101 @@
// Copyright (c) 2011 Bitcoin Developers
// 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"
#include "init.h" // for pwalletMain
#include "bitcoinrpc.h"
// #include <boost/asio.hpp>
// #include <boost/iostreams/concepts.hpp>
// #include <boost/iostreams/stream.hpp>
#include <boost/lexical_cast.hpp>
// #ifdef USE_SSL
// #include <boost/asio/ssl.hpp>
// typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
// #endif
// #include <boost/xpressive/xpressive_dynamic.hpp>
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_writer_template.h"
#include "json/json_spirit_utils.h"
#define printf OutputDebugStringF
// using namespace boost::asio;
using namespace json_spirit;
using namespace std;
extern Object JSONRPCError(int code, const string& message);
class CTxDump
{
public:
CBlockIndex *pindex;
int64 nValue;
bool fSpent;
CWalletTx* ptx;
int nOut;
CTxDump(CWalletTx* ptx = NULL, int nOut = -1)
{
pindex = NULL;
nValue = 0;
fSpent = false;
this->ptx = ptx;
this->nOut = nOut;
}
};
Value importprivkey(const Array& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
"importprivkey <bitcoinprivkey> [label]\n"
"Adds a private key (as returned by dumpprivkey) to your wallet.");
string strSecret = params[0].get_str();
string strLabel = "";
if (params.size() > 1)
strLabel = params[1].get_str();
CBitcoinSecret vchSecret;
bool fGood = vchSecret.SetString(strSecret);
if (!fGood) throw JSONRPCError(-5,"Invalid private key");
CKey key;
key.SetSecret(vchSecret.GetSecret());
CBitcoinAddress vchAddress = CBitcoinAddress(key.GetPubKey());
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(pwalletMain->cs_wallet)
{
pwalletMain->MarkDirty();
pwalletMain->SetAddressBookName(vchAddress, strLabel);
if (!pwalletMain->AddKey(key))
throw JSONRPCError(-4,"Error adding key to wallet");
pwalletMain->ScanForWalletTransactions(pindexGenesisBlock, true);
pwalletMain->ReacceptWalletTransactions();
}
MainFrameRepaint();
return Value::null;
}
Value dumpprivkey(const Array& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
"dumpprivkey <bitcoinaddress>\n"
"Reveals the private key corresponding to <bitcoinaddress>.");
string strAddress = params[0].get_str();
CBitcoinAddress address;
if (!address.SetString(strAddress))
throw JSONRPCError(-5, "Invalid bitcoin address");
CSecret vchSecret;
if (!pwalletMain->GetSecret(address, vchSecret))
throw JSONRPCError(-4,"Private key for address " + strAddress + " is not known");
return CBitcoinSecret(vchSecret).ToString();
}

62
src/wallet.cpp

@ -224,6 +224,15 @@ void CWallet::WalletUpdateSpent(const CTransaction &tx)
} }
} }
void CWallet::MarkDirty()
{
CRITICAL_BLOCK(cs_wallet)
{
BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
item.second.MarkDirty();
}
}
bool CWallet::AddToWallet(const CWalletTx& wtxIn) bool CWallet::AddToWallet(const CWalletTx& wtxIn)
{ {
uint256 hash = wtxIn.GetHash(); uint256 hash = wtxIn.GetHash();
@ -232,7 +241,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn)
// Inserts only if not already there, returns tx inserted or tx found // Inserts only if not already there, returns tx inserted or tx found
pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn)); pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
CWalletTx& wtx = (*ret.first).second; CWalletTx& wtx = (*ret.first).second;
wtx.pwallet = this; wtx.BindWallet(this);
bool fInsertedNew = ret.second; bool fInsertedNew = ret.second;
if (fInsertedNew) if (fInsertedNew)
wtx.nTimeReceived = GetAdjustedTime(); wtx.nTimeReceived = GetAdjustedTime();
@ -299,7 +308,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn)
// Add a transaction to the wallet, or update it. // Add a transaction to the wallet, or update it.
// pblock is optional, but should be provided if the transaction is known to be in a block. // pblock is optional, but should be provided if the transaction is known to be in a block.
// If fUpdate is true, existing transactions will be updated. // If fUpdate is true, existing transactions will be updated.
bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate) bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate, bool fFindBlock)
{ {
uint256 hash = tx.GetHash(); uint256 hash = tx.GetHash();
CRITICAL_BLOCK(cs_wallet) CRITICAL_BLOCK(cs_wallet)
@ -586,6 +595,15 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
return ret; return ret;
} }
int CWallet::ScanForWalletTransaction(const uint256& hashTx)
{
CTransaction tx;
tx.ReadFromDisk(COutPoint(hashTx, 0));
if (AddToWalletIfInvolvingMe(tx, NULL, true, true))
return 1;
return 0;
}
void CWallet::ReacceptWalletTransactions() void CWallet::ReacceptWalletTransactions()
{ {
CTxDB txdb("r"); CTxDB txdb("r");
@ -924,7 +942,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CW
if (vecSend.empty() || nValue < 0) if (vecSend.empty() || nValue < 0)
return false; return false;
wtxNew.pwallet = this; wtxNew.BindWallet(this);
CRITICAL_BLOCK(cs_main) CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_wallet) CRITICAL_BLOCK(cs_wallet)
@ -1062,7 +1080,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
BOOST_FOREACH(const CTxIn& txin, wtxNew.vin) BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
{ {
CWalletTx &coin = mapWallet[txin.prevout.hash]; CWalletTx &coin = mapWallet[txin.prevout.hash];
coin.pwallet = this; coin.BindWallet(this);
coin.MarkSpent(txin.prevout.n); coin.MarkSpent(txin.prevout.n);
coin.WriteToDisk(); coin.WriteToDisk();
vWalletUpdated.push_back(coin.GetHash()); vWalletUpdated.push_back(coin.GetHash());
@ -1325,6 +1343,22 @@ void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
} }
} }
int64 CWallet::AddReserveKey(const CKeyPool& keypool)
{
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_wallet)
{
CWalletDB walletdb(strWalletFile);
int64 nIndex = 1 + *(--setKeyPool.end());
if (!walletdb.WritePool(nIndex, keypool))
throw runtime_error("AddReserveKey() : writing added key failed");
setKeyPool.insert(nIndex);
return nIndex;
}
return -1;
}
void CWallet::KeepKey(int64 nIndex) void CWallet::KeepKey(int64 nIndex)
{ {
// Remove from key pool // Remove from key pool
@ -1413,3 +1447,23 @@ void CReserveKey::ReturnKey()
vchPubKey.clear(); vchPubKey.clear();
} }
void CWallet::GetAllReserveAddresses(set<CBitcoinAddress>& setAddress)
{
setAddress.clear();
CWalletDB walletdb(strWalletFile);
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_wallet)
BOOST_FOREACH(const int64& id, setKeyPool)
{
CKeyPool keypool;
if (!walletdb.ReadPool(id, keypool))
throw runtime_error("GetAllReserveKeyHashes() : read failed");
CBitcoinAddress address(keypool.vchPubKey);
assert(!keypool.vchPubKey.empty());
if (!HaveKey(address))
throw runtime_error("GetAllReserveKeyHashes() : unknown key in key pool");
setAddress.insert(address);
}
}

15
src/wallet.h

@ -74,11 +74,13 @@ public:
bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase); bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
bool EncryptWallet(const SecureString& strWalletPassphrase); bool EncryptWallet(const SecureString& strWalletPassphrase);
void MarkDirty();
bool AddToWallet(const CWalletTx& wtxIn); bool AddToWallet(const CWalletTx& wtxIn);
bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate = false); bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate = false, bool fFindBlock = false);
bool EraseFromWallet(uint256 hash); bool EraseFromWallet(uint256 hash);
void WalletUpdateSpent(const CTransaction& prevout); void WalletUpdateSpent(const CTransaction& prevout);
int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
int ScanForWalletTransaction(const uint256& hashTx);
void ReacceptWalletTransactions(); void ReacceptWalletTransactions();
void ResendWalletTransactions(); void ResendWalletTransactions();
int64 GetBalance() const; int64 GetBalance() const;
@ -92,11 +94,13 @@ public:
bool NewKeyPool(); bool NewKeyPool();
bool TopUpKeyPool(); bool TopUpKeyPool();
int64 AddReserveKey(const CKeyPool& keypool);
void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool); void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool);
void KeepKey(int64 nIndex); void KeepKey(int64 nIndex);
void ReturnKey(int64 nIndex); void ReturnKey(int64 nIndex);
bool GetKeyFromPool(std::vector<unsigned char> &key, bool fAllowReuse=true); bool GetKeyFromPool(std::vector<unsigned char> &key, bool fAllowReuse=true);
int64 GetOldestKeyPoolTime(); int64 GetOldestKeyPoolTime();
void GetAllReserveAddresses(std::set<CBitcoinAddress>& setAddress);
bool IsMine(const CTxIn& txin) const; bool IsMine(const CTxIn& txin) const;
int64 GetDebit(const CTxIn& txin) const; int64 GetDebit(const CTxIn& txin) const;
@ -243,9 +247,10 @@ public:
// //
class CWalletTx : public CMerkleTx class CWalletTx : public CMerkleTx
{ {
public: private:
const CWallet* pwallet; const CWallet* pwallet;
public:
std::vector<CMerkleTx> vtxPrev; std::vector<CMerkleTx> vtxPrev;
std::map<std::string, std::string> mapValue; std::map<std::string, std::string> mapValue;
std::vector<std::pair<std::string, std::string> > vOrderForm; std::vector<std::pair<std::string, std::string> > vOrderForm;
@ -389,6 +394,12 @@ public:
fChangeCached = false; fChangeCached = false;
} }
void BindWallet(CWallet *pwalletIn)
{
pwallet = pwalletIn;
MarkDirty();
}
void MarkSpent(unsigned int nOut) void MarkSpent(unsigned int nOut)
{ {
if (nOut >= vout.size()) if (nOut >= vout.size())

Loading…
Cancel
Save