Browse Source

move wallet code to separate file

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.
tags/v0.15.1
Pieter Wuille 10 years ago
parent
commit
e89b9f6a2a
16 changed files with 1735 additions and 1690 deletions
  1. 0
    103
      src/db.cpp
  2. 5
    29
      src/db.h
  3. 0
    2
      src/headers.h
  4. 33
    0
      src/keystore.cpp
  5. 10
    0
      src/keystore.h
  6. 165
    1116
      src/main.cpp
  7. 9
    437
      src/main.h
  8. 3
    1
      src/makefile.mingw
  9. 3
    1
      src/makefile.osx
  10. 3
    1
      src/makefile.unix
  11. 2
    0
      src/noui.h
  12. 1
    0
      src/script.h
  13. 1
    0
      src/ui.cpp
  14. 3
    0
      src/ui.h
  15. 1056
    0
      src/wallet.cpp
  16. 441
    0
      src/wallet.h

+ 0
- 103
src/db.cpp View File

@@ -584,9 +584,6 @@ bool LoadAddresses()
// CWalletDB
//

static set<int64> setKeyPool;
static CCriticalSection cs_setKeyPool;

bool CWalletDB::ReadAccount(const string& strAccount, CAccount& account)
{
account.SetNull();
@@ -831,34 +828,6 @@ bool CWalletDB::LoadWallet()
return true;
}

bool LoadWallet(bool& fFirstRunRet)
{
fFirstRunRet = false;
if (!CWalletDB("cr+").LoadWallet())
return false;
fFirstRunRet = vchDefaultKey.empty();

if (mapKeys.count(vchDefaultKey))
{
// Set keyUser
keyUser.SetPubKey(vchDefaultKey);
keyUser.SetPrivKey(mapKeys[vchDefaultKey]);
}
else
{
// Create new keyUser and set as default key
RandAddSeedPerfmon();

CWalletDB walletdb;
vchDefaultKey = GetKeyFromKeyPool();
walletdb.WriteDefaultKey(vchDefaultKey);
walletdb.WriteName(PubKeyToAddress(vchDefaultKey), "");
}

CreateThread(ThreadFlushWalletDB, NULL);
return true;
}

void ThreadFlushWalletDB(void* parg)
{
static bool fOneThread;
@@ -954,75 +923,3 @@ void BackupWallet(const string& strDest)
}


void CWalletDB::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
{
nIndex = -1;
keypool.vchPubKey.clear();
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(cs_setKeyPool)
{
// Top up key pool
int64 nTargetSize = max(GetArg("-keypool", 100), (int64)0);
while (setKeyPool.size() < nTargetSize+1)
{
int64 nEnd = 1;
if (!setKeyPool.empty())
nEnd = *(--setKeyPool.end()) + 1;
if (!Write(make_pair(string("pool"), nEnd), CKeyPool(GenerateNewKey())))
throw runtime_error("ReserveKeyFromKeyPool() : writing generated key failed");
setKeyPool.insert(nEnd);
printf("keypool added key %"PRI64d", size=%d\n", nEnd, setKeyPool.size());
}

// Get the oldest key
assert(!setKeyPool.empty());
nIndex = *(setKeyPool.begin());
setKeyPool.erase(setKeyPool.begin());
if (!Read(make_pair(string("pool"), nIndex), keypool))
throw runtime_error("ReserveKeyFromKeyPool() : read failed");
if (!mapKeys.count(keypool.vchPubKey))
throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
assert(!keypool.vchPubKey.empty());
printf("keypool reserve %"PRI64d"\n", nIndex);
}
}

void CWalletDB::KeepKey(int64 nIndex)
{
// Remove from key pool
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_mapWallet)
{
Erase(make_pair(string("pool"), nIndex));
}
printf("keypool keep %"PRI64d"\n", nIndex);
}

void CWalletDB::ReturnKey(int64 nIndex)
{
// Return to key pool
CRITICAL_BLOCK(cs_setKeyPool)
setKeyPool.insert(nIndex);
printf("keypool return %"PRI64d"\n", nIndex);
}

vector<unsigned char> GetKeyFromKeyPool()
{
CWalletDB walletdb;
int64 nIndex = 0;
CKeyPool keypool;
walletdb.ReserveKeyFromKeyPool(nIndex, keypool);
walletdb.KeepKey(nIndex);
return keypool.vchPubKey;
}

int64 GetOldestKeyPoolTime()
{
CWalletDB walletdb;
int64 nIndex = 0;
CKeyPool keypool;
walletdb.ReserveKeyFromKeyPool(nIndex, keypool);
walletdb.ReturnKey(nIndex);
return keypool.nTime;
}

+ 5
- 29
src/db.h View File

@@ -25,8 +25,6 @@ class CAccount;
class CAccountingEntry;
class CBlockLocator;

extern std::map<std::string, std::string> mapAddressBook;
extern CCriticalSection cs_mapAddressBook;
extern std::vector<unsigned char> vchDefaultKey;
extern bool fClient;
extern int nBestHeight;
@@ -39,6 +37,8 @@ extern DbEnv dbenv;
extern void DBFlush(bool fShutdown);
extern std::vector<unsigned char> GetKeyFromKeyPool();
extern int64 GetOldestKeyPoolTime();
extern void ThreadFlushWalletDB(void* parg);




@@ -494,33 +494,9 @@ public:
ReturnKey();
}

std::vector<unsigned char> GetReservedKey()
{
if (nIndex == -1)
{
CKeyPool keypool;
CWalletDB().ReserveKeyFromKeyPool(nIndex, keypool);
vchPubKey = keypool.vchPubKey;
}
assert(!vchPubKey.empty());
return vchPubKey;
}

void KeepKey()
{
if (nIndex != -1)
CWalletDB().KeepKey(nIndex);
nIndex = -1;
vchPubKey.clear();
}

void ReturnKey()
{
if (nIndex != -1)
CWalletDB::ReturnKey(nIndex);
nIndex = -1;
vchPubKey.clear();
}
std::vector<unsigned char> GetReservedKey();
void KeepKey();
void ReturnKey();
};

#endif

+ 0
- 2
src/headers.h View File

@@ -91,10 +91,8 @@
#include "serialize.h"
#include "uint256.h"
#include "util.h"
#include "key.h"
#include "bignum.h"
#include "base58.h"
#include "script.h"
#include "main.h"
#ifdef GUI
#include "uibase.h"

+ 33
- 0
src/keystore.cpp View File

@@ -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());
}

+ 10
- 0
src/keystore.h View File

@@ -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

+ 165
- 1116
src/main.cpp
File diff suppressed because it is too large
View File


+ 9
- 437
src/main.h View File

@@ -7,7 +7,6 @@
#include "bignum.h"
#include "net.h"
#include "key.h"
#include "db.h"
#include "script.h"

#include <list>
@@ -22,6 +21,7 @@ class CTransaction;
class CBlock;
class CBlockIndex;
class CWalletTx;
class CWallet;
class CKeyItem;

class CMessageHeader;
@@ -62,14 +62,15 @@ extern CBigNum bnBestChainWork;
extern CBigNum bnBestInvalidWork;
extern uint256 hashBestChain;
extern CBlockIndex* pindexBest;
extern std::set<int64> setKeyPool;
extern CCriticalSection cs_setKeyPool;
extern unsigned int nTransactionsUpdated;
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 double dHashesPerSec;
extern int64 nHPSTimerStart;
extern int64 nTimeBestReceived;
extern std::map<std::string, std::string> mapAddressBook;
extern CCriticalSection cs_mapAddressBook;


// Settings
extern int fGenerateBitcoins;
@@ -92,24 +93,11 @@ class CTxIndex;
bool CheckDiskSpace(uint64 nAdditionalBytes=0);
FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb");
FILE* AppendBlockFile(unsigned int& nFileRet);
bool AddKey(const CKey& key);
std::vector<unsigned char> GenerateNewKey();
bool AddToWallet(const CWalletTx& wtxIn);
void WalletUpdateSpent(const COutPoint& prevout);
int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
void ReacceptWalletTransactions();
bool LoadBlockIndex(bool fAllowNew=true);
void PrintBlockTree();
bool ProcessMessages(CNode* pfrom);
bool ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vRecv);
bool SendMessages(CNode* pto, bool fSendTrickle);
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);
void GenerateBitcoins(bool fGenerate);
void ThreadBitcoinMiner(void* parg);
CBlock* CreateNewBlock(CReserveKey& reservekey);
@@ -721,11 +709,7 @@ public:
bool ClientConnectInputs();
bool CheckTransaction() const;
bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true, bool* pfMissingInputs=NULL);
bool AcceptToMemoryPool(bool fCheckInputs=true, bool* pfMissingInputs=NULL)
{
CTxDB txdb("r");
return AcceptToMemoryPool(txdb, fCheckInputs, pfMissingInputs);
}
bool AcceptToMemoryPool(bool fCheckInputs=true, bool* pfMissingInputs=NULL);
protected:
bool AddToMemoryPoolUnchecked();
public:
@@ -784,307 +768,7 @@ public:
bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
int GetBlocksToMaturity() const;
bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true);
bool AcceptToMemoryPool() { CTxDB txdb("r"); return AcceptToMemoryPool(txdb); }
};




//
// 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()
{
return CWalletDB().WriteTx(GetHash(), *this);
}


int64 GetTxTime() const;
int GetRequestCount() const;

void AddSupportingTransactions(CTxDB& txdb);

bool AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs=true);
bool AcceptWalletTransaction() { CTxDB txdb("r"); return AcceptWalletTransaction(txdb); }

void RelayWalletTransaction(CTxDB& txdb);
void RelayWalletTransaction() { CTxDB txdb("r"); RelayWalletTransaction(txdb); }
bool AcceptToMemoryPool();
};


@@ -1744,114 +1428,6 @@ public:



//
// 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);
)
};









@@ -2064,12 +1640,8 @@ public:


extern std::map<uint256, CTransaction> mapTransactions;
extern std::map<uint256, CWalletTx> mapWallet;
extern std::vector<uint256> vWalletUpdated;
extern CCriticalSection cs_mapWallet;
extern std::map<std::vector<unsigned char>, CPrivKey> mapKeys;
extern std::map<uint160, std::vector<unsigned char> > mapPubKeys;
extern CCriticalSection cs_mapKeys;
extern CKey keyUser;

#endif

+ 3
- 1
src/makefile.mingw View File

@@ -33,7 +33,7 @@ DEFS=-DWIN32 -D__WXMSW__ -D_WINDOWS -DNOPCH -DUSE_SSL
DEBUGFLAGS=-g -D__WXDEBUG__
CFLAGS=-mthreads -O2 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h \
script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h noui.h init.h
script.h db.h net.h irc.h keystore.h main.h wallet.h rpc.h uibase.h ui.h noui.h init.h

ifdef USE_UPNP
INCLUDEPATHS += -I"C:\upnpc-exe-win32-20110215"
@@ -50,7 +50,9 @@ OBJS= \
obj/db.o \
obj/net.o \
obj/irc.o \
obj/keystore.o \
obj/main.o \
obj/wallet.o \
obj/rpc.o \
obj/init.o \
cryptopp/obj/sha.o \

+ 3
- 1
src/makefile.osx View File

@@ -33,7 +33,7 @@ DEBUGFLAGS=-g -DwxDEBUG_LEVEL=0
# ppc doesn't work because we don't support big-endian
CFLAGS=-mmacosx-version-min=10.5 -arch i386 -arch x86_64 -O3 -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h \
script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h noui.h init.h
script.h db.h net.h irc.h keystore.h main.h wallet.h rpc.h uibase.h ui.h noui.h init.h

OBJS= \
obj/util.o \
@@ -41,7 +41,9 @@ OBJS= \
obj/db.o \
obj/net.o \
obj/irc.o \
obj/keystore.o \
obj/main.o \
obj/wallet.o \
obj/rpc.o \
obj/init.o \
cryptopp/obj/sha.o \

+ 3
- 1
src/makefile.unix View File

@@ -39,7 +39,7 @@ LIBS+= \
DEBUGFLAGS=-g -D__WXDEBUG__
CXXFLAGS=-O2 -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS)
HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h \
script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h noui.h init.h
script.h db.h net.h irc.h keystore.h main.h wallet.h rpc.h uibase.h ui.h noui.h init.h

OBJS= \
obj/util.o \
@@ -47,7 +47,9 @@ OBJS= \
obj/db.o \
obj/net.o \
obj/irc.o \
obj/keystore.o \
obj/main.o \
obj/wallet.o \
obj/rpc.o \
obj/init.o \
cryptopp/obj/sha.o \

+ 2
- 0
src/noui.h View File

@@ -5,6 +5,8 @@
#define BITCOIN_NOUI_H

#include <string>
#include <boost/function.hpp>
#include "wallet.h"

typedef void wxWindow;
#define wxYES 0x00000002

+ 1
- 0
src/script.h View File

@@ -5,6 +5,7 @@
#define H_BITCOIN_SCRIPT

#include "base58.h"
#include "keystore.h"

#include <string>
#include <vector>

+ 1
- 0
src/ui.cpp View File

@@ -3,6 +3,7 @@
// file license.txt or http://www.opensource.org/licenses/mit-license.php.

#include "headers.h"
#include "db.h"
#include "init.h"
#include "strlcpy.h"
#include <boost/filesystem/fstream.hpp>

+ 3
- 0
src/ui.h View File

@@ -4,6 +4,9 @@
#ifndef BITCOIN_UI_H
#define BITCOIN_UI_H

#include <boost/function.hpp>
#include "wallet.h"

DECLARE_EVENT_TYPE(wxEVT_UITHREADCALL, -1)



+ 1056
- 0
src/wallet.cpp
File diff suppressed because it is too large
View File


+ 441
- 0
src/wallet.h View File

@@ -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…
Cancel
Save