Browse Source
This introduces two new source files, keystore.cpp and wallet.cpp with corresponding headers. Code is moved from main and db, in a preparation for a follow-up commit which introduces the classes CWallet and CKeyStore.miguelfreitas
Pieter Wuille
14 years ago
16 changed files with 1735 additions and 1690 deletions
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2009-2011 Satoshi Nakamoto & 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 "db.h" |
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// mapKeys
|
||||
//
|
||||
|
||||
std::vector<unsigned char> GenerateNewKey() |
||||
{ |
||||
RandAddSeedPerfmon(); |
||||
CKey key; |
||||
key.MakeNewKey(); |
||||
if (!AddKey(key)) |
||||
throw std::runtime_error("GenerateNewKey() : AddKey failed"); |
||||
return key.GetPubKey(); |
||||
} |
||||
|
||||
bool AddKey(const CKey& key) |
||||
{ |
||||
CRITICAL_BLOCK(cs_mapKeys) |
||||
{ |
||||
mapKeys[key.GetPubKey()] = key.GetPrivKey(); |
||||
mapPubKeys[Hash160(key.GetPubKey())] = key.GetPubKey(); |
||||
} |
||||
return CWalletDB().WriteKey(key.GetPubKey(), key.GetPrivKey()); |
||||
} |
@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
|
||||
// Copyright (c) 2009-2011 Satoshi Nakamoto & Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_KEYSTORE_H |
||||
#define BITCOIN_KEYSTORE_H |
||||
|
||||
bool AddKey(const CKey& key); |
||||
std::vector<unsigned char> GenerateNewKey(); |
||||
|
||||
#endif |
@ -0,0 +1,441 @@
@@ -0,0 +1,441 @@
|
||||
// Copyright (c) 2009-2011 Satoshi Nakamoto & Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_WALLET_H |
||||
#define BITCOIN_WALLET_H |
||||
|
||||
#include "bignum.h" |
||||
#include "script.h" |
||||
|
||||
class CWalletTx; |
||||
class CReserveKey; |
||||
class CWalletDB; |
||||
|
||||
extern std::map<uint256, CWalletTx> mapWallet; |
||||
extern std::vector<uint256> vWalletUpdated; |
||||
extern CCriticalSection cs_mapWallet; |
||||
|
||||
extern std::map<uint256, int> mapRequestCount; |
||||
extern CCriticalSection cs_mapRequestCount; |
||||
|
||||
extern std::map<std::string, std::string> mapAddressBook; |
||||
extern CCriticalSection cs_mapAddressBook; |
||||
|
||||
extern std::vector<unsigned char> vchDefaultKey; |
||||
extern CKey keyUser; |
||||
|
||||
bool AddToWallet(const CWalletTx& wtxIn); |
||||
bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate = false); |
||||
bool EraseFromWallet(uint256 hash); |
||||
void WalletUpdateSpent(const COutPoint& prevout); |
||||
int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); |
||||
void ReacceptWalletTransactions(); |
||||
void ResendWalletTransactions(); |
||||
int64 GetBalance(); |
||||
bool CreateTransaction(const std::vector<std::pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet); |
||||
bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet); |
||||
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey); |
||||
bool BroadcastTransaction(CWalletTx& wtxNew); |
||||
std::string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false); |
||||
std::string SendMoneyToBitcoinAddress(std::string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false); |
||||
|
||||
|
||||
|
||||
//
|
||||
// A transaction with a bunch of additional info that only the owner cares
|
||||
// about. It includes any unrecorded transactions needed to link it back
|
||||
// to the block chain.
|
||||
//
|
||||
class CWalletTx : public CMerkleTx |
||||
{ |
||||
public: |
||||
std::vector<CMerkleTx> vtxPrev; |
||||
std::map<std::string, std::string> mapValue; |
||||
std::vector<std::pair<std::string, std::string> > vOrderForm; |
||||
unsigned int fTimeReceivedIsTxTime; |
||||
unsigned int nTimeReceived; // time received by this node
|
||||
char fFromMe; |
||||
std::string strFromAccount; |
||||
std::vector<char> vfSpent; |
||||
|
||||
// memory only
|
||||
mutable char fDebitCached; |
||||
mutable char fCreditCached; |
||||
mutable char fAvailableCreditCached; |
||||
mutable char fChangeCached; |
||||
mutable int64 nDebitCached; |
||||
mutable int64 nCreditCached; |
||||
mutable int64 nAvailableCreditCached; |
||||
mutable int64 nChangeCached; |
||||
|
||||
// memory only UI hints
|
||||
mutable unsigned int nTimeDisplayed; |
||||
mutable int nLinesDisplayed; |
||||
mutable char fConfirmedDisplayed; |
||||
|
||||
|
||||
CWalletTx() |
||||
{ |
||||
Init(); |
||||
} |
||||
|
||||
CWalletTx(const CMerkleTx& txIn) : CMerkleTx(txIn) |
||||
{ |
||||
Init(); |
||||
} |
||||
|
||||
CWalletTx(const CTransaction& txIn) : CMerkleTx(txIn) |
||||
{ |
||||
Init(); |
||||
} |
||||
|
||||
void Init() |
||||
{ |
||||
vtxPrev.clear(); |
||||
mapValue.clear(); |
||||
vOrderForm.clear(); |
||||
fTimeReceivedIsTxTime = false; |
||||
nTimeReceived = 0; |
||||
fFromMe = false; |
||||
strFromAccount.clear(); |
||||
vfSpent.clear(); |
||||
fDebitCached = false; |
||||
fCreditCached = false; |
||||
fAvailableCreditCached = false; |
||||
fChangeCached = false; |
||||
nDebitCached = 0; |
||||
nCreditCached = 0; |
||||
nAvailableCreditCached = 0; |
||||
nChangeCached = 0; |
||||
nTimeDisplayed = 0; |
||||
nLinesDisplayed = 0; |
||||
fConfirmedDisplayed = false; |
||||
} |
||||
|
||||
IMPLEMENT_SERIALIZE |
||||
( |
||||
CWalletTx* pthis = const_cast<CWalletTx*>(this); |
||||
if (fRead) |
||||
pthis->Init(); |
||||
char fSpent = false; |
||||
|
||||
if (!fRead) |
||||
{ |
||||
pthis->mapValue["fromaccount"] = pthis->strFromAccount; |
||||
|
||||
std::string str; |
||||
BOOST_FOREACH(char f, vfSpent) |
||||
{ |
||||
str += (f ? '1' : '0'); |
||||
if (f) |
||||
fSpent = true; |
||||
} |
||||
pthis->mapValue["spent"] = str; |
||||
} |
||||
|
||||
nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion,ser_action); |
||||
READWRITE(vtxPrev); |
||||
READWRITE(mapValue); |
||||
READWRITE(vOrderForm); |
||||
READWRITE(fTimeReceivedIsTxTime); |
||||
READWRITE(nTimeReceived); |
||||
READWRITE(fFromMe); |
||||
READWRITE(fSpent); |
||||
|
||||
if (fRead) |
||||
{ |
||||
pthis->strFromAccount = pthis->mapValue["fromaccount"]; |
||||
|
||||
if (mapValue.count("spent")) |
||||
BOOST_FOREACH(char c, pthis->mapValue["spent"]) |
||||
pthis->vfSpent.push_back(c != '0'); |
||||
else |
||||
pthis->vfSpent.assign(vout.size(), fSpent); |
||||
} |
||||
|
||||
pthis->mapValue.erase("fromaccount"); |
||||
pthis->mapValue.erase("version"); |
||||
pthis->mapValue.erase("spent"); |
||||
) |
||||
|
||||
// marks certain txout's as spent
|
||||
// returns true if any update took place
|
||||
bool UpdateSpent(const std::vector<char>& vfNewSpent) |
||||
{ |
||||
bool fReturn = false; |
||||
for (int i=0; i < vfNewSpent.size(); i++) |
||||
{ |
||||
if (i == vfSpent.size()) |
||||
break; |
||||
|
||||
if (vfNewSpent[i] && !vfSpent[i]) |
||||
{ |
||||
vfSpent[i] = true; |
||||
fReturn = true; |
||||
fAvailableCreditCached = false; |
||||
} |
||||
} |
||||
return fReturn; |
||||
} |
||||
|
||||
void MarkDirty() |
||||
{ |
||||
fCreditCached = false; |
||||
fAvailableCreditCached = false; |
||||
fDebitCached = false; |
||||
fChangeCached = false; |
||||
} |
||||
|
||||
void MarkSpent(unsigned int nOut) |
||||
{ |
||||
if (nOut >= vout.size()) |
||||
throw std::runtime_error("CWalletTx::MarkSpent() : nOut out of range"); |
||||
vfSpent.resize(vout.size()); |
||||
if (!vfSpent[nOut]) |
||||
{ |
||||
vfSpent[nOut] = true; |
||||
fAvailableCreditCached = false; |
||||
} |
||||
} |
||||
|
||||
bool IsSpent(unsigned int nOut) const |
||||
{ |
||||
if (nOut >= vout.size()) |
||||
throw std::runtime_error("CWalletTx::IsSpent() : nOut out of range"); |
||||
if (nOut >= vfSpent.size()) |
||||
return false; |
||||
return (!!vfSpent[nOut]); |
||||
} |
||||
|
||||
int64 GetDebit() const |
||||
{ |
||||
if (vin.empty()) |
||||
return 0; |
||||
if (fDebitCached) |
||||
return nDebitCached; |
||||
nDebitCached = CTransaction::GetDebit(); |
||||
fDebitCached = true; |
||||
return nDebitCached; |
||||
} |
||||
|
||||
int64 GetCredit(bool fUseCache=true) const |
||||
{ |
||||
// Must wait until coinbase is safely deep enough in the chain before valuing it
|
||||
if (IsCoinBase() && GetBlocksToMaturity() > 0) |
||||
return 0; |
||||
|
||||
// GetBalance can assume transactions in mapWallet won't change
|
||||
if (fUseCache && fCreditCached) |
||||
return nCreditCached; |
||||
nCreditCached = CTransaction::GetCredit(); |
||||
fCreditCached = true; |
||||
return nCreditCached; |
||||
} |
||||
|
||||
int64 GetAvailableCredit(bool fUseCache=true) const |
||||
{ |
||||
// Must wait until coinbase is safely deep enough in the chain before valuing it
|
||||
if (IsCoinBase() && GetBlocksToMaturity() > 0) |
||||
return 0; |
||||
|
||||
if (fUseCache && fAvailableCreditCached) |
||||
return nAvailableCreditCached; |
||||
|
||||
int64 nCredit = 0; |
||||
for (int i = 0; i < vout.size(); i++) |
||||
{ |
||||
if (!IsSpent(i)) |
||||
{ |
||||
const CTxOut &txout = vout[i]; |
||||
nCredit += txout.GetCredit(); |
||||
if (!MoneyRange(nCredit)) |
||||
throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range"); |
||||
} |
||||
} |
||||
|
||||
nAvailableCreditCached = nCredit; |
||||
fAvailableCreditCached = true; |
||||
return nCredit; |
||||
} |
||||
|
||||
|
||||
int64 GetChange() const |
||||
{ |
||||
if (fChangeCached) |
||||
return nChangeCached; |
||||
nChangeCached = CTransaction::GetChange(); |
||||
fChangeCached = true; |
||||
return nChangeCached; |
||||
} |
||||
|
||||
void GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, std::list<std::pair<std::string /* address */, int64> >& listReceived, |
||||
std::list<std::pair<std::string /* address */, int64> >& listSent, int64& nFee, std::string& strSentAccount) const; |
||||
|
||||
void GetAccountAmounts(const std::string& strAccount, int64& nGenerated, int64& nReceived, |
||||
int64& nSent, int64& nFee) const; |
||||
|
||||
bool IsFromMe() const |
||||
{ |
||||
return (GetDebit() > 0); |
||||
} |
||||
|
||||
bool IsConfirmed() const |
||||
{ |
||||
// Quick answer in most cases
|
||||
if (!IsFinal()) |
||||
return false; |
||||
if (GetDepthInMainChain() >= 1) |
||||
return true; |
||||
if (!IsFromMe()) // using wtx's cached debit
|
||||
return false; |
||||
|
||||
// If no confirmations but it's from us, we can still
|
||||
// consider it confirmed if all dependencies are confirmed
|
||||
std::map<uint256, const CMerkleTx*> mapPrev; |
||||
std::vector<const CMerkleTx*> vWorkQueue; |
||||
vWorkQueue.reserve(vtxPrev.size()+1); |
||||
vWorkQueue.push_back(this); |
||||
for (int i = 0; i < vWorkQueue.size(); i++) |
||||
{ |
||||
const CMerkleTx* ptx = vWorkQueue[i]; |
||||
|
||||
if (!ptx->IsFinal()) |
||||
return false; |
||||
if (ptx->GetDepthInMainChain() >= 1) |
||||
continue; |
||||
if (!ptx->IsFromMe()) |
||||
return false; |
||||
|
||||
if (mapPrev.empty()) |
||||
BOOST_FOREACH(const CMerkleTx& tx, vtxPrev) |
||||
mapPrev[tx.GetHash()] = &tx; |
||||
|
||||
BOOST_FOREACH(const CTxIn& txin, ptx->vin) |
||||
{ |
||||
if (!mapPrev.count(txin.prevout.hash)) |
||||
return false; |
||||
vWorkQueue.push_back(mapPrev[txin.prevout.hash]); |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
bool WriteToDisk(); |
||||
|
||||
int64 GetTxTime() const; |
||||
int GetRequestCount() const; |
||||
|
||||
void AddSupportingTransactions(CTxDB& txdb); |
||||
|
||||
bool AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs=true); |
||||
bool AcceptWalletTransaction(); |
||||
|
||||
void RelayWalletTransaction(CTxDB& txdb); |
||||
void RelayWalletTransaction(); |
||||
}; |
||||
|
||||
|
||||
//
|
||||
// Private key that includes an expiration date in case it never gets used.
|
||||
//
|
||||
class CWalletKey |
||||
{ |
||||
public: |
||||
CPrivKey vchPrivKey; |
||||
int64 nTimeCreated; |
||||
int64 nTimeExpires; |
||||
std::string strComment; |
||||
//// todo: add something to note what created it (user, getnewaddress, change)
|
||||
//// maybe should have a map<string, string> property map
|
||||
|
||||
CWalletKey(int64 nExpires=0) |
||||
{ |
||||
nTimeCreated = (nExpires ? GetTime() : 0); |
||||
nTimeExpires = nExpires; |
||||
} |
||||
|
||||
IMPLEMENT_SERIALIZE |
||||
( |
||||
if (!(nType & SER_GETHASH)) |
||||
READWRITE(nVersion); |
||||
READWRITE(vchPrivKey); |
||||
READWRITE(nTimeCreated); |
||||
READWRITE(nTimeExpires); |
||||
READWRITE(strComment); |
||||
) |
||||
}; |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Account information.
|
||||
// Stored in wallet with key "acc"+string account name
|
||||
//
|
||||
class CAccount |
||||
{ |
||||
public: |
||||
std::vector<unsigned char> vchPubKey; |
||||
|
||||
CAccount() |
||||
{ |
||||
SetNull(); |
||||
} |
||||
|
||||
void SetNull() |
||||
{ |
||||
vchPubKey.clear(); |
||||
} |
||||
|
||||
IMPLEMENT_SERIALIZE |
||||
( |
||||
if (!(nType & SER_GETHASH)) |
||||
READWRITE(nVersion); |
||||
READWRITE(vchPubKey); |
||||
) |
||||
}; |
||||
|
||||
|
||||
|
||||
//
|
||||
// Internal transfers.
|
||||
// Database key is acentry<account><counter>
|
||||
//
|
||||
class CAccountingEntry |
||||
{ |
||||
public: |
||||
std::string strAccount; |
||||
int64 nCreditDebit; |
||||
int64 nTime; |
||||
std::string strOtherAccount; |
||||
std::string strComment; |
||||
|
||||
CAccountingEntry() |
||||
{ |
||||
SetNull(); |
||||
} |
||||
|
||||
void SetNull() |
||||
{ |
||||
nCreditDebit = 0; |
||||
nTime = 0; |
||||
strAccount.clear(); |
||||
strOtherAccount.clear(); |
||||
strComment.clear(); |
||||
} |
||||
|
||||
IMPLEMENT_SERIALIZE |
||||
( |
||||
if (!(nType & SER_GETHASH)) |
||||
READWRITE(nVersion); |
||||
// Note: strAccount is serialized as part of the key, not here.
|
||||
READWRITE(nCreditDebit); |
||||
READWRITE(nTime); |
||||
READWRITE(strOtherAccount); |
||||
READWRITE(strComment); |
||||
) |
||||
}; |
||||
|
||||
#endif |
Loading…
Reference in new issue