diff -uNr a/src/base58.h b/src/base58.h --- a/src/base58.h e4fa4700d17d7da955e3ee980c4a4315e44655dafdec0a4657278e174fa92a187de81c121d30b85a86fd0fe4334867ca73090142c58a3d51083f4ebe7dd4b35c +++ b/src/base58.h 857443d49370c92511e3762aca5d5c8d8b9e178d362affd84add07ac54d3ab1ab88b13980f9639b7be703aa440b5d536c2eab515870f3106238e589d9d127401 @@ -18,6 +18,7 @@ #include #include #include "bignum.h" +#include "key.h" static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; @@ -315,4 +316,52 @@ } }; + +/** A base58-encoded secret key */ +class CBitcoinSecret : public CBase58Data +{ +public: + void SetSecret(const CSecret& vchSecret) + { + assert(vchSecret.size() == 32); + SetData(128, &vchSecret[0], vchSecret.size()); + } + + CSecret GetSecret() + { + CSecret vchSecret; + vchSecret.resize(32); + memcpy(&vchSecret[0], &vchData[0], 32); + return vchSecret; + } + + bool IsValid() const + { + bool fExpectTestNet = false; + switch(nVersion) + { + case 128: + break; + + case 239: + fExpectTestNet = true; + break; + + default: + return false; + } + return (vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1)); + } + + CBitcoinSecret(const CSecret& vchSecret) + { + SetSecret(vchSecret); + } + + CBitcoinSecret() + { + } +}; + + #endif diff -uNr a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp --- a/src/bitcoinrpc.cpp ede2e19dd0ce3d03f54689cbeda30b4b36152f7e532b3d34f0f8c55bb292f7d25c149b88162d96a8208997237a32566d0e555aa7105bfed8175983d80ad892e6 +++ b/src/bitcoinrpc.cpp 2612a5b16a1e14275be2737eb32beb02f89c355d5309b6d2e2e7a75c38603928fc85ecd4c6a03c91bb347247643df6fcbaae60eb7ecc477072ffe3bcdb7a42b0 @@ -7,6 +7,7 @@ #include "db.h" #include "net.h" #include "init.h" +#include "util.h" #undef printf #include #include @@ -584,7 +585,8 @@ if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig)) return false; - return (key.GetAddress() == addr); + // return (key.GetAddress() == addr); + return (CBitcoinAddress(key.GetPubKey()) == addr); } @@ -1838,6 +1840,62 @@ } // ... but will return 'false' if we already have the block. +Value importprivkey(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "importprivkey [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; + CSecret secret = vchSecret.GetSecret(); + key.SetSecret(secret); + 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 \n" + "Reveals the private key corresponding to ."); + + 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(); +} // // Call Table @@ -1887,6 +1945,8 @@ make_pair("listsinceblock", &listsinceblock), make_pair("dumpblock", &dumpblock), make_pair("eatblock", &eatblock), + make_pair("importprivkey", &importprivkey), + make_pair("dumpprivkey", &dumpprivkey), }; map mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0])); diff -uNr a/src/key.h b/src/key.h --- a/src/key.h 6b2389129dec411d013d754eaebc169a23f60b2169dc41cced21248a603ced46dfdc64e016c082a154af87784049333be75c91fb08265306a3bdc2bc0af2e6c5 +++ b/src/key.h 101a99d2cbc7a18eff4ea341667c836afb49cabc104797869a168ac63c04ffa5b93cb90ae9091266e09dd5563c9a8bbbd92a69c6d2045f68058d848fd938c551 @@ -14,7 +14,6 @@ #include "serialize.h" #include "uint256.h" -#include "base58.h" // secp160k1 // const unsigned int PRIVATE_KEY_SIZE = 192; @@ -386,10 +385,10 @@ } // Get the address corresponding to this key - CBitcoinAddress GetAddress() const - { - return CBitcoinAddress(GetPubKey()); - } + // CBitcoinAddress GetAddress() const + // { + // return CBitcoinAddress(GetPubKey()); + // } bool IsValid() { diff -uNr a/src/keystore.cpp b/src/keystore.cpp --- a/src/keystore.cpp d11a428a6fd4d8431cce1195406dff39b0a585a0f44c6156a07a33e02c61d711220747b25bf9c341e88deae60719c1ddeb03df016f7374b966b3a0b830e6f98a +++ b/src/keystore.cpp ee0c9b5d5d154ce9cffcf05b58cd90f7f4ba864417b7e34d701040245f7fd2a0a4c5a172574ee0bdc9ebf0edfe273d5ce427473207a762c4ac42a3331b77f1f1 @@ -29,7 +29,8 @@ bool CBasicKeyStore::AddKey(const CKey& key) { CRITICAL_BLOCK(cs_KeyStore) - mapKeys[key.GetAddress()] = key.GetSecret(); + // mapKeys[key.GetAddress()] = key.GetSecret(); + mapKeys[CBitcoinAddress(key.GetPubKey())] = key.GetSecret(); return true; } diff -uNr a/src/keystore.h b/src/keystore.h --- a/src/keystore.h 247c94ea309f95ddc3b90dcd41dd9212bd5269e8772816bb272a1152422cc1c50bead6370495043a9abc924e119c926d55ecd7f39d1022c7d4eb50718188a641 +++ b/src/keystore.h c5de591c414d332c3a75e7df5497c4eff2a38b559534f409f1f73f7dae03faba62ca9b83921889b3454fb3833f6a11de1f17a341dd81d4e661348a458eced528 @@ -27,6 +27,15 @@ // Retrieve only the public key corresponding to a given address. // This may succeed even if GetKey fails (e.g., encrypted wallets) virtual bool GetPubKey(const CBitcoinAddress &address, std::vector& vchPubKeyOut) const; + + virtual bool GetSecret(const CBitcoinAddress &address, CSecret& vchSecret) const + { + CKey key; + if (!GetKey(address, key)) + return false; + vchSecret = key.GetSecret(); + return true; + } // Generate a new key, and add it to the store virtual std::vector GenerateNewKey(); diff -uNr a/src/wallet.cpp b/src/wallet.cpp --- a/src/wallet.cpp bdc4fc472be4a86fb91fa69368faace04414fdeee5b8c82795e31d37e21581b973caf7f3e9ccc27d487944a5782e3b59615180eab87c8b3e81242901f3039e4d +++ b/src/wallet.cpp 5215203ab6bf6d76003d6e82b3c54145fb5f59b41af5b88d72d315e0723fea8e1313894707ec159d2303a22109b1d8961aa822ae2dd45416bd00e440832f6ee3 @@ -224,6 +224,15 @@ } } +void CWallet::MarkDirty() +{ + CRITICAL_BLOCK(cs_wallet) + { + BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet) + item.second.MarkDirty(); + } +} + bool CWallet::AddToWallet(const CWalletTx& wtxIn) { uint256 hash = wtxIn.GetHash(); diff -uNr a/src/wallet.h b/src/wallet.h --- a/src/wallet.h 86f5e1ca584e6aa01b956278ea06eff4f79b58ca386c490fe605384923f90fcc710fd6bf2f14926d5dfd43e17fc5655a0150b32bc750f05506baf439255c8e30 +++ b/src/wallet.h e99f1c98e8619088d9ec26e6334e58316381f55fa449a510a6595d850302f2c3c250853e2637e4c28c223fcb73e13f7bf74ca2d5c866aff849d6bda6d601483f @@ -73,6 +73,7 @@ bool Unlock(const SecureString& strWalletPassphrase); bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase); bool EncryptWallet(const SecureString& strWalletPassphrase); + void MarkDirty(); bool AddToWallet(const CWalletTx& wtxIn); bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate = false);