key pool for safer wallet backup
git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@163 1a98c847-1fd6-4fd8-948a-caf3550aa51b
This commit is contained in:
parent
0a27bd065e
commit
103849419a
8 changed files with 198 additions and 57 deletions
65
db.cpp
65
db.cpp
|
@ -576,6 +576,9 @@ bool LoadAddresses()
|
||||||
// CWalletDB
|
// CWalletDB
|
||||||
//
|
//
|
||||||
|
|
||||||
|
static set<int64> setKeyPool;
|
||||||
|
static CCriticalSection cs_setKeyPool;
|
||||||
|
|
||||||
bool CWalletDB::LoadWallet()
|
bool CWalletDB::LoadWallet()
|
||||||
{
|
{
|
||||||
vchDefaultKey.clear();
|
vchDefaultKey.clear();
|
||||||
|
@ -654,6 +657,12 @@ bool CWalletDB::LoadWallet()
|
||||||
{
|
{
|
||||||
ssValue >> vchDefaultKey;
|
ssValue >> vchDefaultKey;
|
||||||
}
|
}
|
||||||
|
else if (strType == "pool")
|
||||||
|
{
|
||||||
|
int64 nIndex;
|
||||||
|
ssKey >> nIndex;
|
||||||
|
setKeyPool.insert(nIndex);
|
||||||
|
}
|
||||||
else if (strType == "version")
|
else if (strType == "version")
|
||||||
{
|
{
|
||||||
ssValue >> nFileVersion;
|
ssValue >> nFileVersion;
|
||||||
|
@ -836,3 +845,59 @@ void BackupWallet(const string& strDest)
|
||||||
Sleep(100);
|
Sleep(100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CWalletDB::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
|
||||||
|
{
|
||||||
|
nIndex = -1;
|
||||||
|
keypool.vchPubKey.clear();
|
||||||
|
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
|
||||||
|
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> CWalletDB::GetKeyFromKeyPool()
|
||||||
|
{
|
||||||
|
int64 nIndex = 0;
|
||||||
|
CKeyPool keypool;
|
||||||
|
ReserveKeyFromKeyPool(nIndex, keypool);
|
||||||
|
KeepKey(nIndex);
|
||||||
|
return keypool.vchPubKey;
|
||||||
|
}
|
||||||
|
|
81
db.h
81
db.h
|
@ -308,6 +308,35 @@ bool LoadAddresses();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class CKeyPool
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int64 nTime;
|
||||||
|
vector<unsigned char> vchPubKey;
|
||||||
|
|
||||||
|
CKeyPool()
|
||||||
|
{
|
||||||
|
nTime = GetTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
CKeyPool(const vector<unsigned char>& vchPubKeyIn)
|
||||||
|
{
|
||||||
|
nTime = GetTime();
|
||||||
|
vchPubKey = vchPubKeyIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMPLEMENT_SERIALIZE
|
||||||
|
(
|
||||||
|
if (!(nType & SER_GETHASH))
|
||||||
|
READWRITE(nVersion);
|
||||||
|
READWRITE(nTime);
|
||||||
|
READWRITE(vchPubKey);
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CWalletDB : public CDB
|
class CWalletDB : public CDB
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -396,6 +425,13 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadWallet();
|
bool LoadWallet();
|
||||||
|
protected:
|
||||||
|
void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool);
|
||||||
|
void KeepKey(int64 nIndex);
|
||||||
|
static void ReturnKey(int64 nIndex);
|
||||||
|
friend class CReserveKey;
|
||||||
|
public:
|
||||||
|
vector<unsigned char> GetKeyFromKeyPool();
|
||||||
};
|
};
|
||||||
|
|
||||||
bool LoadWallet(bool& fFirstRunRet);
|
bool LoadWallet(bool& fFirstRunRet);
|
||||||
|
@ -405,3 +441,48 @@ inline bool SetAddressBookName(const string& strAddress, const string& strName)
|
||||||
{
|
{
|
||||||
return CWalletDB().WriteName(strAddress, strName);
|
return CWalletDB().WriteName(strAddress, strName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CReserveKey
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
int64 nIndex;
|
||||||
|
vector<unsigned char> vchPubKey;
|
||||||
|
public:
|
||||||
|
CReserveKey()
|
||||||
|
{
|
||||||
|
nIndex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
~CReserveKey()
|
||||||
|
{
|
||||||
|
ReturnKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
6
irc.cpp
6
irc.cpp
|
@ -126,7 +126,7 @@ bool RecvLineIRC(SOCKET hSocket, string& strLine)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int RecvUntil(SOCKET hSocket, const char* psz1, const char* psz2=NULL, const char* psz3=NULL)
|
int RecvUntil(SOCKET hSocket, const char* psz1, const char* psz2=NULL, const char* psz3=NULL, const char* psz4=NULL)
|
||||||
{
|
{
|
||||||
loop
|
loop
|
||||||
{
|
{
|
||||||
|
@ -141,6 +141,8 @@ int RecvUntil(SOCKET hSocket, const char* psz1, const char* psz2=NULL, const cha
|
||||||
return 2;
|
return 2;
|
||||||
if (psz3 && strLine.find(psz3) != -1)
|
if (psz3 && strLine.find(psz3) != -1)
|
||||||
return 3;
|
return 3;
|
||||||
|
if (psz4 && strLine.find(psz4) != -1)
|
||||||
|
return 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,7 +212,7 @@ void ThreadIRCSeed2(void* parg)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!RecvUntil(hSocket, "Found your hostname", "using your IP address instead", "Couldn't look up your hostname"))
|
if (!RecvUntil(hSocket, "Found your hostname", "using your IP address instead", "Couldn't look up your hostname", "ignoring hostname"))
|
||||||
{
|
{
|
||||||
closesocket(hSocket);
|
closesocket(hSocket);
|
||||||
hSocket = INVALID_SOCKET;
|
hSocket = INVALID_SOCKET;
|
||||||
|
|
61
main.cpp
61
main.cpp
|
@ -158,7 +158,8 @@ bool AddToWallet(const CWalletTx& wtxIn)
|
||||||
if (txout.scriptPubKey == scriptDefaultKey)
|
if (txout.scriptPubKey == scriptDefaultKey)
|
||||||
{
|
{
|
||||||
CWalletDB walletdb;
|
CWalletDB walletdb;
|
||||||
walletdb.WriteDefaultKey(GenerateNewKey());
|
vchDefaultKey = walletdb.GetKeyFromKeyPool();
|
||||||
|
walletdb.WriteDefaultKey(vchDefaultKey);
|
||||||
walletdb.WriteName(PubKeyToAddress(vchDefaultKey), "");
|
walletdb.WriteName(PubKeyToAddress(vchDefaultKey), "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1493,15 +1494,6 @@ bool CBlock::AcceptBlock()
|
||||||
(nHeight == 74000 && hash != uint256("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20")))
|
(nHeight == 74000 && hash != uint256("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20")))
|
||||||
return error("AcceptBlock() : rejected by checkpoint lockin at %d", nHeight);
|
return error("AcceptBlock() : rejected by checkpoint lockin at %d", nHeight);
|
||||||
|
|
||||||
// Scanback checkpoint lockin
|
|
||||||
for (CBlockIndex* pindex = pindexPrev; pindex->nHeight >= 74000; pindex = pindex->pprev)
|
|
||||||
{
|
|
||||||
if (pindex->nHeight == 74000 && pindex->GetBlockHash() != uint256("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20"))
|
|
||||||
return error("AcceptBlock() : rejected by scanback lockin at %d", pindex->nHeight);
|
|
||||||
if (pindex->nHeight == 74638 && pindex->GetBlockHash() == uint256("0x0000000000790ab3f22ec756ad43b6ab569abf0bddeb97c67a6f7b1470a7ec1c"))
|
|
||||||
return error("AcceptBlock() : rejected by scanback lockin at %d", pindex->nHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write block to history file
|
// Write block to history file
|
||||||
if (!CheckDiskSpace(::GetSerializeSize(*this, SER_DISK)))
|
if (!CheckDiskSpace(::GetSerializeSize(*this, SER_DISK)))
|
||||||
return error("AcceptBlock() : out of disk space");
|
return error("AcceptBlock() : out of disk space");
|
||||||
|
@ -1961,7 +1953,7 @@ bool AlreadyHave(CTxDB& txdb, const CInv& inv)
|
||||||
{
|
{
|
||||||
switch (inv.type)
|
switch (inv.type)
|
||||||
{
|
{
|
||||||
case MSG_TX: return mapTransactions.count(inv.hash) || txdb.ContainsTx(inv.hash);
|
case MSG_TX: return mapTransactions.count(inv.hash) || mapOrphanTransactions.count(inv.hash) || txdb.ContainsTx(inv.hash);
|
||||||
case MSG_BLOCK: return mapBlockIndex.count(inv.hash) || mapOrphanBlocks.count(inv.hash);
|
case MSG_BLOCK: return mapBlockIndex.count(inv.hash) || mapOrphanBlocks.count(inv.hash);
|
||||||
}
|
}
|
||||||
// Don't know what it is, just say we already got one
|
// Don't know what it is, just say we already got one
|
||||||
|
@ -2472,7 +2464,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||||
|
|
||||||
// Keep giving the same key to the same ip until they use it
|
// Keep giving the same key to the same ip until they use it
|
||||||
if (!mapReuseKey.count(pfrom->addr.ip))
|
if (!mapReuseKey.count(pfrom->addr.ip))
|
||||||
mapReuseKey[pfrom->addr.ip] = GenerateNewKey();
|
mapReuseKey[pfrom->addr.ip] = CWalletDB().GetKeyFromKeyPool();
|
||||||
|
|
||||||
// Send back approval of order and pubkey to use
|
// Send back approval of order and pubkey to use
|
||||||
CScript scriptPubKey;
|
CScript scriptPubKey;
|
||||||
|
@ -2933,8 +2925,7 @@ void BitcoinMiner()
|
||||||
if (mapArgs.count("-4way"))
|
if (mapArgs.count("-4way"))
|
||||||
f4WaySSE2 = (mapArgs["-4way"] != "0");
|
f4WaySSE2 = (mapArgs["-4way"] != "0");
|
||||||
|
|
||||||
CKey key;
|
CReserveKey reservekey;
|
||||||
key.MakeNewKey();
|
|
||||||
CBigNum bnExtraNonce = 0;
|
CBigNum bnExtraNonce = 0;
|
||||||
while (fGenerateBitcoins)
|
while (fGenerateBitcoins)
|
||||||
{
|
{
|
||||||
|
@ -2961,9 +2952,9 @@ void BitcoinMiner()
|
||||||
CTransaction txNew;
|
CTransaction txNew;
|
||||||
txNew.vin.resize(1);
|
txNew.vin.resize(1);
|
||||||
txNew.vin[0].prevout.SetNull();
|
txNew.vin[0].prevout.SetNull();
|
||||||
txNew.vin[0].scriptSig << nBits << ++bnExtraNonce;
|
txNew.vin[0].scriptSig << ++bnExtraNonce;
|
||||||
txNew.vout.resize(1);
|
txNew.vout.resize(1);
|
||||||
txNew.vout[0].scriptPubKey << key.GetPubKey() << OP_CHECKSIG;
|
txNew.vout[0].scriptPubKey << reservekey.GetReservedKey() << OP_CHECKSIG;
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -3113,10 +3104,8 @@ void BitcoinMiner()
|
||||||
{
|
{
|
||||||
if (pindexPrev == pindexBest)
|
if (pindexPrev == pindexBest)
|
||||||
{
|
{
|
||||||
// Save key
|
// Remove key from key pool
|
||||||
if (!AddKey(key))
|
reservekey.KeepKey();
|
||||||
return;
|
|
||||||
key.MakeNewKey();
|
|
||||||
|
|
||||||
// Track how many getdata requests this block gets
|
// Track how many getdata requests this block gets
|
||||||
CRITICAL_BLOCK(cs_mapRequestCount)
|
CRITICAL_BLOCK(cs_mapRequestCount)
|
||||||
|
@ -3183,7 +3172,10 @@ void BitcoinMiner()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Update nTime every few seconds
|
// Update nTime every few seconds
|
||||||
pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
|
int64 nNewTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
|
||||||
|
if (nNewTime != pblock->nTime && bnExtraNonce > 10)
|
||||||
|
bnExtraNonce = 0;
|
||||||
|
pblock->nTime = nNewTime;
|
||||||
tmp.block.nTime = ByteReverse(pblock->nTime);
|
tmp.block.nTime = ByteReverse(pblock->nTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3342,7 +3334,7 @@ bool SelectCoins(int64 nTargetValue, set<CWalletTx*>& setCoinsRet)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CKey& keyRet, int64& nFeeRequiredRet)
|
bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRequiredRet)
|
||||||
{
|
{
|
||||||
nFeeRequiredRet = 0;
|
nFeeRequiredRet = 0;
|
||||||
CRITICAL_BLOCK(cs_main)
|
CRITICAL_BLOCK(cs_main)
|
||||||
|
@ -3386,18 +3378,20 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CK
|
||||||
// rediscover unknown transactions that were written with keys of ours to recover
|
// rediscover unknown transactions that were written with keys of ours to recover
|
||||||
// post-backup change.
|
// post-backup change.
|
||||||
|
|
||||||
// New private key
|
// Reserve a new key pair from key pool
|
||||||
if (keyRet.IsNull())
|
vector<unsigned char> vchPubKey = reservekey.GetReservedKey();
|
||||||
keyRet.MakeNewKey();
|
assert(mapKeys.count(vchPubKey));
|
||||||
|
|
||||||
// Fill a vout to ourself, using same address type as the payment
|
// Fill a vout to ourself, using same address type as the payment
|
||||||
CScript scriptChange;
|
CScript scriptChange;
|
||||||
if (scriptPubKey.GetBitcoinAddressHash160() != 0)
|
if (scriptPubKey.GetBitcoinAddressHash160() != 0)
|
||||||
scriptChange.SetBitcoinAddress(keyRet.GetPubKey());
|
scriptChange.SetBitcoinAddress(vchPubKey);
|
||||||
else
|
else
|
||||||
scriptChange << keyRet.GetPubKey() << OP_CHECKSIG;
|
scriptChange << vchPubKey << OP_CHECKSIG;
|
||||||
wtxNew.vout.push_back(CTxOut(nChange, scriptChange));
|
wtxNew.vout.push_back(CTxOut(nChange, scriptChange));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
reservekey.ReturnKey();
|
||||||
|
|
||||||
// Fill a vout to the payee
|
// Fill a vout to the payee
|
||||||
if (fChangeFirst)
|
if (fChangeFirst)
|
||||||
|
@ -3440,7 +3434,7 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CK
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call after CreateTransaction unless you want to abort
|
// Call after CreateTransaction unless you want to abort
|
||||||
bool CommitTransaction(CWalletTx& wtxNew, const CKey& key)
|
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_main)
|
CRITICAL_BLOCK(cs_main)
|
||||||
{
|
{
|
||||||
|
@ -3452,9 +3446,8 @@ bool CommitTransaction(CWalletTx& wtxNew, const CKey& key)
|
||||||
// maybe makes sense; please don't do it anywhere else.
|
// maybe makes sense; please don't do it anywhere else.
|
||||||
CWalletDB walletdb("r");
|
CWalletDB walletdb("r");
|
||||||
|
|
||||||
// Add the change's private key to wallet
|
// Take key pair from key pool so it won't be used again
|
||||||
if (!key.IsNull() && !AddKey(key))
|
reservekey.KeepKey();
|
||||||
throw runtime_error("CommitTransaction() : AddKey failed");
|
|
||||||
|
|
||||||
// Add tx to wallet, because if it has change it's also ours,
|
// Add tx to wallet, because if it has change it's also ours,
|
||||||
// otherwise just for transaction history.
|
// otherwise just for transaction history.
|
||||||
|
@ -3496,9 +3489,9 @@ string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAs
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_main)
|
CRITICAL_BLOCK(cs_main)
|
||||||
{
|
{
|
||||||
CKey key;
|
CReserveKey reservekey;
|
||||||
int64 nFeeRequired;
|
int64 nFeeRequired;
|
||||||
if (!CreateTransaction(scriptPubKey, nValue, wtxNew, key, nFeeRequired))
|
if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
|
||||||
{
|
{
|
||||||
string strError;
|
string strError;
|
||||||
if (nValue + nFeeRequired > GetBalance())
|
if (nValue + nFeeRequired > GetBalance())
|
||||||
|
@ -3512,7 +3505,7 @@ string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAs
|
||||||
if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL))
|
if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL))
|
||||||
return "ABORTED";
|
return "ABORTED";
|
||||||
|
|
||||||
if (!CommitTransaction(wtxNew, key))
|
if (!CommitTransaction(wtxNew, reservekey))
|
||||||
return _("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
|
return _("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
|
||||||
}
|
}
|
||||||
MainFrameRepaint();
|
MainFrameRepaint();
|
||||||
|
|
6
main.h
6
main.h
|
@ -76,8 +76,8 @@ bool ProcessMessages(CNode* pfrom);
|
||||||
bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv);
|
bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv);
|
||||||
bool SendMessages(CNode* pto, bool fSendTrickle);
|
bool SendMessages(CNode* pto, bool fSendTrickle);
|
||||||
int64 GetBalance();
|
int64 GetBalance();
|
||||||
bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CKey& keyRet, int64& nFeeRequiredRet);
|
bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRequiredRet);
|
||||||
bool CommitTransaction(CWalletTx& wtxNew, const CKey& key);
|
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
|
||||||
bool BroadcastTransaction(CWalletTx& wtxNew);
|
bool BroadcastTransaction(CWalletTx& wtxNew);
|
||||||
string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
|
string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
|
||||||
string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
|
string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
|
||||||
|
@ -361,7 +361,7 @@ public:
|
||||||
{
|
{
|
||||||
if (scriptPubKey.size() < 6)
|
if (scriptPubKey.size() < 6)
|
||||||
return "CTxOut(error)";
|
return "CTxOut(error)";
|
||||||
return strprintf("CTxOut(nValue=%"PRI64d".%08"PRI64d", scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,24).c_str());
|
return strprintf("CTxOut(nValue=%"PRI64d".%08"PRI64d", scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,30).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void print() const
|
void print() const
|
||||||
|
|
2
rpc.cpp
2
rpc.cpp
|
@ -275,7 +275,7 @@ Value getnewaddress(const Array& params, bool fHelp)
|
||||||
strLabel = params[0].get_str();
|
strLabel = params[0].get_str();
|
||||||
|
|
||||||
// Generate a new key that is added to wallet
|
// Generate a new key that is added to wallet
|
||||||
string strAddress = PubKeyToAddress(GenerateNewKey());
|
string strAddress = PubKeyToAddress(CWalletDB().GetKeyFromKeyPool());
|
||||||
|
|
||||||
SetAddressBookName(strAddress, strLabel);
|
SetAddressBookName(strAddress, strLabel);
|
||||||
return strAddress;
|
return strAddress;
|
||||||
|
|
16
serialize.h
16
serialize.h
|
@ -22,7 +22,7 @@ class CDataStream;
|
||||||
class CAutoFile;
|
class CAutoFile;
|
||||||
static const unsigned int MAX_SIZE = 0x02000000;
|
static const unsigned int MAX_SIZE = 0x02000000;
|
||||||
|
|
||||||
static const int VERSION = 31302;
|
static const int VERSION = 31303;
|
||||||
static const char* pszSubVer = "";
|
static const char* pszSubVer = "";
|
||||||
|
|
||||||
|
|
||||||
|
@ -725,39 +725,39 @@ public:
|
||||||
typedef vector_type::const_iterator const_iterator;
|
typedef vector_type::const_iterator const_iterator;
|
||||||
typedef vector_type::reverse_iterator reverse_iterator;
|
typedef vector_type::reverse_iterator reverse_iterator;
|
||||||
|
|
||||||
explicit CDataStream(int nTypeIn=0, int nVersionIn=VERSION)
|
explicit CDataStream(int nTypeIn=SER_NETWORK, int nVersionIn=VERSION)
|
||||||
{
|
{
|
||||||
Init(nTypeIn, nVersionIn);
|
Init(nTypeIn, nVersionIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
CDataStream(const_iterator pbegin, const_iterator pend, int nTypeIn=0, int nVersionIn=VERSION) : vch(pbegin, pend)
|
CDataStream(const_iterator pbegin, const_iterator pend, int nTypeIn=SER_NETWORK, int nVersionIn=VERSION) : vch(pbegin, pend)
|
||||||
{
|
{
|
||||||
Init(nTypeIn, nVersionIn);
|
Init(nTypeIn, nVersionIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(_MSC_VER) || _MSC_VER >= 1300
|
#if !defined(_MSC_VER) || _MSC_VER >= 1300
|
||||||
CDataStream(const char* pbegin, const char* pend, int nTypeIn=0, int nVersionIn=VERSION) : vch(pbegin, pend)
|
CDataStream(const char* pbegin, const char* pend, int nTypeIn=SER_NETWORK, int nVersionIn=VERSION) : vch(pbegin, pend)
|
||||||
{
|
{
|
||||||
Init(nTypeIn, nVersionIn);
|
Init(nTypeIn, nVersionIn);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CDataStream(const vector_type& vchIn, int nTypeIn=0, int nVersionIn=VERSION) : vch(vchIn.begin(), vchIn.end())
|
CDataStream(const vector_type& vchIn, int nTypeIn=SER_NETWORK, int nVersionIn=VERSION) : vch(vchIn.begin(), vchIn.end())
|
||||||
{
|
{
|
||||||
Init(nTypeIn, nVersionIn);
|
Init(nTypeIn, nVersionIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
CDataStream(const vector<char>& vchIn, int nTypeIn=0, int nVersionIn=VERSION) : vch(vchIn.begin(), vchIn.end())
|
CDataStream(const vector<char>& vchIn, int nTypeIn=SER_NETWORK, int nVersionIn=VERSION) : vch(vchIn.begin(), vchIn.end())
|
||||||
{
|
{
|
||||||
Init(nTypeIn, nVersionIn);
|
Init(nTypeIn, nVersionIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
CDataStream(const vector<unsigned char>& vchIn, int nTypeIn=0, int nVersionIn=VERSION) : vch((char*)&vchIn.begin()[0], (char*)&vchIn.end()[0])
|
CDataStream(const vector<unsigned char>& vchIn, int nTypeIn=SER_NETWORK, int nVersionIn=VERSION) : vch((char*)&vchIn.begin()[0], (char*)&vchIn.end()[0])
|
||||||
{
|
{
|
||||||
Init(nTypeIn, nVersionIn);
|
Init(nTypeIn, nVersionIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init(int nTypeIn=0, int nVersionIn=VERSION)
|
void Init(int nTypeIn=SER_NETWORK, int nVersionIn=VERSION)
|
||||||
{
|
{
|
||||||
nReadPos = 0;
|
nReadPos = 0;
|
||||||
nType = nTypeIn;
|
nType = nTypeIn;
|
||||||
|
|
18
ui.cpp
18
ui.cpp
|
@ -1170,7 +1170,7 @@ void CMainFrame::OnButtonNew(wxCommandEvent& event)
|
||||||
string strName = dialog.GetValue();
|
string strName = dialog.GetValue();
|
||||||
|
|
||||||
// Generate new key
|
// Generate new key
|
||||||
string strAddress = PubKeyToAddress(GenerateNewKey());
|
string strAddress = PubKeyToAddress(CWalletDB().GetKeyFromKeyPool());
|
||||||
|
|
||||||
// Save
|
// Save
|
||||||
SetAddressBookName(strAddress, strName);
|
SetAddressBookName(strAddress, strName);
|
||||||
|
@ -1425,7 +1425,10 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
|
||||||
if (txout.IsMine())
|
if (txout.IsMine())
|
||||||
strHTML += "<b>Credit:</b> " + FormatMoney(txout.GetCredit()) + "<br>";
|
strHTML += "<b>Credit:</b> " + FormatMoney(txout.GetCredit()) + "<br>";
|
||||||
|
|
||||||
strHTML += "<b>Inputs:</b><br>";
|
strHTML += "<br><b>Transaction:</b><br>";
|
||||||
|
strHTML += HtmlEscape(wtx.ToString(), true);
|
||||||
|
|
||||||
|
strHTML += "<br><b>Inputs:</b><br>";
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
CRITICAL_BLOCK(cs_mapWallet)
|
||||||
{
|
{
|
||||||
foreach(const CTxIn& txin, wtx.vin)
|
foreach(const CTxIn& txin, wtx.vin)
|
||||||
|
@ -1444,9 +1447,6 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
strHTML += "<br><hr><br><b>Transaction:</b><br>";
|
|
||||||
strHTML += HtmlEscape(wtx.ToString(), true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2245,9 +2245,9 @@ void CSendingDialog::OnReply2(CDataStream& vRecv)
|
||||||
Error(_("Insufficient funds"));
|
Error(_("Insufficient funds"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CKey key;
|
CReserveKey reservekey;
|
||||||
int64 nFeeRequired;
|
int64 nFeeRequired;
|
||||||
if (!CreateTransaction(scriptPubKey, nPrice, wtx, key, nFeeRequired))
|
if (!CreateTransaction(scriptPubKey, nPrice, wtx, reservekey, nFeeRequired))
|
||||||
{
|
{
|
||||||
if (nPrice + nFeeRequired > GetBalance())
|
if (nPrice + nFeeRequired > GetBalance())
|
||||||
Error(strprintf(_("This is an oversized transaction that requires a transaction fee of %s"), FormatMoney(nFeeRequired).c_str()));
|
Error(strprintf(_("This is an oversized transaction that requires a transaction fee of %s"), FormatMoney(nFeeRequired).c_str()));
|
||||||
|
@ -2287,7 +2287,7 @@ void CSendingDialog::OnReply2(CDataStream& vRecv)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Commit
|
// Commit
|
||||||
if (!CommitTransaction(wtx, key))
|
if (!CommitTransaction(wtx, reservekey))
|
||||||
{
|
{
|
||||||
Error(_("The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."));
|
Error(_("The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."));
|
||||||
return;
|
return;
|
||||||
|
@ -2565,7 +2565,7 @@ void CAddressBookDialog::OnButtonNew(wxCommandEvent& event)
|
||||||
strName = dialog.GetValue();
|
strName = dialog.GetValue();
|
||||||
|
|
||||||
// Generate new key
|
// Generate new key
|
||||||
strAddress = PubKeyToAddress(GenerateNewKey());
|
strAddress = PubKeyToAddress(CWalletDB().GetKeyFromKeyPool());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to list and select it
|
// Add to list and select it
|
||||||
|
|
Loading…
Reference in a new issue