mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-05 14:06:27 -05:00
Merge branch 'master' of https://github.com/bitcoin/bitcoin
This commit is contained in:
commit
d421117620
42 changed files with 2269 additions and 683 deletions
|
@ -83,7 +83,8 @@ HEADERS += src/qt/bitcoingui.h \
|
||||||
src/bitcoinrpc.h \
|
src/bitcoinrpc.h \
|
||||||
src/qt/overviewpage.h \
|
src/qt/overviewpage.h \
|
||||||
src/qt/csvmodelwriter.h \
|
src/qt/csvmodelwriter.h \
|
||||||
src/qt/qtwin.h
|
src/qt/qtwin.h \
|
||||||
|
src/crypter.h
|
||||||
SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
|
SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
|
||||||
src/qt/transactiontablemodel.cpp \
|
src/qt/transactiontablemodel.cpp \
|
||||||
src/qt/addresstablemodel.cpp \
|
src/qt/addresstablemodel.cpp \
|
||||||
|
@ -122,7 +123,8 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
|
||||||
src/bitcoinrpc.cpp \
|
src/bitcoinrpc.cpp \
|
||||||
src/qt/overviewpage.cpp \
|
src/qt/overviewpage.cpp \
|
||||||
src/qt/csvmodelwriter.cpp \
|
src/qt/csvmodelwriter.cpp \
|
||||||
src/qt/qtwin.cpp
|
src/qt/qtwin.cpp \
|
||||||
|
src/crypter.cpp
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
src/qt/bitcoin.qrc
|
src/qt/bitcoin.qrc
|
||||||
|
|
|
@ -17,11 +17,11 @@
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>0.3.24</string>
|
<string>0.3.25</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>324</string>
|
<string>325</string>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
<string>10.5</string>
|
<string>10.5</string>
|
||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
|
|
45
doc/README
45
doc/README
|
@ -1,4 +1,4 @@
|
||||||
Bitcoin 0.3.24 BETA
|
Bitcoin 0.3.25 BETA
|
||||||
|
|
||||||
Copyright (c) 2009-2011 Bitcoin Developers
|
Copyright (c) 2009-2011 Bitcoin Developers
|
||||||
Distributed under the MIT/X11 software license, see the accompanying
|
Distributed under the MIT/X11 software license, see the accompanying
|
||||||
|
@ -24,6 +24,49 @@ Unpack the files into a directory and run:
|
||||||
bin/64/bitcoin (GUI, 64-bit)
|
bin/64/bitcoin (GUI, 64-bit)
|
||||||
bin/64/bitcoind (headless, 64-bit)
|
bin/64/bitcoind (headless, 64-bit)
|
||||||
|
|
||||||
|
|
||||||
|
Wallet Encryption
|
||||||
|
-----------------
|
||||||
|
Bitcoin supports native wallet encryption so that people who steal your
|
||||||
|
wallet file don't automatically get access to all of your Bitcoins.
|
||||||
|
In order to enable this feature, chose "Encrypt Wallet" from the
|
||||||
|
Options menu. You will be prompted to enter a passphrase, which
|
||||||
|
will be used as the key to encrypt your wallet and will be needed
|
||||||
|
every time you wish to send Bitcoins. If you lose this passphrase,
|
||||||
|
you will lose access to spend all of the bitcoins in your wallet,
|
||||||
|
no one, not even the Bitcoin developers can recover your Bitcoins.
|
||||||
|
This means you are responsible for your own security, store your
|
||||||
|
password in a secure location and do not forget it.
|
||||||
|
|
||||||
|
Remember that the encryption built into bitcoin only encrypts the
|
||||||
|
actual keys which are required to send your bitcoins, not the full
|
||||||
|
wallet. This means that someone who steals your wallet file will
|
||||||
|
be able to see all the addresses which belong to you, as well as the
|
||||||
|
relevant transactions, you are only protected from someone spending
|
||||||
|
your coins.
|
||||||
|
|
||||||
|
It is recommended that you backup your wallet file before you
|
||||||
|
encrypt your wallet. To do this, close the Bitcoin client and
|
||||||
|
copy the wallet.dat file from ~/.bitcoin/ on Linux, /Users/(user
|
||||||
|
name)/Application Support/Bitcoin/ on Mac OSX, and %APPDATA%/Bitcoin/
|
||||||
|
on Windows (that is /Users/(user name)/AppData/Roaming/Bitcoin on
|
||||||
|
Windows Vista and 7 and /Documents and Settings/(user name)/Application
|
||||||
|
Data/Bitcoin on Windows XP). Once you have copied that file to a
|
||||||
|
safe location, reopen the Bitcoin client and Encrypt your wallet.
|
||||||
|
If everything goes fine, delete the backup and enjoy your encrypted
|
||||||
|
wallet. Note that once you encrypt your wallet, you will never be
|
||||||
|
able to go back to a version of the Bitcoin client older than 0.4.
|
||||||
|
|
||||||
|
Keep in mind that you are always responsible for you own security.
|
||||||
|
All it takes is a slightly more advanced wallet-stealing trojan which
|
||||||
|
installs a keylogger to steal your wallet passphrase as you enter it
|
||||||
|
in addition to your wallet file and you have lost all your Bitcoins.
|
||||||
|
Wallet encryption cannot keep you safe if you do not practice
|
||||||
|
good security, such as running up-to-date antivirus software, only
|
||||||
|
entering your wallet passphrase in the Bitcoin client and using the
|
||||||
|
same passphrase only as your wallet passphrase.
|
||||||
|
|
||||||
|
|
||||||
See the documentation at the bitcoin wiki:
|
See the documentation at the bitcoin wiki:
|
||||||
https://en.bitcoin.it/wiki/Main_Page
|
https://en.bitcoin.it/wiki/Main_Page
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Bitcoin 0.3.24 BETA
|
Bitcoin 0.3.25 BETA
|
||||||
|
|
||||||
Copyright (c) 2009-2011 Bitcoin Developers
|
Copyright (c) 2009-2011 Bitcoin Developers
|
||||||
Distributed under the MIT/X11 software license, see the accompanying
|
Distributed under the MIT/X11 software license, see the accompanying
|
||||||
|
|
File diff suppressed because it is too large
Load diff
BIN
locale/sv/LC_MESSAGES/bitcoin.mo
Normal file
BIN
locale/sv/LC_MESSAGES/bitcoin.mo
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 91 KiB |
BIN
share/pixmaps/nsis-header.bmp
Normal file
BIN
share/pixmaps/nsis-header.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
BIN
share/pixmaps/nsis-wizard.bmp
Normal file
BIN
share/pixmaps/nsis-wizard.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 151 KiB |
|
@ -1,15 +1,20 @@
|
||||||
Name Bitcoin
|
Name Bitcoin
|
||||||
|
|
||||||
RequestExecutionLevel highest
|
RequestExecutionLevel highest
|
||||||
|
SetCompressor /SOLID lzma
|
||||||
|
|
||||||
# General Symbol Definitions
|
# General Symbol Definitions
|
||||||
!define REGKEY "SOFTWARE\$(^Name)"
|
!define REGKEY "SOFTWARE\$(^Name)"
|
||||||
!define VERSION 0.3.24
|
!define VERSION 0.3.25
|
||||||
!define COMPANY "Bitcoin project"
|
!define COMPANY "Bitcoin project"
|
||||||
!define URL http://www.bitcoin.org/
|
!define URL http://www.bitcoin.org/
|
||||||
|
|
||||||
# MUI Symbol Definitions
|
# MUI Symbol Definitions
|
||||||
!define MUI_ICON "../share/pixmaps/bitcoin.ico"
|
!define MUI_ICON "../share/pixmaps/bitcoin.ico"
|
||||||
|
!define MUI_WELCOMEFINISHPAGE_BITMAP "../share/pixmaps/nsis-wizard.bmp"
|
||||||
|
!define MUI_HEADERIMAGE
|
||||||
|
!define MUI_HEADERIMAGE_RIGHT
|
||||||
|
!define MUI_HEADERIMAGE_BITMAP "../share/pixmaps/nsis-header.bmp"
|
||||||
!define MUI_FINISHPAGE_NOAUTOCLOSE
|
!define MUI_FINISHPAGE_NOAUTOCLOSE
|
||||||
!define MUI_STARTMENUPAGE_REGISTRY_ROOT HKLM
|
!define MUI_STARTMENUPAGE_REGISTRY_ROOT HKLM
|
||||||
!define MUI_STARTMENUPAGE_REGISTRY_KEY ${REGKEY}
|
!define MUI_STARTMENUPAGE_REGISTRY_KEY ${REGKEY}
|
||||||
|
@ -17,6 +22,7 @@ RequestExecutionLevel highest
|
||||||
!define MUI_STARTMENUPAGE_DEFAULTFOLDER Bitcoin
|
!define MUI_STARTMENUPAGE_DEFAULTFOLDER Bitcoin
|
||||||
!define MUI_FINISHPAGE_RUN $INSTDIR\bitcoin.exe
|
!define MUI_FINISHPAGE_RUN $INSTDIR\bitcoin.exe
|
||||||
!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"
|
!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"
|
||||||
|
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "../share/pixmaps/nsis-wizard.bmp"
|
||||||
!define MUI_UNFINISHPAGE_NOAUTOCLOSE
|
!define MUI_UNFINISHPAGE_NOAUTOCLOSE
|
||||||
|
|
||||||
# Included files
|
# Included files
|
||||||
|
@ -39,12 +45,13 @@ Var StartMenuGroup
|
||||||
!insertmacro MUI_LANGUAGE English
|
!insertmacro MUI_LANGUAGE English
|
||||||
|
|
||||||
# Installer attributes
|
# Installer attributes
|
||||||
OutFile bitcoin-0.3.24-win32-setup.exe
|
OutFile bitcoin-0.3.25-win32-setup.exe
|
||||||
InstallDir $PROGRAMFILES\Bitcoin
|
InstallDir $PROGRAMFILES\Bitcoin
|
||||||
CRCCheck on
|
CRCCheck on
|
||||||
XPStyle on
|
XPStyle on
|
||||||
|
BrandingText " "
|
||||||
ShowInstDetails show
|
ShowInstDetails show
|
||||||
VIProductVersion 0.3.24.0
|
VIProductVersion 0.3.25.0
|
||||||
VIAddVersionKey ProductName Bitcoin
|
VIAddVersionKey ProductName Bitcoin
|
||||||
VIAddVersionKey ProductVersion "${VERSION}"
|
VIAddVersionKey ProductVersion "${VERSION}"
|
||||||
VIAddVersionKey CompanyName "${COMPANY}"
|
VIAddVersionKey CompanyName "${COMPANY}"
|
||||||
|
|
|
@ -162,6 +162,36 @@
|
||||||
<event name="OnMenuSelection">OnMenuOptionsChangeYourAddress</event>
|
<event name="OnMenuSelection">OnMenuOptionsChangeYourAddress</event>
|
||||||
<event name="OnUpdateUI"></event>
|
<event name="OnUpdateUI"></event>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="wxMenuItem" expanded="1">
|
||||||
|
<property name="bitmap"></property>
|
||||||
|
<property name="checked">0</property>
|
||||||
|
<property name="enabled">1</property>
|
||||||
|
<property name="help"></property>
|
||||||
|
<property name="id">wxID_ANY</property>
|
||||||
|
<property name="kind">wxITEM_NORMAL</property>
|
||||||
|
<property name="label">&Encrypt Wallet...</property>
|
||||||
|
<property name="name">m_menuOptionsEncryptWallet</property>
|
||||||
|
<property name="permission">public</property>
|
||||||
|
<property name="shortcut"></property>
|
||||||
|
<property name="unchecked_bitmap"></property>
|
||||||
|
<event name="OnMenuSelection">OnMenuOptionsEncryptWallet</event>
|
||||||
|
<event name="OnUpdateUI"></event>
|
||||||
|
</object>
|
||||||
|
<object class="wxMenuItem" expanded="1">
|
||||||
|
<property name="bitmap"></property>
|
||||||
|
<property name="checked">0</property>
|
||||||
|
<property name="enabled">1</property>
|
||||||
|
<property name="help"></property>
|
||||||
|
<property name="id">wxID_ANY</property>
|
||||||
|
<property name="kind">wxITEM_NORMAL</property>
|
||||||
|
<property name="label">&Change Wallet Encryption Passphrase...</property>
|
||||||
|
<property name="name">m_menuOptionsChangeWalletPassphrase</property>
|
||||||
|
<property name="permission">public</property>
|
||||||
|
<property name="shortcut"></property>
|
||||||
|
<property name="unchecked_bitmap"></property>
|
||||||
|
<event name="OnMenuSelection">OnMenuOptionsChangeWalletPassphrase</event>
|
||||||
|
<event name="OnUpdateUI"></event>
|
||||||
|
</object>
|
||||||
<object class="wxMenuItem" expanded="1">
|
<object class="wxMenuItem" expanded="1">
|
||||||
<property name="bitmap"></property>
|
<property name="bitmap"></property>
|
||||||
<property name="checked">0</property>
|
<property name="checked">0</property>
|
||||||
|
|
|
@ -36,6 +36,9 @@ void ThreadRPCServer2(void* parg);
|
||||||
typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
|
typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
|
||||||
extern map<string, rpcfn_type> mapCallTable;
|
extern map<string, rpcfn_type> mapCallTable;
|
||||||
|
|
||||||
|
static int64 nWalletUnlockTime;
|
||||||
|
static CCriticalSection cs_nWalletUnlockTime;
|
||||||
|
|
||||||
|
|
||||||
Object JSONRPCError(int code, const string& message)
|
Object JSONRPCError(int code, const string& message)
|
||||||
{
|
{
|
||||||
|
@ -309,7 +312,10 @@ Value getinfo(const Array& params, bool fHelp)
|
||||||
obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
|
obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
|
||||||
obj.push_back(Pair("testnet", fTestNet));
|
obj.push_back(Pair("testnet", fTestNet));
|
||||||
obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
|
obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
|
||||||
|
obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
|
||||||
obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
|
obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
|
||||||
|
if (pwalletMain->IsCrypted())
|
||||||
|
obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
|
||||||
obj.push_back(Pair("errors", GetWarnings("statusbar")));
|
obj.push_back(Pair("errors", GetWarnings("statusbar")));
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
@ -324,13 +330,19 @@ Value getnewaddress(const Array& params, bool fHelp)
|
||||||
"If [account] is specified (recommended), it is added to the address book "
|
"If [account] is specified (recommended), it is added to the address book "
|
||||||
"so payments received with the address will be credited to [account].");
|
"so payments received with the address will be credited to [account].");
|
||||||
|
|
||||||
|
if (!pwalletMain->IsLocked())
|
||||||
|
pwalletMain->TopUpKeyPool();
|
||||||
|
|
||||||
|
if (pwalletMain->GetKeyPoolSize() < 1)
|
||||||
|
throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
|
||||||
|
|
||||||
// Parse the account first so we don't generate a key if there's an error
|
// Parse the account first so we don't generate a key if there's an error
|
||||||
string strAccount;
|
string strAccount;
|
||||||
if (params.size() > 0)
|
if (params.size() > 0)
|
||||||
strAccount = AccountFromValue(params[0]);
|
strAccount = AccountFromValue(params[0]);
|
||||||
|
|
||||||
// Generate a new key that is added to wallet
|
// Generate a new key that is added to wallet
|
||||||
string strAddress = PubKeyToAddress(pwalletMain->GetKeyFromKeyPool());
|
string strAddress = PubKeyToAddress(pwalletMain->GetOrReuseKeyFromPool());
|
||||||
|
|
||||||
// This could be done in the same main CS as GetKeyFromKeyPool.
|
// This could be done in the same main CS as GetKeyFromKeyPool.
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
||||||
|
@ -346,37 +358,48 @@ string GetAccountAddress(string strAccount, bool bForceNew=false)
|
||||||
string strAddress;
|
string strAddress;
|
||||||
|
|
||||||
CWalletDB walletdb(pwalletMain->strWalletFile);
|
CWalletDB walletdb(pwalletMain->strWalletFile);
|
||||||
walletdb.TxnBegin();
|
|
||||||
|
|
||||||
CAccount account;
|
CAccount account;
|
||||||
walletdb.ReadAccount(strAccount, account);
|
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
||||||
|
|
||||||
// Check if the current key has been used
|
|
||||||
if (!account.vchPubKey.empty())
|
|
||||||
{
|
{
|
||||||
CScript scriptPubKey;
|
walletdb.ReadAccount(strAccount, account);
|
||||||
scriptPubKey.SetBitcoinAddress(account.vchPubKey);
|
|
||||||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
|
bool bKeyUsed = false;
|
||||||
it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
|
|
||||||
++it)
|
// Check if the current key has been used
|
||||||
|
if (!account.vchPubKey.empty())
|
||||||
{
|
{
|
||||||
const CWalletTx& wtx = (*it).second;
|
CScript scriptPubKey;
|
||||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
scriptPubKey.SetBitcoinAddress(account.vchPubKey);
|
||||||
if (txout.scriptPubKey == scriptPubKey)
|
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
|
||||||
account.vchPubKey.clear();
|
it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
|
||||||
|
++it)
|
||||||
|
{
|
||||||
|
const CWalletTx& wtx = (*it).second;
|
||||||
|
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||||
|
if (txout.scriptPubKey == scriptPubKey)
|
||||||
|
bKeyUsed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a new key
|
||||||
|
if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
|
||||||
|
{
|
||||||
|
if (pwalletMain->GetKeyPoolSize() < 1)
|
||||||
|
{
|
||||||
|
if (bKeyUsed || bForceNew)
|
||||||
|
throw JSONRPCError(-12, "Error: Keypool ran out, please call topupkeypool first");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
account.vchPubKey = pwalletMain->GetOrReuseKeyFromPool();
|
||||||
|
string strAddress = PubKeyToAddress(account.vchPubKey);
|
||||||
|
pwalletMain->SetAddressBookName(strAddress, strAccount);
|
||||||
|
walletdb.WriteAccount(strAccount, account);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a new key
|
|
||||||
if (account.vchPubKey.empty() || bForceNew)
|
|
||||||
{
|
|
||||||
account.vchPubKey = pwalletMain->GetKeyFromKeyPool();
|
|
||||||
string strAddress = PubKeyToAddress(account.vchPubKey);
|
|
||||||
pwalletMain->SetAddressBookName(strAddress, strAccount);
|
|
||||||
walletdb.WriteAccount(strAccount, account);
|
|
||||||
}
|
|
||||||
|
|
||||||
walletdb.TxnCommit();
|
|
||||||
strAddress = PubKeyToAddress(account.vchPubKey);
|
strAddress = PubKeyToAddress(account.vchPubKey);
|
||||||
|
|
||||||
return strAddress;
|
return strAddress;
|
||||||
|
@ -510,7 +533,12 @@ Value settxfee(const Array& params, bool fHelp)
|
||||||
|
|
||||||
Value sendtoaddress(const Array& params, bool fHelp)
|
Value sendtoaddress(const Array& params, bool fHelp)
|
||||||
{
|
{
|
||||||
if (fHelp || params.size() < 2 || params.size() > 4)
|
if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
|
||||||
|
throw runtime_error(
|
||||||
|
"sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
|
||||||
|
"<amount> is a real and is rounded to the nearest 0.00000001\n"
|
||||||
|
"requires wallet passphrase to be set with walletpassphrase first");
|
||||||
|
if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
|
"sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
|
||||||
"<amount> is a real and is rounded to the nearest 0.00000001");
|
"<amount> is a real and is rounded to the nearest 0.00000001");
|
||||||
|
@ -528,7 +556,11 @@ Value sendtoaddress(const Array& params, bool fHelp)
|
||||||
wtx.mapValue["to"] = params[3].get_str();
|
wtx.mapValue["to"] = params[3].get_str();
|
||||||
|
|
||||||
CRITICAL_BLOCK(cs_main)
|
CRITICAL_BLOCK(cs_main)
|
||||||
|
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
|
||||||
{
|
{
|
||||||
|
if(pwalletMain->IsLocked())
|
||||||
|
throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
|
||||||
|
|
||||||
string strError = pwalletMain->SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
|
string strError = pwalletMain->SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
|
||||||
if (strError != "")
|
if (strError != "")
|
||||||
throw JSONRPCError(-4, strError);
|
throw JSONRPCError(-4, strError);
|
||||||
|
@ -674,7 +706,7 @@ int64 GetAccountBalance(const string& strAccount, int nMinDepth)
|
||||||
|
|
||||||
Value getbalance(const Array& params, bool fHelp)
|
Value getbalance(const Array& params, bool fHelp)
|
||||||
{
|
{
|
||||||
if (fHelp || params.size() < 0 || params.size() > 2)
|
if (fHelp || params.size() > 2)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"getbalance [account] [minconf=1]\n"
|
"getbalance [account] [minconf=1]\n"
|
||||||
"If [account] is not specified, returns the server's total available balance.\n"
|
"If [account] is not specified, returns the server's total available balance.\n"
|
||||||
|
@ -733,9 +765,9 @@ Value movecmd(const Array& params, bool fHelp)
|
||||||
string strFrom = AccountFromValue(params[0]);
|
string strFrom = AccountFromValue(params[0]);
|
||||||
string strTo = AccountFromValue(params[1]);
|
string strTo = AccountFromValue(params[1]);
|
||||||
int64 nAmount = AmountFromValue(params[2]);
|
int64 nAmount = AmountFromValue(params[2]);
|
||||||
int nMinDepth = 1;
|
|
||||||
if (params.size() > 3)
|
if (params.size() > 3)
|
||||||
nMinDepth = params[3].get_int();
|
// unused parameter, used to be nMinDepth, keep type-checking it though
|
||||||
|
(void)params[3].get_int();
|
||||||
string strComment;
|
string strComment;
|
||||||
if (params.size() > 4)
|
if (params.size() > 4)
|
||||||
strComment = params[4].get_str();
|
strComment = params[4].get_str();
|
||||||
|
@ -773,7 +805,12 @@ Value movecmd(const Array& params, bool fHelp)
|
||||||
|
|
||||||
Value sendfrom(const Array& params, bool fHelp)
|
Value sendfrom(const Array& params, bool fHelp)
|
||||||
{
|
{
|
||||||
if (fHelp || params.size() < 3 || params.size() > 6)
|
if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
|
||||||
|
throw runtime_error(
|
||||||
|
"sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
|
||||||
|
"<amount> is a real and is rounded to the nearest 0.00000001\n"
|
||||||
|
"requires wallet passphrase to be set with walletpassphrase first");
|
||||||
|
if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
|
"sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
|
||||||
"<amount> is a real and is rounded to the nearest 0.00000001");
|
"<amount> is a real and is rounded to the nearest 0.00000001");
|
||||||
|
@ -794,7 +831,11 @@ Value sendfrom(const Array& params, bool fHelp)
|
||||||
|
|
||||||
CRITICAL_BLOCK(cs_main)
|
CRITICAL_BLOCK(cs_main)
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
||||||
|
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
|
||||||
{
|
{
|
||||||
|
if(pwalletMain->IsLocked())
|
||||||
|
throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
|
||||||
|
|
||||||
// Check funds
|
// Check funds
|
||||||
int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
|
int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
|
||||||
if (nAmount > nBalance)
|
if (nAmount > nBalance)
|
||||||
|
@ -809,9 +850,15 @@ Value sendfrom(const Array& params, bool fHelp)
|
||||||
return wtx.GetHash().GetHex();
|
return wtx.GetHash().GetHex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Value sendmany(const Array& params, bool fHelp)
|
Value sendmany(const Array& params, bool fHelp)
|
||||||
{
|
{
|
||||||
if (fHelp || params.size() < 2 || params.size() > 4)
|
if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
|
||||||
|
throw runtime_error(
|
||||||
|
"sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
|
||||||
|
"amounts are double-precision floating point numbers\n"
|
||||||
|
"requires wallet passphrase to be set with walletpassphrase first");
|
||||||
|
if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
|
"sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
|
||||||
"amounts are double-precision floating point numbers");
|
"amounts are double-precision floating point numbers");
|
||||||
|
@ -851,7 +898,11 @@ Value sendmany(const Array& params, bool fHelp)
|
||||||
|
|
||||||
CRITICAL_BLOCK(cs_main)
|
CRITICAL_BLOCK(cs_main)
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
||||||
|
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
|
||||||
{
|
{
|
||||||
|
if(pwalletMain->IsLocked())
|
||||||
|
throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
|
||||||
|
|
||||||
// Check funds
|
// Check funds
|
||||||
int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
|
int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
|
||||||
if (totalAmount > nBalance)
|
if (totalAmount > nBalance)
|
||||||
|
@ -1281,6 +1332,219 @@ Value backupwallet(const Array& params, bool fHelp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Value keypoolrefill(const Array& params, bool fHelp)
|
||||||
|
{
|
||||||
|
if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
|
||||||
|
throw runtime_error(
|
||||||
|
"keypoolrefill\n"
|
||||||
|
"Fills the keypool, requires wallet passphrase to be set.");
|
||||||
|
if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
|
||||||
|
throw runtime_error(
|
||||||
|
"keypoolrefill\n"
|
||||||
|
"Fills the keypool.");
|
||||||
|
|
||||||
|
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
|
||||||
|
{
|
||||||
|
if (pwalletMain->IsLocked())
|
||||||
|
throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
|
||||||
|
|
||||||
|
pwalletMain->TopUpKeyPool();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
|
||||||
|
throw JSONRPCError(-4, "Error refreshing keypool.");
|
||||||
|
|
||||||
|
return Value::null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ThreadTopUpKeyPool(void* parg)
|
||||||
|
{
|
||||||
|
pwalletMain->TopUpKeyPool();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThreadCleanWalletPassphrase(void* parg)
|
||||||
|
{
|
||||||
|
int64 nMyWakeTime = GetTime() + *((int*)parg);
|
||||||
|
|
||||||
|
if (nWalletUnlockTime == 0)
|
||||||
|
{
|
||||||
|
CRITICAL_BLOCK(cs_nWalletUnlockTime)
|
||||||
|
{
|
||||||
|
nWalletUnlockTime = nMyWakeTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (GetTime() < nWalletUnlockTime)
|
||||||
|
Sleep(GetTime() - nWalletUnlockTime);
|
||||||
|
|
||||||
|
CRITICAL_BLOCK(cs_nWalletUnlockTime)
|
||||||
|
{
|
||||||
|
nWalletUnlockTime = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CRITICAL_BLOCK(cs_nWalletUnlockTime)
|
||||||
|
{
|
||||||
|
if (nWalletUnlockTime < nMyWakeTime)
|
||||||
|
nWalletUnlockTime = nMyWakeTime;
|
||||||
|
}
|
||||||
|
free(parg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pwalletMain->Lock();
|
||||||
|
|
||||||
|
delete (int*)parg;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value walletpassphrase(const Array& params, bool fHelp)
|
||||||
|
{
|
||||||
|
if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
|
||||||
|
throw runtime_error(
|
||||||
|
"walletpassphrase <passphrase> <timeout>\n"
|
||||||
|
"Stores the wallet decryption key in memory for <timeout> seconds.");
|
||||||
|
if (fHelp)
|
||||||
|
return true;
|
||||||
|
if (!pwalletMain->IsCrypted())
|
||||||
|
throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
|
||||||
|
|
||||||
|
if (!pwalletMain->IsLocked())
|
||||||
|
throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
|
||||||
|
|
||||||
|
// Note that the walletpassphrase is stored in params[0] which is not mlock()ed
|
||||||
|
string strWalletPass;
|
||||||
|
strWalletPass.reserve(100);
|
||||||
|
mlock(&strWalletPass[0], strWalletPass.capacity());
|
||||||
|
strWalletPass = params[0].get_str();
|
||||||
|
|
||||||
|
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
|
||||||
|
{
|
||||||
|
if (strWalletPass.length() > 0)
|
||||||
|
{
|
||||||
|
if (!pwalletMain->Unlock(strWalletPass))
|
||||||
|
{
|
||||||
|
fill(strWalletPass.begin(), strWalletPass.end(), '\0');
|
||||||
|
munlock(&strWalletPass[0], strWalletPass.capacity());
|
||||||
|
throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
|
||||||
|
}
|
||||||
|
fill(strWalletPass.begin(), strWalletPass.end(), '\0');
|
||||||
|
munlock(&strWalletPass[0], strWalletPass.capacity());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw runtime_error(
|
||||||
|
"walletpassphrase <passphrase> <timeout>\n"
|
||||||
|
"Stores the wallet decryption key in memory for <timeout> seconds.");
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateThread(ThreadTopUpKeyPool, NULL);
|
||||||
|
int* pnSleepTime = new int(params[1].get_int());
|
||||||
|
CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
|
||||||
|
|
||||||
|
return Value::null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Value walletpassphrasechange(const Array& params, bool fHelp)
|
||||||
|
{
|
||||||
|
if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
|
||||||
|
throw runtime_error(
|
||||||
|
"walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
|
||||||
|
"Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
|
||||||
|
if (fHelp)
|
||||||
|
return true;
|
||||||
|
if (!pwalletMain->IsCrypted())
|
||||||
|
throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
|
||||||
|
|
||||||
|
string strOldWalletPass;
|
||||||
|
strOldWalletPass.reserve(100);
|
||||||
|
mlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
||||||
|
strOldWalletPass = params[0].get_str();
|
||||||
|
|
||||||
|
string strNewWalletPass;
|
||||||
|
strNewWalletPass.reserve(100);
|
||||||
|
mlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
||||||
|
strNewWalletPass = params[1].get_str();
|
||||||
|
|
||||||
|
if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
|
||||||
|
throw runtime_error(
|
||||||
|
"walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
|
||||||
|
"Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
|
||||||
|
|
||||||
|
if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
|
||||||
|
{
|
||||||
|
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
|
||||||
|
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
|
||||||
|
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
||||||
|
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
||||||
|
throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
|
||||||
|
}
|
||||||
|
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
|
||||||
|
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
|
||||||
|
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
||||||
|
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
||||||
|
|
||||||
|
return Value::null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Value walletlock(const Array& params, bool fHelp)
|
||||||
|
{
|
||||||
|
if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
|
||||||
|
throw runtime_error(
|
||||||
|
"walletlock\n"
|
||||||
|
"Removes the wallet encryption key from memory, locking the wallet.\n"
|
||||||
|
"After calling this method, you will need to call walletpassphrase again\n"
|
||||||
|
"before being able to call any methods which require the wallet to be unlocked.");
|
||||||
|
if (fHelp)
|
||||||
|
return true;
|
||||||
|
if (!pwalletMain->IsCrypted())
|
||||||
|
throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
|
||||||
|
|
||||||
|
pwalletMain->Lock();
|
||||||
|
CRITICAL_BLOCK(cs_nWalletUnlockTime)
|
||||||
|
{
|
||||||
|
nWalletUnlockTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Value::null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Value encryptwallet(const Array& params, bool fHelp)
|
||||||
|
{
|
||||||
|
if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
|
||||||
|
throw runtime_error(
|
||||||
|
"encryptwallet <passphrase>\n"
|
||||||
|
"Encrypts the wallet with <passphrase>.");
|
||||||
|
if (fHelp)
|
||||||
|
return true;
|
||||||
|
if (pwalletMain->IsCrypted())
|
||||||
|
throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
|
||||||
|
|
||||||
|
string strWalletPass;
|
||||||
|
strWalletPass.reserve(100);
|
||||||
|
mlock(&strWalletPass[0], strWalletPass.capacity());
|
||||||
|
strWalletPass = params[0].get_str();
|
||||||
|
|
||||||
|
if (strWalletPass.length() < 1)
|
||||||
|
throw runtime_error(
|
||||||
|
"encryptwallet <passphrase>\n"
|
||||||
|
"Encrypts the wallet with <passphrase>.");
|
||||||
|
|
||||||
|
if (!pwalletMain->EncryptWallet(strWalletPass))
|
||||||
|
{
|
||||||
|
fill(strWalletPass.begin(), strWalletPass.end(), '\0');
|
||||||
|
munlock(&strWalletPass[0], strWalletPass.capacity());
|
||||||
|
throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
|
||||||
|
}
|
||||||
|
fill(strWalletPass.begin(), strWalletPass.end(), '\0');
|
||||||
|
munlock(&strWalletPass[0], strWalletPass.capacity());
|
||||||
|
|
||||||
|
return Value::null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Value validateaddress(const Array& params, bool fHelp)
|
Value validateaddress(const Array& params, bool fHelp)
|
||||||
{
|
{
|
||||||
if (fHelp || params.size() != 1)
|
if (fHelp || params.size() != 1)
|
||||||
|
@ -1432,44 +1696,49 @@ Value getwork(const Array& params, bool fHelp)
|
||||||
|
|
||||||
pair<string, rpcfn_type> pCallTable[] =
|
pair<string, rpcfn_type> pCallTable[] =
|
||||||
{
|
{
|
||||||
make_pair("help", &help),
|
make_pair("help", &help),
|
||||||
make_pair("stop", &stop),
|
make_pair("stop", &stop),
|
||||||
make_pair("getblockcount", &getblockcount),
|
make_pair("getblockcount", &getblockcount),
|
||||||
make_pair("getblocknumber", &getblocknumber),
|
make_pair("getblocknumber", &getblocknumber),
|
||||||
make_pair("getconnectioncount", &getconnectioncount),
|
make_pair("getconnectioncount", &getconnectioncount),
|
||||||
make_pair("getdifficulty", &getdifficulty),
|
make_pair("getdifficulty", &getdifficulty),
|
||||||
make_pair("getgenerate", &getgenerate),
|
make_pair("getgenerate", &getgenerate),
|
||||||
make_pair("setgenerate", &setgenerate),
|
make_pair("setgenerate", &setgenerate),
|
||||||
make_pair("gethashespersec", &gethashespersec),
|
make_pair("gethashespersec", &gethashespersec),
|
||||||
make_pair("getinfo", &getinfo),
|
make_pair("getinfo", &getinfo),
|
||||||
make_pair("getnewaddress", &getnewaddress),
|
make_pair("getnewaddress", &getnewaddress),
|
||||||
make_pair("getaccountaddress", &getaccountaddress),
|
make_pair("getaccountaddress", &getaccountaddress),
|
||||||
make_pair("setaccount", &setaccount),
|
make_pair("setaccount", &setaccount),
|
||||||
make_pair("setlabel", &setaccount), // deprecated
|
make_pair("setlabel", &setaccount), // deprecated
|
||||||
make_pair("getaccount", &getaccount),
|
make_pair("getaccount", &getaccount),
|
||||||
make_pair("getlabel", &getaccount), // deprecated
|
make_pair("getlabel", &getaccount), // deprecated
|
||||||
make_pair("getaddressesbyaccount", &getaddressesbyaccount),
|
make_pair("getaddressesbyaccount", &getaddressesbyaccount),
|
||||||
make_pair("getaddressesbylabel", &getaddressesbyaccount), // deprecated
|
make_pair("getaddressesbylabel", &getaddressesbyaccount), // deprecated
|
||||||
make_pair("sendtoaddress", &sendtoaddress),
|
make_pair("sendtoaddress", &sendtoaddress),
|
||||||
make_pair("getamountreceived", &getreceivedbyaddress), // deprecated, renamed to getreceivedbyaddress
|
make_pair("getamountreceived", &getreceivedbyaddress), // deprecated, renamed to getreceivedbyaddress
|
||||||
make_pair("getallreceived", &listreceivedbyaddress), // deprecated, renamed to listreceivedbyaddress
|
make_pair("getallreceived", &listreceivedbyaddress), // deprecated, renamed to listreceivedbyaddress
|
||||||
make_pair("getreceivedbyaddress", &getreceivedbyaddress),
|
make_pair("getreceivedbyaddress", &getreceivedbyaddress),
|
||||||
make_pair("getreceivedbyaccount", &getreceivedbyaccount),
|
make_pair("getreceivedbyaccount", &getreceivedbyaccount),
|
||||||
make_pair("getreceivedbylabel", &getreceivedbyaccount), // deprecated
|
make_pair("getreceivedbylabel", &getreceivedbyaccount), // deprecated
|
||||||
make_pair("listreceivedbyaddress", &listreceivedbyaddress),
|
make_pair("listreceivedbyaddress", &listreceivedbyaddress),
|
||||||
make_pair("listreceivedbyaccount", &listreceivedbyaccount),
|
make_pair("listreceivedbyaccount", &listreceivedbyaccount),
|
||||||
make_pair("listreceivedbylabel", &listreceivedbyaccount), // deprecated
|
make_pair("listreceivedbylabel", &listreceivedbyaccount), // deprecated
|
||||||
make_pair("backupwallet", &backupwallet),
|
make_pair("backupwallet", &backupwallet),
|
||||||
make_pair("validateaddress", &validateaddress),
|
make_pair("keypoolrefill", &keypoolrefill),
|
||||||
make_pair("getbalance", &getbalance),
|
make_pair("walletpassphrase", &walletpassphrase),
|
||||||
make_pair("move", &movecmd),
|
make_pair("walletpassphrasechange", &walletpassphrasechange),
|
||||||
make_pair("sendfrom", &sendfrom),
|
make_pair("walletlock", &walletlock),
|
||||||
make_pair("sendmany", &sendmany),
|
make_pair("encryptwallet", &encryptwallet),
|
||||||
make_pair("gettransaction", &gettransaction),
|
make_pair("validateaddress", &validateaddress),
|
||||||
make_pair("listtransactions", &listtransactions),
|
make_pair("getbalance", &getbalance),
|
||||||
make_pair("getwork", &getwork),
|
make_pair("move", &movecmd),
|
||||||
make_pair("listaccounts", &listaccounts),
|
make_pair("sendfrom", &sendfrom),
|
||||||
make_pair("settxfee", &settxfee),
|
make_pair("sendmany", &sendmany),
|
||||||
|
make_pair("gettransaction", &gettransaction),
|
||||||
|
make_pair("listtransactions", &listtransactions),
|
||||||
|
make_pair("getwork", &getwork),
|
||||||
|
make_pair("listaccounts", &listaccounts),
|
||||||
|
make_pair("settxfee", &settxfee),
|
||||||
};
|
};
|
||||||
map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
|
map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
|
||||||
|
|
||||||
|
@ -1493,6 +1762,9 @@ string pAllowInSafeMode[] =
|
||||||
"getaddressesbyaccount",
|
"getaddressesbyaccount",
|
||||||
"getaddressesbylabel", // deprecated
|
"getaddressesbylabel", // deprecated
|
||||||
"backupwallet",
|
"backupwallet",
|
||||||
|
"keypoolrefill",
|
||||||
|
"walletpassphrase",
|
||||||
|
"walletlock",
|
||||||
"validateaddress",
|
"validateaddress",
|
||||||
"getwork",
|
"getwork",
|
||||||
};
|
};
|
||||||
|
@ -2130,6 +2402,7 @@ int CommandLineRPC(int argc, char *argv[])
|
||||||
if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
|
if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
|
||||||
if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
|
if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
|
||||||
if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
|
if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
|
||||||
|
if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
|
||||||
if (strMethod == "sendmany" && n > 1)
|
if (strMethod == "sendmany" && n > 1)
|
||||||
{
|
{
|
||||||
string s = params[1].get_str();
|
string s = params[1].get_str();
|
||||||
|
@ -2146,7 +2419,6 @@ int CommandLineRPC(int argc, char *argv[])
|
||||||
// Parse reply
|
// Parse reply
|
||||||
const Value& result = find_value(reply, "result");
|
const Value& result = find_value(reply, "result");
|
||||||
const Value& error = find_value(reply, "error");
|
const Value& error = find_value(reply, "error");
|
||||||
const Value& id = find_value(reply, "id");
|
|
||||||
|
|
||||||
if (error.type() != null_type)
|
if (error.type() != null_type)
|
||||||
{
|
{
|
||||||
|
|
132
src/crypter.cpp
Normal file
132
src/crypter.cpp
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
// Copyright (c) 2011 The Bitcoin Developers
|
||||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include <openssl/aes.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include "headers.h"
|
||||||
|
#ifdef __WXMSW__
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "crypter.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
bool CCrypter::SetKeyFromPassphrase(const std::string& strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
|
||||||
|
{
|
||||||
|
if (nRounds < 1 || chSalt.size() != WALLET_CRYPTO_SALT_SIZE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Try to keep the keydata out of swap (and be a bit over-careful to keep the IV that we don't even use out of swap)
|
||||||
|
// Note that this does nothing about suspend-to-disk (which will put all our key data on disk)
|
||||||
|
// Note as well that at no point in this program is any attempt made to prevent stealing of keys by reading the memory of the running process.
|
||||||
|
mlock(&chKey[0], sizeof chKey);
|
||||||
|
mlock(&chIV[0], sizeof chIV);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
if (nDerivationMethod == 0)
|
||||||
|
i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt[0],
|
||||||
|
(unsigned char *)&strKeyData[0], strKeyData.size(), nRounds, chKey, chIV);
|
||||||
|
|
||||||
|
if (i != WALLET_CRYPTO_KEY_SIZE)
|
||||||
|
{
|
||||||
|
memset(&chKey, 0, sizeof chKey);
|
||||||
|
memset(&chIV, 0, sizeof chIV);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fKeySet = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCrypter::SetKey(const CKeyingMaterial& chNewKey, const std::vector<unsigned char>& chNewIV)
|
||||||
|
{
|
||||||
|
if (chNewKey.size() != WALLET_CRYPTO_KEY_SIZE || chNewIV.size() != WALLET_CRYPTO_KEY_SIZE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Try to keep the keydata out of swap
|
||||||
|
// Note that this does nothing about suspend-to-disk (which will put all our key data on disk)
|
||||||
|
// Note as well that at no point in this program is any attempt made to prevent stealing of keys by reading the memory of the running process.
|
||||||
|
mlock(&chKey[0], sizeof chKey);
|
||||||
|
mlock(&chIV[0], sizeof chIV);
|
||||||
|
|
||||||
|
memcpy(&chKey[0], &chNewKey[0], sizeof chKey);
|
||||||
|
memcpy(&chIV[0], &chNewIV[0], sizeof chIV);
|
||||||
|
|
||||||
|
fKeySet = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCrypter::Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned char> &vchCiphertext)
|
||||||
|
{
|
||||||
|
if (!fKeySet)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// max ciphertext len for a n bytes of plaintext is
|
||||||
|
// n + AES_BLOCK_SIZE - 1 bytes
|
||||||
|
int nLen = vchPlaintext.size();
|
||||||
|
int nCLen = nLen + AES_BLOCK_SIZE, nFLen = 0;
|
||||||
|
vchCiphertext = std::vector<unsigned char> (nCLen);
|
||||||
|
|
||||||
|
EVP_CIPHER_CTX ctx;
|
||||||
|
|
||||||
|
EVP_CIPHER_CTX_init(&ctx);
|
||||||
|
EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV);
|
||||||
|
|
||||||
|
EVP_EncryptUpdate(&ctx, &vchCiphertext[0], &nCLen, &vchPlaintext[0], nLen);
|
||||||
|
EVP_EncryptFinal_ex(&ctx, (&vchCiphertext[0])+nCLen, &nFLen);
|
||||||
|
|
||||||
|
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||||
|
|
||||||
|
vchCiphertext.resize(nCLen + nFLen);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCrypter::Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingMaterial& vchPlaintext)
|
||||||
|
{
|
||||||
|
if (!fKeySet)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// plaintext will always be equal to or lesser than length of ciphertext
|
||||||
|
int nLen = vchCiphertext.size();
|
||||||
|
int nPLen = nLen, nFLen = 0;
|
||||||
|
|
||||||
|
vchPlaintext = CKeyingMaterial(nPLen);
|
||||||
|
|
||||||
|
EVP_CIPHER_CTX ctx;
|
||||||
|
|
||||||
|
EVP_CIPHER_CTX_init(&ctx);
|
||||||
|
EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV);
|
||||||
|
|
||||||
|
EVP_DecryptUpdate(&ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen);
|
||||||
|
EVP_DecryptFinal_ex(&ctx, (&vchPlaintext[0])+nPLen, &nFLen);
|
||||||
|
|
||||||
|
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||||
|
|
||||||
|
vchPlaintext.resize(nPLen + nFLen);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool EncryptSecret(CKeyingMaterial& vMasterKey, const CSecret &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext)
|
||||||
|
{
|
||||||
|
CCrypter cKeyCrypter;
|
||||||
|
std::vector<unsigned char> chIV(WALLET_CRYPTO_KEY_SIZE);
|
||||||
|
memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE);
|
||||||
|
if(!cKeyCrypter.SetKey(vMasterKey, chIV))
|
||||||
|
return false;
|
||||||
|
return cKeyCrypter.Encrypt((CKeyingMaterial)vchPlaintext, vchCiphertext);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CSecret& vchPlaintext)
|
||||||
|
{
|
||||||
|
CCrypter cKeyCrypter;
|
||||||
|
std::vector<unsigned char> chIV(WALLET_CRYPTO_KEY_SIZE);
|
||||||
|
memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE);
|
||||||
|
if(!cKeyCrypter.SetKey(vMasterKey, chIV))
|
||||||
|
return false;
|
||||||
|
return cKeyCrypter.Decrypt(vchCiphertext, *((CKeyingMaterial*)&vchPlaintext));
|
||||||
|
}
|
96
src/crypter.h
Normal file
96
src/crypter.h
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
// Copyright (c) 2011 The Bitcoin Developers
|
||||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
#ifndef __CRYPTER_H__
|
||||||
|
#define __CRYPTER_H__
|
||||||
|
|
||||||
|
#include "key.h"
|
||||||
|
|
||||||
|
const unsigned int WALLET_CRYPTO_KEY_SIZE = 32;
|
||||||
|
const unsigned int WALLET_CRYPTO_SALT_SIZE = 8;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Private key encryption is done based on a CMasterKey,
|
||||||
|
which holds a salt and random encryption key.
|
||||||
|
|
||||||
|
CMasterKeys is encrypted using AES-256-CBC using a key
|
||||||
|
derived using derivation method nDerivationMethod
|
||||||
|
(0 == EVP_sha512()) and derivation iterations nDeriveIterations.
|
||||||
|
vchOtherDerivationParameters is provided for alternative algorithms
|
||||||
|
which may require more parameters (such as scrypt).
|
||||||
|
|
||||||
|
Wallet Private Keys are then encrypted using AES-256-CBC
|
||||||
|
with the double-sha256 of the private key as the IV, and the
|
||||||
|
master key's key as the encryption key.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class CMasterKey
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::vector<unsigned char> vchCryptedKey;
|
||||||
|
std::vector<unsigned char> vchSalt;
|
||||||
|
// 0 = EVP_sha512()
|
||||||
|
// 1 = scrypt()
|
||||||
|
unsigned int nDerivationMethod;
|
||||||
|
unsigned int nDeriveIterations;
|
||||||
|
// Use this for more parameters to key derivation,
|
||||||
|
// such as the various parameters to scrypt
|
||||||
|
std::vector<unsigned char> vchOtherDerivationParameters;
|
||||||
|
|
||||||
|
IMPLEMENT_SERIALIZE
|
||||||
|
(
|
||||||
|
READWRITE(vchCryptedKey);
|
||||||
|
READWRITE(vchSalt);
|
||||||
|
READWRITE(nDerivationMethod);
|
||||||
|
READWRITE(nDeriveIterations);
|
||||||
|
READWRITE(vchOtherDerivationParameters);
|
||||||
|
)
|
||||||
|
CMasterKey()
|
||||||
|
{
|
||||||
|
// 25000 rounds is just under 0.1 seconds on a 1.86 GHz Pentium M
|
||||||
|
// ie slightly lower than the lowest hardware we need bother supporting
|
||||||
|
nDeriveIterations = 25000;
|
||||||
|
nDerivationMethod = 0;
|
||||||
|
vchOtherDerivationParameters = std::vector<unsigned char>(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
|
||||||
|
|
||||||
|
class CCrypter
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
unsigned char chKey[WALLET_CRYPTO_KEY_SIZE];
|
||||||
|
unsigned char chIV[WALLET_CRYPTO_KEY_SIZE];
|
||||||
|
bool fKeySet;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool SetKeyFromPassphrase(const std::string &strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod);
|
||||||
|
bool Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned char> &vchCiphertext);
|
||||||
|
bool Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingMaterial& vchPlaintext);
|
||||||
|
bool SetKey(const CKeyingMaterial& chNewKey, const std::vector<unsigned char>& chNewIV);
|
||||||
|
|
||||||
|
void CleanKey()
|
||||||
|
{
|
||||||
|
memset(&chKey, 0, sizeof chKey);
|
||||||
|
memset(&chIV, 0, sizeof chIV);
|
||||||
|
munlock(&chKey, sizeof chKey);
|
||||||
|
munlock(&chIV, sizeof chIV);
|
||||||
|
fKeySet = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CCrypter()
|
||||||
|
{
|
||||||
|
fKeySet = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
~CCrypter()
|
||||||
|
{
|
||||||
|
CleanKey();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool EncryptSecret(CKeyingMaterial& vMasterKey, const CSecret &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext);
|
||||||
|
bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char> &vchCiphertext, const uint256& nIV, CSecret &vchPlaintext);
|
||||||
|
|
||||||
|
#endif
|
|
@ -80,7 +80,7 @@ bool CpuId(word32 input, word32 *output)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#if !CRYPTOPP_BOOL_X64 && !defined(_MSC_VER) && defined(__GNUC__)
|
||||||
static jmp_buf s_jmpNoSSE2;
|
static jmp_buf s_jmpNoSSE2;
|
||||||
static void SigIllHandlerSSE2(int)
|
static void SigIllHandlerSSE2(int)
|
||||||
{
|
{
|
||||||
|
|
59
src/db.cpp
59
src/db.cpp
|
@ -627,8 +627,6 @@ int64 CWalletDB::GetAccountCreditDebit(const string& strAccount)
|
||||||
|
|
||||||
void CWalletDB::ListAccountCreditDebit(const string& strAccount, list<CAccountingEntry>& entries)
|
void CWalletDB::ListAccountCreditDebit(const string& strAccount, list<CAccountingEntry>& entries)
|
||||||
{
|
{
|
||||||
int64 nCreditDebit = 0;
|
|
||||||
|
|
||||||
bool fAllAccounts = (strAccount == "*");
|
bool fAllAccounts = (strAccount == "*");
|
||||||
|
|
||||||
Dbc* pcursor = GetCursor();
|
Dbc* pcursor = GetCursor();
|
||||||
|
@ -670,7 +668,7 @@ void CWalletDB::ListAccountCreditDebit(const string& strAccount, list<CAccountin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CWalletDB::LoadWallet(CWallet* pwallet)
|
int CWalletDB::LoadWallet(CWallet* pwallet)
|
||||||
{
|
{
|
||||||
pwallet->vchDefaultKey.clear();
|
pwallet->vchDefaultKey.clear();
|
||||||
int nFileVersion = 0;
|
int nFileVersion = 0;
|
||||||
|
@ -685,12 +683,12 @@ bool CWalletDB::LoadWallet(CWallet* pwallet)
|
||||||
|
|
||||||
//// todo: shouldn't we catch exceptions and try to recover and continue?
|
//// todo: shouldn't we catch exceptions and try to recover and continue?
|
||||||
CRITICAL_BLOCK(pwallet->cs_mapWallet)
|
CRITICAL_BLOCK(pwallet->cs_mapWallet)
|
||||||
CRITICAL_BLOCK(pwallet->cs_mapKeys)
|
CRITICAL_BLOCK(pwallet->cs_KeyStore)
|
||||||
{
|
{
|
||||||
// Get cursor
|
// Get cursor
|
||||||
Dbc* pcursor = GetCursor();
|
Dbc* pcursor = GetCursor();
|
||||||
if (!pcursor)
|
if (!pcursor)
|
||||||
return false;
|
return DB_CORRUPT;
|
||||||
|
|
||||||
loop
|
loop
|
||||||
{
|
{
|
||||||
|
@ -701,7 +699,7 @@ bool CWalletDB::LoadWallet(CWallet* pwallet)
|
||||||
if (ret == DB_NOTFOUND)
|
if (ret == DB_NOTFOUND)
|
||||||
break;
|
break;
|
||||||
else if (ret != 0)
|
else if (ret != 0)
|
||||||
return false;
|
return DB_CORRUPT;
|
||||||
|
|
||||||
// Unserialize
|
// Unserialize
|
||||||
// Taking advantage of the fact that pair serialization
|
// Taking advantage of the fact that pair serialization
|
||||||
|
@ -765,14 +763,42 @@ bool CWalletDB::LoadWallet(CWallet* pwallet)
|
||||||
{
|
{
|
||||||
vector<unsigned char> vchPubKey;
|
vector<unsigned char> vchPubKey;
|
||||||
ssKey >> vchPubKey;
|
ssKey >> vchPubKey;
|
||||||
CWalletKey wkey;
|
CKey key;
|
||||||
if (strType == "key")
|
if (strType == "key")
|
||||||
ssValue >> wkey.vchPrivKey;
|
{
|
||||||
|
CPrivKey pkey;
|
||||||
|
ssValue >> pkey;
|
||||||
|
key.SetPrivKey(pkey);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
CWalletKey wkey;
|
||||||
ssValue >> wkey;
|
ssValue >> wkey;
|
||||||
|
key.SetPrivKey(wkey.vchPrivKey);
|
||||||
pwallet->mapKeys[vchPubKey] = wkey.vchPrivKey;
|
}
|
||||||
mapPubKeys[Hash160(vchPubKey)] = vchPubKey;
|
if (!pwallet->LoadKey(key))
|
||||||
|
return DB_CORRUPT;
|
||||||
|
}
|
||||||
|
else if (strType == "mkey")
|
||||||
|
{
|
||||||
|
unsigned int nID;
|
||||||
|
ssKey >> nID;
|
||||||
|
CMasterKey kMasterKey;
|
||||||
|
ssValue >> kMasterKey;
|
||||||
|
if(pwallet->mapMasterKeys.count(nID) != 0)
|
||||||
|
return DB_CORRUPT;
|
||||||
|
pwallet->mapMasterKeys[nID] = kMasterKey;
|
||||||
|
if (pwallet->nMasterKeyMaxID < nID)
|
||||||
|
pwallet->nMasterKeyMaxID = nID;
|
||||||
|
}
|
||||||
|
else if (strType == "ckey")
|
||||||
|
{
|
||||||
|
vector<unsigned char> vchPubKey;
|
||||||
|
ssKey >> vchPubKey;
|
||||||
|
vector<unsigned char> vchPrivKey;
|
||||||
|
ssValue >> vchPrivKey;
|
||||||
|
if (!pwallet->LoadCryptedKey(vchPubKey, vchPrivKey))
|
||||||
|
return DB_CORRUPT;
|
||||||
}
|
}
|
||||||
else if (strType == "defaultkey")
|
else if (strType == "defaultkey")
|
||||||
{
|
{
|
||||||
|
@ -800,7 +826,6 @@ bool CWalletDB::LoadWallet(CWallet* pwallet)
|
||||||
if (strKey == "fGenerateBitcoins") ssValue >> fGenerateBitcoins;
|
if (strKey == "fGenerateBitcoins") ssValue >> fGenerateBitcoins;
|
||||||
#endif
|
#endif
|
||||||
if (strKey == "nTransactionFee") ssValue >> nTransactionFee;
|
if (strKey == "nTransactionFee") ssValue >> nTransactionFee;
|
||||||
if (strKey == "addrIncoming") ssValue >> addrIncoming;
|
|
||||||
if (strKey == "fLimitProcessors") ssValue >> fLimitProcessors;
|
if (strKey == "fLimitProcessors") ssValue >> fLimitProcessors;
|
||||||
if (strKey == "nLimitProcessors") ssValue >> nLimitProcessors;
|
if (strKey == "nLimitProcessors") ssValue >> nLimitProcessors;
|
||||||
if (strKey == "fMinimizeToTray") ssValue >> fMinimizeToTray;
|
if (strKey == "fMinimizeToTray") ssValue >> fMinimizeToTray;
|
||||||
|
@ -809,6 +834,13 @@ bool CWalletDB::LoadWallet(CWallet* pwallet)
|
||||||
if (strKey == "addrProxy") ssValue >> addrProxy;
|
if (strKey == "addrProxy") ssValue >> addrProxy;
|
||||||
if (fHaveUPnP && strKey == "fUseUPnP") ssValue >> fUseUPnP;
|
if (fHaveUPnP && strKey == "fUseUPnP") ssValue >> fUseUPnP;
|
||||||
}
|
}
|
||||||
|
else if (strType == "minversion")
|
||||||
|
{
|
||||||
|
int nMinVersion = 0;
|
||||||
|
ssValue >> nMinVersion;
|
||||||
|
if (nMinVersion > VERSION)
|
||||||
|
return DB_TOO_NEW;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pcursor->close();
|
pcursor->close();
|
||||||
}
|
}
|
||||||
|
@ -819,7 +851,6 @@ bool CWalletDB::LoadWallet(CWallet* pwallet)
|
||||||
printf("nFileVersion = %d\n", nFileVersion);
|
printf("nFileVersion = %d\n", nFileVersion);
|
||||||
printf("fGenerateBitcoins = %d\n", fGenerateBitcoins);
|
printf("fGenerateBitcoins = %d\n", fGenerateBitcoins);
|
||||||
printf("nTransactionFee = %"PRI64d"\n", nTransactionFee);
|
printf("nTransactionFee = %"PRI64d"\n", nTransactionFee);
|
||||||
printf("addrIncoming = %s\n", addrIncoming.ToString().c_str());
|
|
||||||
printf("fMinimizeToTray = %d\n", fMinimizeToTray);
|
printf("fMinimizeToTray = %d\n", fMinimizeToTray);
|
||||||
printf("fMinimizeOnClose = %d\n", fMinimizeOnClose);
|
printf("fMinimizeOnClose = %d\n", fMinimizeOnClose);
|
||||||
printf("fUseProxy = %d\n", fUseProxy);
|
printf("fUseProxy = %d\n", fUseProxy);
|
||||||
|
@ -839,7 +870,7 @@ bool CWalletDB::LoadWallet(CWallet* pwallet)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return DB_LOAD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadFlushWalletDB(void* parg)
|
void ThreadFlushWalletDB(void* parg)
|
||||||
|
|
33
src/db.h
33
src/db.h
|
@ -88,7 +88,7 @@ protected:
|
||||||
if (!pdb)
|
if (!pdb)
|
||||||
return false;
|
return false;
|
||||||
if (fReadOnly)
|
if (fReadOnly)
|
||||||
assert(("Write called on database in read-only mode", false));
|
assert(!"Write called on database in read-only mode");
|
||||||
|
|
||||||
// Key
|
// Key
|
||||||
CDataStream ssKey(SER_DISK);
|
CDataStream ssKey(SER_DISK);
|
||||||
|
@ -117,7 +117,7 @@ protected:
|
||||||
if (!pdb)
|
if (!pdb)
|
||||||
return false;
|
return false;
|
||||||
if (fReadOnly)
|
if (fReadOnly)
|
||||||
assert(("Erase called on database in read-only mode", false));
|
assert(!"Erase called on database in read-only mode");
|
||||||
|
|
||||||
// Key
|
// Key
|
||||||
CDataStream ssKey(SER_DISK);
|
CDataStream ssKey(SER_DISK);
|
||||||
|
@ -342,6 +342,14 @@ public:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
enum DBErrors
|
||||||
|
{
|
||||||
|
DB_LOAD_OK,
|
||||||
|
DB_CORRUPT,
|
||||||
|
DB_TOO_NEW,
|
||||||
|
DB_LOAD_FAIL,
|
||||||
|
};
|
||||||
|
|
||||||
class CWalletDB : public CDB
|
class CWalletDB : public CDB
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -391,6 +399,25 @@ public:
|
||||||
return Write(std::make_pair(std::string("key"), vchPubKey), vchPrivKey, false);
|
return Write(std::make_pair(std::string("key"), vchPubKey), vchPrivKey, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WriteCryptedKey(const std::vector<unsigned char>& vchPubKey, const std::vector<unsigned char>& vchCryptedSecret, bool fEraseUnencryptedKey = true)
|
||||||
|
{
|
||||||
|
nWalletDBUpdated++;
|
||||||
|
if (!Write(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false))
|
||||||
|
return false;
|
||||||
|
if (fEraseUnencryptedKey)
|
||||||
|
{
|
||||||
|
Erase(std::make_pair(std::string("key"), vchPubKey));
|
||||||
|
Erase(std::make_pair(std::string("wkey"), vchPubKey));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
|
||||||
|
{
|
||||||
|
nWalletDBUpdated++;
|
||||||
|
return Write(std::make_pair(std::string("mkey"), nID), kMasterKey, true);
|
||||||
|
}
|
||||||
|
|
||||||
bool WriteBestBlock(const CBlockLocator& locator)
|
bool WriteBestBlock(const CBlockLocator& locator)
|
||||||
{
|
{
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdated++;
|
||||||
|
@ -450,7 +477,7 @@ public:
|
||||||
int64 GetAccountCreditDebit(const std::string& strAccount);
|
int64 GetAccountCreditDebit(const std::string& strAccount);
|
||||||
void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& acentries);
|
void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& acentries);
|
||||||
|
|
||||||
bool LoadWallet(CWallet* pwallet);
|
int LoadWallet(CWallet* pwallet);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
13
src/init.cpp
13
src/init.cpp
|
@ -386,8 +386,16 @@ bool AppInit2(int argc, char* argv[])
|
||||||
nStart = GetTimeMillis();
|
nStart = GetTimeMillis();
|
||||||
bool fFirstRun;
|
bool fFirstRun;
|
||||||
pwalletMain = new CWallet("wallet.dat");
|
pwalletMain = new CWallet("wallet.dat");
|
||||||
if (!pwalletMain->LoadWallet(fFirstRun))
|
int nLoadWalletRet = pwalletMain->LoadWallet(fFirstRun);
|
||||||
strErrors += _("Error loading wallet.dat \n");
|
if (nLoadWalletRet != DB_LOAD_OK)
|
||||||
|
{
|
||||||
|
if (nLoadWalletRet == DB_CORRUPT)
|
||||||
|
strErrors += _("Error loading wallet.dat: Wallet corrupted \n");
|
||||||
|
else if (nLoadWalletRet == DB_TOO_NEW)
|
||||||
|
strErrors += _("Error loading wallet.dat: Wallet requires newer version of Bitcoin \n");
|
||||||
|
else
|
||||||
|
strErrors += _("Error loading wallet.dat \n");
|
||||||
|
}
|
||||||
printf(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart);
|
printf(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart);
|
||||||
|
|
||||||
RegisterWallet(pwalletMain);
|
RegisterWallet(pwalletMain);
|
||||||
|
@ -415,7 +423,6 @@ bool AppInit2(int argc, char* argv[])
|
||||||
//// debug print
|
//// debug print
|
||||||
printf("mapBlockIndex.size() = %d\n", mapBlockIndex.size());
|
printf("mapBlockIndex.size() = %d\n", mapBlockIndex.size());
|
||||||
printf("nBestHeight = %d\n", nBestHeight);
|
printf("nBestHeight = %d\n", nBestHeight);
|
||||||
printf("mapKeys.size() = %d\n", pwalletMain->mapKeys.size());
|
|
||||||
printf("setKeyPool.size() = %d\n", pwalletMain->setKeyPool.size());
|
printf("setKeyPool.size() = %d\n", pwalletMain->setKeyPool.size());
|
||||||
printf("mapPubKeys.size() = %d\n", mapPubKeys.size());
|
printf("mapPubKeys.size() = %d\n", mapPubKeys.size());
|
||||||
printf("mapWallet.size() = %d\n", pwalletMain->mapWallet.size());
|
printf("mapWallet.size() = %d\n", pwalletMain->mapWallet.size());
|
||||||
|
|
86
src/key.h
86
src/key.h
|
@ -31,6 +31,41 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
int static inline 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class key_error : public std::runtime_error
|
class key_error : public std::runtime_error
|
||||||
|
@ -42,8 +77,7 @@ public:
|
||||||
|
|
||||||
// secure_allocator is defined in serialize.h
|
// secure_allocator is defined in serialize.h
|
||||||
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
|
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
|
||||||
|
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CSecret;
|
||||||
|
|
||||||
|
|
||||||
class CKey
|
class CKey
|
||||||
{
|
{
|
||||||
|
@ -102,6 +136,38 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SetSecret(const CSecret& vchSecret)
|
||||||
|
{
|
||||||
|
EC_KEY_free(pkey);
|
||||||
|
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||||
|
if (pkey == NULL)
|
||||||
|
throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed");
|
||||||
|
if (vchSecret.size() != 32)
|
||||||
|
throw key_error("CKey::SetSecret() : secret must be 32 bytes");
|
||||||
|
BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new());
|
||||||
|
if (bn == NULL)
|
||||||
|
throw key_error("CKey::SetSecret() : BN_bin2bn failed");
|
||||||
|
if (!EC_KEY_regenerate_key(pkey,bn))
|
||||||
|
throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
|
||||||
|
BN_clear_free(bn);
|
||||||
|
fSet = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSecret GetSecret() const
|
||||||
|
{
|
||||||
|
CSecret vchRet;
|
||||||
|
vchRet.resize(32);
|
||||||
|
const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
|
||||||
|
int nBytes = BN_num_bytes(bn);
|
||||||
|
if (bn == NULL)
|
||||||
|
throw key_error("CKey::GetSecret() : EC_KEY_get0_private_key failed");
|
||||||
|
int n=BN_bn2bin(bn,&vchRet[32 - nBytes]);
|
||||||
|
if (n != nBytes)
|
||||||
|
throw key_error("CKey::GetSecret(): BN_bn2bin failed");
|
||||||
|
return vchRet;
|
||||||
|
}
|
||||||
|
|
||||||
CPrivKey GetPrivKey() const
|
CPrivKey GetPrivKey() const
|
||||||
{
|
{
|
||||||
unsigned int nSize = i2d_ECPrivateKey(pkey, NULL);
|
unsigned int nSize = i2d_ECPrivateKey(pkey, NULL);
|
||||||
|
@ -154,22 +220,6 @@ public:
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Sign(const CPrivKey& vchPrivKey, uint256 hash, std::vector<unsigned char>& vchSig)
|
|
||||||
{
|
|
||||||
CKey key;
|
|
||||||
if (!key.SetPrivKey(vchPrivKey))
|
|
||||||
return false;
|
|
||||||
return key.Sign(hash, vchSig);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool Verify(const std::vector<unsigned char>& vchPubKey, uint256 hash, const std::vector<unsigned char>& vchSig)
|
|
||||||
{
|
|
||||||
CKey key;
|
|
||||||
if (!key.SetPubKey(vchPubKey))
|
|
||||||
return false;
|
|
||||||
return key.Verify(hash, vchSig);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
133
src/keystore.cpp
133
src/keystore.cpp
|
@ -4,13 +4,7 @@
|
||||||
|
|
||||||
#include "headers.h"
|
#include "headers.h"
|
||||||
#include "db.h"
|
#include "db.h"
|
||||||
|
#include "crypter.h"
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// mapKeys
|
|
||||||
//
|
|
||||||
|
|
||||||
std::vector<unsigned char> CKeyStore::GenerateNewKey()
|
std::vector<unsigned char> CKeyStore::GenerateNewKey()
|
||||||
{
|
{
|
||||||
|
@ -18,13 +12,14 @@ std::vector<unsigned char> CKeyStore::GenerateNewKey()
|
||||||
CKey key;
|
CKey key;
|
||||||
key.MakeNewKey();
|
key.MakeNewKey();
|
||||||
if (!AddKey(key))
|
if (!AddKey(key))
|
||||||
throw std::runtime_error("GenerateNewKey() : AddKey failed");
|
throw std::runtime_error("CKeyStore::GenerateNewKey() : AddKey failed");
|
||||||
return key.GetPubKey();
|
return key.GetPubKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CKeyStore::AddKey(const CKey& key)
|
bool CBasicKeyStore::AddKey(const CKey& key)
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_mapKeys)
|
CRITICAL_BLOCK(cs_mapPubKeys)
|
||||||
|
CRITICAL_BLOCK(cs_KeyStore)
|
||||||
{
|
{
|
||||||
mapKeys[key.GetPubKey()] = key.GetPrivKey();
|
mapKeys[key.GetPubKey()] = key.GetPrivKey();
|
||||||
mapPubKeys[Hash160(key.GetPubKey())] = key.GetPubKey();
|
mapPubKeys[Hash160(key.GetPubKey())] = key.GetPubKey();
|
||||||
|
@ -32,3 +27,121 @@ bool CKeyStore::AddKey(const CKey& key)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned char> CCryptoKeyStore::GenerateNewKey()
|
||||||
|
{
|
||||||
|
RandAddSeedPerfmon();
|
||||||
|
CKey key;
|
||||||
|
key.MakeNewKey();
|
||||||
|
if (!AddKey(key))
|
||||||
|
throw std::runtime_error("CCryptoKeyStore::GenerateNewKey() : AddKey failed");
|
||||||
|
return key.GetPubKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
|
||||||
|
{
|
||||||
|
CRITICAL_BLOCK(cs_vMasterKey)
|
||||||
|
{
|
||||||
|
if (!SetCrypted())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::map<std::vector<unsigned char>, std::vector<unsigned char> >::const_iterator mi = mapCryptedKeys.begin();
|
||||||
|
for (; mi != mapCryptedKeys.end(); ++mi)
|
||||||
|
{
|
||||||
|
const std::vector<unsigned char> &vchPubKey = (*mi).first;
|
||||||
|
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second;
|
||||||
|
CSecret vchSecret;
|
||||||
|
if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecret))
|
||||||
|
return false;
|
||||||
|
CKey key;
|
||||||
|
key.SetSecret(vchSecret);
|
||||||
|
if (key.GetPubKey() == vchPubKey)
|
||||||
|
break;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
vMasterKey = vMasterKeyIn;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCryptoKeyStore::AddKey(const CKey& key)
|
||||||
|
{
|
||||||
|
CRITICAL_BLOCK(cs_KeyStore)
|
||||||
|
CRITICAL_BLOCK(cs_vMasterKey)
|
||||||
|
{
|
||||||
|
if (!IsCrypted())
|
||||||
|
return CBasicKeyStore::AddKey(key);
|
||||||
|
|
||||||
|
if (IsLocked())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::vector<unsigned char> vchCryptedSecret;
|
||||||
|
std::vector<unsigned char> vchPubKey = key.GetPubKey();
|
||||||
|
if (!EncryptSecret(vMasterKey, key.GetSecret(), Hash(vchPubKey.begin(), vchPubKey.end()), vchCryptedSecret))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!AddCryptedKey(key.GetPubKey(), vchCryptedSecret))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CCryptoKeyStore::AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
|
||||||
|
{
|
||||||
|
CRITICAL_BLOCK(cs_mapPubKeys)
|
||||||
|
CRITICAL_BLOCK(cs_KeyStore)
|
||||||
|
{
|
||||||
|
if (!SetCrypted())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
mapCryptedKeys[vchPubKey] = vchCryptedSecret;
|
||||||
|
mapPubKeys[Hash160(vchPubKey)] = vchPubKey;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCryptoKeyStore::GetPrivKey(const std::vector<unsigned char> &vchPubKey, CKey& keyOut) const
|
||||||
|
{
|
||||||
|
CRITICAL_BLOCK(cs_vMasterKey)
|
||||||
|
{
|
||||||
|
if (!IsCrypted())
|
||||||
|
return CBasicKeyStore::GetPrivKey(vchPubKey, keyOut);
|
||||||
|
|
||||||
|
std::map<std::vector<unsigned char>, std::vector<unsigned char> >::const_iterator mi = mapCryptedKeys.find(vchPubKey);
|
||||||
|
if (mi != mapCryptedKeys.end())
|
||||||
|
{
|
||||||
|
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second;
|
||||||
|
CSecret vchSecret;
|
||||||
|
if (!DecryptSecret(vMasterKey, (*mi).second, Hash((*mi).first.begin(), (*mi).first.end()), vchSecret))
|
||||||
|
return false;
|
||||||
|
keyOut.SetSecret(vchSecret);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
|
||||||
|
{
|
||||||
|
CRITICAL_BLOCK(cs_KeyStore)
|
||||||
|
CRITICAL_BLOCK(cs_vMasterKey)
|
||||||
|
{
|
||||||
|
if (!mapCryptedKeys.empty() || IsCrypted())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
fUseCrypto = true;
|
||||||
|
CKey key;
|
||||||
|
BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys)
|
||||||
|
{
|
||||||
|
if (!key.SetPrivKey(mKey.second))
|
||||||
|
return false;
|
||||||
|
std::vector<unsigned char> vchCryptedSecret;
|
||||||
|
if (!EncryptSecret(vMasterKeyIn, key.GetSecret(), Hash(mKey.first.begin(), mKey.first.end()), vchCryptedSecret))
|
||||||
|
return false;
|
||||||
|
if (!AddCryptedKey(mKey.first, vchCryptedSecret))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mapKeys.clear();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -4,27 +4,112 @@
|
||||||
#ifndef BITCOIN_KEYSTORE_H
|
#ifndef BITCOIN_KEYSTORE_H
|
||||||
#define BITCOIN_KEYSTORE_H
|
#define BITCOIN_KEYSTORE_H
|
||||||
|
|
||||||
|
#include "crypter.h"
|
||||||
|
|
||||||
class CKeyStore
|
class CKeyStore
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::map<std::vector<unsigned char>, CPrivKey> mapKeys;
|
mutable CCriticalSection cs_KeyStore;
|
||||||
mutable CCriticalSection cs_mapKeys;
|
|
||||||
virtual bool AddKey(const CKey& key);
|
virtual bool AddKey(const CKey& key) =0;
|
||||||
|
virtual bool HaveKey(const std::vector<unsigned char> &vchPubKey) const =0;
|
||||||
|
virtual bool GetPrivKey(const std::vector<unsigned char> &vchPubKey, CKey& keyOut) const =0;
|
||||||
|
virtual std::vector<unsigned char> GenerateNewKey();
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::map<std::vector<unsigned char>, CPrivKey> KeyMap;
|
||||||
|
|
||||||
|
class CBasicKeyStore : public CKeyStore
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
KeyMap mapKeys;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool AddKey(const CKey& key);
|
||||||
bool HaveKey(const std::vector<unsigned char> &vchPubKey) const
|
bool HaveKey(const std::vector<unsigned char> &vchPubKey) const
|
||||||
{
|
{
|
||||||
return (mapKeys.count(vchPubKey) > 0);
|
return (mapKeys.count(vchPubKey) > 0);
|
||||||
}
|
}
|
||||||
bool GetPrivKey(const std::vector<unsigned char> &vchPubKey, CPrivKey& keyOut) const
|
bool GetPrivKey(const std::vector<unsigned char> &vchPubKey, CKey& keyOut) const
|
||||||
{
|
{
|
||||||
std::map<std::vector<unsigned char>, CPrivKey>::const_iterator mi = mapKeys.find(vchPubKey);
|
std::map<std::vector<unsigned char>, CPrivKey>::const_iterator mi = mapKeys.find(vchPubKey);
|
||||||
if (mi != mapKeys.end())
|
if (mi != mapKeys.end())
|
||||||
{
|
{
|
||||||
keyOut = (*mi).second;
|
keyOut.SetPrivKey((*mi).second);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CCryptoKeyStore : public CBasicKeyStore
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::map<std::vector<unsigned char>, std::vector<unsigned char> > mapCryptedKeys;
|
||||||
|
|
||||||
|
CKeyingMaterial vMasterKey;
|
||||||
|
|
||||||
|
// if fUseCrypto is true, mapKeys must be empty
|
||||||
|
// if fUseCrypto is false, vMasterKey must be empty
|
||||||
|
bool fUseCrypto;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool SetCrypted()
|
||||||
|
{
|
||||||
|
if (fUseCrypto)
|
||||||
|
return true;
|
||||||
|
if (!mapKeys.empty())
|
||||||
|
return false;
|
||||||
|
fUseCrypto = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// will encrypt previously unencrypted keys
|
||||||
|
bool EncryptKeys(CKeyingMaterial& vMasterKeyIn);
|
||||||
|
|
||||||
|
bool Unlock(const CKeyingMaterial& vMasterKeyIn);
|
||||||
|
|
||||||
|
public:
|
||||||
|
mutable CCriticalSection cs_vMasterKey; //No guarantees master key wont get locked before you can use it, so lock this first
|
||||||
|
|
||||||
|
CCryptoKeyStore() : fUseCrypto(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsCrypted() const
|
||||||
|
{
|
||||||
|
return fUseCrypto;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsLocked() const
|
||||||
|
{
|
||||||
|
if (!IsCrypted())
|
||||||
|
return false;
|
||||||
|
return vMasterKey.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Lock()
|
||||||
|
{
|
||||||
|
CRITICAL_BLOCK(cs_vMasterKey)
|
||||||
|
{
|
||||||
|
if (!SetCrypted())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
vMasterKey.clear();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
|
||||||
std::vector<unsigned char> GenerateNewKey();
|
std::vector<unsigned char> GenerateNewKey();
|
||||||
|
bool AddKey(const CKey& key);
|
||||||
|
bool HaveKey(const std::vector<unsigned char> &vchPubKey) const
|
||||||
|
{
|
||||||
|
if (!IsCrypted())
|
||||||
|
return CBasicKeyStore::HaveKey(vchPubKey);
|
||||||
|
return mapCryptedKeys.count(vchPubKey) > 0;
|
||||||
|
}
|
||||||
|
bool GetPrivKey(const std::vector<unsigned char> &vchPubKey, CKey& keyOut) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
10
src/main.cpp
10
src/main.cpp
|
@ -55,7 +55,6 @@ int64 nHPSTimerStart;
|
||||||
// Settings
|
// Settings
|
||||||
int fGenerateBitcoins = false;
|
int fGenerateBitcoins = false;
|
||||||
int64 nTransactionFee = 0;
|
int64 nTransactionFee = 0;
|
||||||
CAddress addrIncoming;
|
|
||||||
int fLimitProcessors = false;
|
int fLimitProcessors = false;
|
||||||
int nLimitProcessors = 1;
|
int nLimitProcessors = 1;
|
||||||
int fMinimizeToTray = true;
|
int fMinimizeToTray = true;
|
||||||
|
@ -1689,7 +1688,7 @@ string GetWarnings(string strFor)
|
||||||
return strStatusBar;
|
return strStatusBar;
|
||||||
else if (strFor == "rpc")
|
else if (strFor == "rpc")
|
||||||
return strRPC;
|
return strRPC;
|
||||||
assert(("GetWarnings() : invalid parameter", false));
|
assert(!"GetWarnings() : invalid parameter");
|
||||||
return "error";
|
return "error";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1900,6 +1899,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||||
return error("message addr size() = %d", vAddr.size());
|
return error("message addr size() = %d", vAddr.size());
|
||||||
|
|
||||||
// Store the new addresses
|
// Store the new addresses
|
||||||
|
CAddrDB addrDB;
|
||||||
|
addrDB.TxnBegin();
|
||||||
int64 nNow = GetAdjustedTime();
|
int64 nNow = GetAdjustedTime();
|
||||||
int64 nSince = nNow - 10 * 60;
|
int64 nSince = nNow - 10 * 60;
|
||||||
BOOST_FOREACH(CAddress& addr, vAddr)
|
BOOST_FOREACH(CAddress& addr, vAddr)
|
||||||
|
@ -1911,7 +1912,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||||
continue;
|
continue;
|
||||||
if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60)
|
if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60)
|
||||||
addr.nTime = nNow - 5 * 24 * 60 * 60;
|
addr.nTime = nNow - 5 * 24 * 60 * 60;
|
||||||
AddAddress(addr, 2 * 60 * 60);
|
AddAddress(addr, 2 * 60 * 60, &addrDB);
|
||||||
pfrom->AddAddressKnown(addr);
|
pfrom->AddAddressKnown(addr);
|
||||||
if (addr.nTime > nSince && !pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable())
|
if (addr.nTime > nSince && !pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable())
|
||||||
{
|
{
|
||||||
|
@ -1942,6 +1943,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
addrDB.TxnCommit(); // Save addresses (it's ok if this fails)
|
||||||
if (vAddr.size() < 1000)
|
if (vAddr.size() < 1000)
|
||||||
pfrom->fGetAddr = false;
|
pfrom->fGetAddr = false;
|
||||||
}
|
}
|
||||||
|
@ -2213,7 +2215,7 @@ bool static 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] = pwalletMain->GetKeyFromKeyPool();
|
mapReuseKey[pfrom->addr.ip] = pwalletMain->GetOrReuseKeyFromPool();
|
||||||
|
|
||||||
// Send back approval of order and pubkey to use
|
// Send back approval of order and pubkey to use
|
||||||
CScript scriptPubKey;
|
CScript scriptPubKey;
|
||||||
|
|
|
@ -70,7 +70,6 @@ extern std::set<CWallet*> setpwalletRegistered;
|
||||||
// Settings
|
// Settings
|
||||||
extern int fGenerateBitcoins;
|
extern int fGenerateBitcoins;
|
||||||
extern int64 nTransactionFee;
|
extern int64 nTransactionFee;
|
||||||
extern CAddress addrIncoming;
|
|
||||||
extern int fLimitProcessors;
|
extern int fLimitProcessors;
|
||||||
extern int nLimitProcessors;
|
extern int nLimitProcessors;
|
||||||
extern int fMinimizeToTray;
|
extern int fMinimizeToTray;
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
DEPSDIR:=/usr/i586-mingw32msvc
|
DEPSDIR:=/usr/i586-mingw32msvc
|
||||||
|
|
||||||
|
USE_UPNP:=0
|
||||||
|
|
||||||
INCLUDEPATHS= \
|
INCLUDEPATHS= \
|
||||||
-I"$(DEPSDIR)/boost_1_43_0" \
|
-I"$(DEPSDIR)/boost_1_43_0" \
|
||||||
-I"$(DEPSDIR)/db-4.7.25.NC/build_unix" \
|
-I"$(DEPSDIR)/db-4.7.25.NC/build_unix" \
|
||||||
|
@ -34,23 +36,15 @@ DEFS=-D_MT -DWIN32 -D__WXMSW__ -D_WINDOWS -DNOPCH -DUSE_SSL
|
||||||
DEBUGFLAGS=-g -D__WXDEBUG__
|
DEBUGFLAGS=-g -D__WXDEBUG__
|
||||||
CFLAGS=-O2 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
|
CFLAGS=-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 \
|
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 keystore.h main.h wallet.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 \
|
||||||
|
crypter.h init.h
|
||||||
|
|
||||||
bitcoin.exe: USE_UPNP:=1
|
ifdef USE_UPNP
|
||||||
ifdef USE_UPNP
|
INCLUDEPATHS += -I"$(DEPSDIR)/upnpc-exe-win32-20110215"
|
||||||
INCLUDEPATHS += -I"$(DEPSDIR)/upnpc-exe-win32-20110215"
|
LIBPATHS += -L"$(DEPSDIR)/upnpc-exe-win32-20110215"
|
||||||
LIBPATHS += -L"$(DEPSDIR)/upnpc-exe-win32-20110215"
|
LIBS += -l miniupnpc -l iphlpapi
|
||||||
LIBS += -l miniupnpc -l iphlpapi
|
DEFS += -DSTATICLIB -DUSE_UPNP=$(USE_UPNP)
|
||||||
DEFS += -DSTATICLIB -DUSE_UPNP=$(USE_UPNP)
|
endif
|
||||||
endif
|
|
||||||
|
|
||||||
bitcoind.exe: USE_UPNP:=0
|
|
||||||
ifdef USE_UPNP
|
|
||||||
INCLUDEPATHS += -I"$(DEPSDIR)/upnpc-exe-win32-20110215"
|
|
||||||
LIBPATHS += -L"$(DEPSDIR)/upnpc-exe-win32-20110215"
|
|
||||||
LIBS += -l miniupnpc -l iphlpapi
|
|
||||||
DEFS += -DSTATICLIB -DUSE_UPNP=$(USE_UPNP)
|
|
||||||
endif
|
|
||||||
|
|
||||||
LIBS += -l mingwthrd -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l shlwapi
|
LIBS += -l mingwthrd -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l shlwapi
|
||||||
|
|
||||||
|
@ -65,6 +59,7 @@ OBJS= \
|
||||||
obj/wallet.o \
|
obj/wallet.o \
|
||||||
obj/rpc.o \
|
obj/rpc.o \
|
||||||
obj/init.o \
|
obj/init.o \
|
||||||
|
obj/crypter.o \
|
||||||
cryptopp/obj/sha.o \
|
cryptopp/obj/sha.o \
|
||||||
cryptopp/obj/cpu.o
|
cryptopp/obj/cpu.o
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,8 @@ DEFS=-DWIN32 -D__WXMSW__ -D_WINDOWS -DNOPCH -DUSE_SSL
|
||||||
DEBUGFLAGS=-g -D__WXDEBUG__
|
DEBUGFLAGS=-g -D__WXDEBUG__
|
||||||
CFLAGS=-mthreads -O2 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
|
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 \
|
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 keystore.h main.h wallet.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 crypter.h
|
||||||
|
|
||||||
ifdef USE_UPNP
|
ifdef USE_UPNP
|
||||||
INCLUDEPATHS += -I"C:\upnpc-exe-win32-20110215"
|
INCLUDEPATHS += -I"C:\upnpc-exe-win32-20110215"
|
||||||
|
@ -55,6 +56,7 @@ OBJS= \
|
||||||
obj/wallet.o \
|
obj/wallet.o \
|
||||||
obj/rpc.o \
|
obj/rpc.o \
|
||||||
obj/init.o \
|
obj/init.o \
|
||||||
|
obj/crypter.o \
|
||||||
cryptopp/obj/sha.o \
|
cryptopp/obj/sha.o \
|
||||||
cryptopp/obj/cpu.o
|
cryptopp/obj/cpu.o
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,8 @@ DEBUGFLAGS=-g -DwxDEBUG_LEVEL=0
|
||||||
# ppc doesn't work because we don't support big-endian
|
# 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)
|
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 \
|
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 keystore.h main.h wallet.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 crypter.h
|
||||||
|
|
||||||
OBJS= \
|
OBJS= \
|
||||||
obj/util.o \
|
obj/util.o \
|
||||||
|
@ -46,6 +47,7 @@ OBJS= \
|
||||||
obj/wallet.o \
|
obj/wallet.o \
|
||||||
obj/rpc.o \
|
obj/rpc.o \
|
||||||
obj/init.o \
|
obj/init.o \
|
||||||
|
obj/crypter.o \
|
||||||
cryptopp/obj/sha.o \
|
cryptopp/obj/sha.o \
|
||||||
cryptopp/obj/cpu.o
|
cryptopp/obj/cpu.o
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,8 @@ LIBS+= \
|
||||||
DEBUGFLAGS=-g -D__WXDEBUG__
|
DEBUGFLAGS=-g -D__WXDEBUG__
|
||||||
CXXFLAGS=-O2 -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS)
|
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 \
|
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 keystore.h main.h wallet.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 crypter.h
|
||||||
|
|
||||||
OBJS= \
|
OBJS= \
|
||||||
obj/util.o \
|
obj/util.o \
|
||||||
|
@ -52,6 +53,7 @@ OBJS= \
|
||||||
obj/wallet.o \
|
obj/wallet.o \
|
||||||
obj/rpc.o \
|
obj/rpc.o \
|
||||||
obj/init.o \
|
obj/init.o \
|
||||||
|
obj/crypter.o \
|
||||||
cryptopp/obj/sha.o \
|
cryptopp/obj/sha.o \
|
||||||
cryptopp/obj/cpu.o
|
cryptopp/obj/cpu.o
|
||||||
|
|
||||||
|
|
24
src/net.cpp
24
src/net.cpp
|
@ -440,7 +440,7 @@ void ThreadGetMyExternalIP(void* parg)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool AddAddress(CAddress addr, int64 nTimePenalty)
|
bool AddAddress(CAddress addr, int64 nTimePenalty, CAddrDB *pAddrDB)
|
||||||
{
|
{
|
||||||
if (!addr.IsRoutable())
|
if (!addr.IsRoutable())
|
||||||
return false;
|
return false;
|
||||||
|
@ -455,7 +455,10 @@ bool AddAddress(CAddress addr, int64 nTimePenalty)
|
||||||
// New address
|
// New address
|
||||||
printf("AddAddress(%s)\n", addr.ToString().c_str());
|
printf("AddAddress(%s)\n", addr.ToString().c_str());
|
||||||
mapAddresses.insert(make_pair(addr.GetKey(), addr));
|
mapAddresses.insert(make_pair(addr.GetKey(), addr));
|
||||||
CAddrDB().WriteAddress(addr);
|
if (pAddrDB)
|
||||||
|
pAddrDB->WriteAddress(addr);
|
||||||
|
else
|
||||||
|
CAddrDB().WriteAddress(addr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -477,7 +480,12 @@ bool AddAddress(CAddress addr, int64 nTimePenalty)
|
||||||
fUpdated = true;
|
fUpdated = true;
|
||||||
}
|
}
|
||||||
if (fUpdated)
|
if (fUpdated)
|
||||||
CAddrDB().WriteAddress(addrFound);
|
{
|
||||||
|
if (pAddrDB)
|
||||||
|
pAddrDB->WriteAddress(addrFound);
|
||||||
|
else
|
||||||
|
CAddrDB().WriteAddress(addrFound);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -831,7 +839,7 @@ void ThreadSocketHandler2(void* parg)
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||||
{
|
{
|
||||||
if (pnode->hSocket == INVALID_SOCKET || pnode->hSocket < 0)
|
if (pnode->hSocket == INVALID_SOCKET)
|
||||||
continue;
|
continue;
|
||||||
FD_SET(pnode->hSocket, &fdsetRecv);
|
FD_SET(pnode->hSocket, &fdsetRecv);
|
||||||
FD_SET(pnode->hSocket, &fdsetError);
|
FD_SET(pnode->hSocket, &fdsetError);
|
||||||
|
@ -1158,6 +1166,8 @@ void DNSAddressSeed()
|
||||||
if (!fTestNet)
|
if (!fTestNet)
|
||||||
{
|
{
|
||||||
printf("Loading addresses from DNS seeds (could take a while)\n");
|
printf("Loading addresses from DNS seeds (could take a while)\n");
|
||||||
|
CAddrDB addrDB;
|
||||||
|
addrDB.TxnBegin();
|
||||||
|
|
||||||
for (int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
|
for (int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
|
||||||
vector<CAddress> vaddr;
|
vector<CAddress> vaddr;
|
||||||
|
@ -1168,12 +1178,14 @@ void DNSAddressSeed()
|
||||||
if (addr.GetByte(3) != 127)
|
if (addr.GetByte(3) != 127)
|
||||||
{
|
{
|
||||||
addr.nTime = 0;
|
addr.nTime = 0;
|
||||||
AddAddress(addr);
|
AddAddress(addr, 0, &addrDB);
|
||||||
found++;
|
found++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addrDB.TxnCommit(); // Save addresses (it's ok if this fails)
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%d addresses found from DNS seeds\n", found);
|
printf("%d addresses found from DNS seeds\n", found);
|
||||||
|
@ -1700,7 +1712,7 @@ void StartNode(void* parg)
|
||||||
printf("Error: CreateThread(ThreadIRCSeed) failed\n");
|
printf("Error: CreateThread(ThreadIRCSeed) failed\n");
|
||||||
|
|
||||||
// Send and receive from sockets, accept connections
|
// Send and receive from sockets, accept connections
|
||||||
pthread_t hThreadSocketHandler = CreateThread(ThreadSocketHandler, NULL, true);
|
CreateThread(ThreadSocketHandler, NULL, true);
|
||||||
|
|
||||||
// Initiate outbound connections
|
// Initiate outbound connections
|
||||||
if (!CreateThread(ThreadOpenConnections, NULL))
|
if (!CreateThread(ThreadOpenConnections, NULL))
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
class CMessageHeader;
|
class CMessageHeader;
|
||||||
class CAddress;
|
class CAddress;
|
||||||
|
class CAddrDB;
|
||||||
class CInv;
|
class CInv;
|
||||||
class CRequestTracker;
|
class CRequestTracker;
|
||||||
class CNode;
|
class CNode;
|
||||||
|
@ -40,7 +41,7 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout
|
||||||
bool Lookup(const char *pszName, std::vector<CAddress>& vaddr, int nServices, int nMaxSolutions, bool fAllowLookup = false, int portDefault = 0, bool fAllowPort = false);
|
bool Lookup(const char *pszName, std::vector<CAddress>& vaddr, int nServices, int nMaxSolutions, bool fAllowLookup = false, int portDefault = 0, bool fAllowPort = false);
|
||||||
bool Lookup(const char *pszName, CAddress& addr, int nServices, bool fAllowLookup = false, int portDefault = 0, bool fAllowPort = false);
|
bool Lookup(const char *pszName, CAddress& addr, int nServices, bool fAllowLookup = false, int portDefault = 0, bool fAllowPort = false);
|
||||||
bool GetMyExternalIP(unsigned int& ipRet);
|
bool GetMyExternalIP(unsigned int& ipRet);
|
||||||
bool AddAddress(CAddress addr, int64 nTimePenalty=0);
|
bool AddAddress(CAddress addr, int64 nTimePenalty=0, CAddrDB *pAddrDB=NULL);
|
||||||
void AddressCurrentlyConnected(const CAddress& addr);
|
void AddressCurrentlyConnected(const CAddress& addr);
|
||||||
CNode* FindNode(unsigned int ip);
|
CNode* FindNode(unsigned int ip);
|
||||||
CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0);
|
CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0);
|
||||||
|
|
|
@ -38,7 +38,7 @@ struct AddressTablePriv
|
||||||
{
|
{
|
||||||
cachedAddressTable.clear();
|
cachedAddressTable.clear();
|
||||||
|
|
||||||
CRITICAL_BLOCK(wallet->cs_mapKeys)
|
CRITICAL_BLOCK(cs_mapPubKeys)
|
||||||
CRITICAL_BLOCK(wallet->cs_mapAddressBook)
|
CRITICAL_BLOCK(wallet->cs_mapAddressBook)
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(const PAIRTYPE(std::string, std::string)& item, wallet->mapAddressBook)
|
BOOST_FOREACH(const PAIRTYPE(std::string, std::string)& item, wallet->mapAddressBook)
|
||||||
|
@ -255,14 +255,15 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
|
||||||
{
|
{
|
||||||
// Generate a new address to associate with given label, optionally
|
// Generate a new address to associate with given label, optionally
|
||||||
// set as default receiving address.
|
// set as default receiving address.
|
||||||
strAddress = PubKeyToAddress(wallet->GetKeyFromKeyPool());
|
strAddress = PubKeyToAddress(wallet->GetOrReuseKeyFromPool());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
// Add entry and update list
|
// Add entry and update list
|
||||||
wallet->SetAddressBookName(strAddress, strLabel);
|
CRITICAL_BLOCK(wallet->cs_mapAddressBook)
|
||||||
|
wallet->SetAddressBookName(strAddress, strLabel);
|
||||||
updateList();
|
updateList();
|
||||||
return QString::fromStdString(strAddress);
|
return QString::fromStdString(strAddress);
|
||||||
}
|
}
|
||||||
|
|
|
@ -580,6 +580,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
|
||||||
case OP_ABS: if (bn < bnZero) bn = -bn; break;
|
case OP_ABS: if (bn < bnZero) bn = -bn; break;
|
||||||
case OP_NOT: bn = (bn == bnZero); break;
|
case OP_NOT: bn = (bn == bnZero); break;
|
||||||
case OP_0NOTEQUAL: bn = (bn != bnZero); break;
|
case OP_0NOTEQUAL: bn = (bn != bnZero); break;
|
||||||
|
default: assert(!"invalid opcode"); break;
|
||||||
}
|
}
|
||||||
popstack(stack);
|
popstack(stack);
|
||||||
stack.push_back(bn.getvch());
|
stack.push_back(bn.getvch());
|
||||||
|
@ -659,6 +660,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
|
||||||
case OP_GREATERTHANOREQUAL: bn = (bn1 >= bn2); break;
|
case OP_GREATERTHANOREQUAL: bn = (bn1 >= bn2); break;
|
||||||
case OP_MIN: bn = (bn1 < bn2 ? bn1 : bn2); break;
|
case OP_MIN: bn = (bn1 < bn2 ? bn1 : bn2); break;
|
||||||
case OP_MAX: bn = (bn1 > bn2 ? bn1 : bn2); break;
|
case OP_MAX: bn = (bn1 > bn2 ? bn1 : bn2); break;
|
||||||
|
default: assert(!"invalid opcode"); break;
|
||||||
}
|
}
|
||||||
popstack(stack);
|
popstack(stack);
|
||||||
popstack(stack);
|
popstack(stack);
|
||||||
|
@ -1030,7 +1032,7 @@ bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Compile solution
|
// Compile solution
|
||||||
CRITICAL_BLOCK(keystore.cs_mapKeys)
|
CRITICAL_BLOCK(keystore.cs_KeyStore)
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
|
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
|
||||||
{
|
{
|
||||||
|
@ -1038,13 +1040,13 @@ bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash
|
||||||
{
|
{
|
||||||
// Sign
|
// Sign
|
||||||
const valtype& vchPubKey = item.second;
|
const valtype& vchPubKey = item.second;
|
||||||
CPrivKey privkey;
|
CKey key;
|
||||||
if (!keystore.GetPrivKey(vchPubKey, privkey))
|
if (!keystore.GetPrivKey(vchPubKey, key))
|
||||||
return false;
|
return false;
|
||||||
if (hash != 0)
|
if (hash != 0)
|
||||||
{
|
{
|
||||||
vector<unsigned char> vchSig;
|
vector<unsigned char> vchSig;
|
||||||
if (!CKey::Sign(privkey, hash, vchSig))
|
if (!key.Sign(hash, vchSig))
|
||||||
return false;
|
return false;
|
||||||
vchSig.push_back((unsigned char)nHashType);
|
vchSig.push_back((unsigned char)nHashType);
|
||||||
scriptSigRet << vchSig;
|
scriptSigRet << vchSig;
|
||||||
|
@ -1057,13 +1059,13 @@ bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash
|
||||||
if (mi == mapPubKeys.end())
|
if (mi == mapPubKeys.end())
|
||||||
return false;
|
return false;
|
||||||
const vector<unsigned char>& vchPubKey = (*mi).second;
|
const vector<unsigned char>& vchPubKey = (*mi).second;
|
||||||
CPrivKey privkey;
|
CKey key;
|
||||||
if (!keystore.GetPrivKey(vchPubKey, privkey))
|
if (!keystore.GetPrivKey(vchPubKey, key))
|
||||||
return false;
|
return false;
|
||||||
if (hash != 0)
|
if (hash != 0)
|
||||||
{
|
{
|
||||||
vector<unsigned char> vchSig;
|
vector<unsigned char> vchSig;
|
||||||
if (!CKey::Sign(privkey, hash, vchSig))
|
if (!key.Sign(hash, vchSig))
|
||||||
return false;
|
return false;
|
||||||
vchSig.push_back((unsigned char)nHashType);
|
vchSig.push_back((unsigned char)nHashType);
|
||||||
scriptSigRet << vchSig << vchPubKey;
|
scriptSigRet << vchSig << vchPubKey;
|
||||||
|
@ -1089,8 +1091,40 @@ bool IsStandard(const CScript& scriptPubKey)
|
||||||
|
|
||||||
bool IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
|
bool IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
|
||||||
{
|
{
|
||||||
CScript scriptSig;
|
vector<pair<opcodetype, valtype> > vSolution;
|
||||||
return Solver(keystore, scriptPubKey, 0, 0, scriptSig);
|
if (!Solver(scriptPubKey, vSolution))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Compile solution
|
||||||
|
CRITICAL_BLOCK(keystore.cs_KeyStore)
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
|
||||||
|
{
|
||||||
|
if (item.first == OP_PUBKEY)
|
||||||
|
{
|
||||||
|
// Sign
|
||||||
|
const valtype& vchPubKey = item.second;
|
||||||
|
if (!keystore.HaveKey(vchPubKey))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (item.first == OP_PUBKEYHASH)
|
||||||
|
{
|
||||||
|
// Sign and give pubkey
|
||||||
|
map<uint160, valtype>::iterator mi = mapPubKeys.find(uint160(item.second));
|
||||||
|
if (mi == mapPubKeys.end())
|
||||||
|
return false;
|
||||||
|
const vector<unsigned char>& vchPubKey = (*mi).second;
|
||||||
|
if (!keystore.HaveKey(vchPubKey))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -486,7 +486,7 @@ public:
|
||||||
{
|
{
|
||||||
// I'm not sure if this should push the script or concatenate scripts.
|
// I'm not sure if this should push the script or concatenate scripts.
|
||||||
// If there's ever a use for pushing a script onto a script, delete this member fn
|
// If there's ever a use for pushing a script onto a script, delete this member fn
|
||||||
assert(("warning: pushing a CScript onto a CScript with << is probably not intended, use + to concatenate", false));
|
assert(!"warning: pushing a CScript onto a CScript with << is probably not intended, use + to concatenate");
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,12 +28,36 @@ typedef unsigned long long uint64;
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1300
|
#if defined(_MSC_VER) && _MSC_VER < 1300
|
||||||
#define for if (false) ; else for
|
#define for if (false) ; else for
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __WXMSW__
|
||||||
|
// This is used to attempt to keep keying material out of swap
|
||||||
|
// Note that VirtualLock does not provide this as a guarantee on Windows,
|
||||||
|
// but, in practice, memory that has been VirtualLock'd almost never gets written to
|
||||||
|
// the pagefile except in rare circumstances where memory is extremely low.
|
||||||
|
#define mlock(p, n) VirtualLock((p), (n));
|
||||||
|
#define munlock(p, n) VirtualUnlock((p), (n));
|
||||||
|
#else
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <limits.h>
|
||||||
|
/* This comes from limits.h if it's not defined there set a sane default */
|
||||||
|
#ifndef PAGESIZE
|
||||||
|
#include <unistd.h>
|
||||||
|
#define PAGESIZE sysconf(_SC_PAGESIZE)
|
||||||
|
#endif
|
||||||
|
#define mlock(a,b) \
|
||||||
|
mlock(((void *)(((size_t)(a)) & (~((PAGESIZE)-1)))),\
|
||||||
|
(((((size_t)(a)) + (b) - 1) | ((PAGESIZE) - 1)) + 1) - (((size_t)(a)) & (~((PAGESIZE) - 1))))
|
||||||
|
#define munlock(a,b) \
|
||||||
|
munlock(((void *)(((size_t)(a)) & (~((PAGESIZE)-1)))),\
|
||||||
|
(((((size_t)(a)) + (b) - 1) | ((PAGESIZE) - 1)) + 1) - (((size_t)(a)) & (~((PAGESIZE) - 1))))
|
||||||
|
#endif
|
||||||
|
|
||||||
class CScript;
|
class CScript;
|
||||||
class CDataStream;
|
class CDataStream;
|
||||||
class CAutoFile;
|
class CAutoFile;
|
||||||
static const unsigned int MAX_SIZE = 0x02000000;
|
static const unsigned int MAX_SIZE = 0x02000000;
|
||||||
|
|
||||||
static const int VERSION = 32400;
|
static const int VERSION = 32500;
|
||||||
static const char* pszSubVer = "";
|
static const char* pszSubVer = "";
|
||||||
static const bool VERSION_IS_BETA = true;
|
static const bool VERSION_IS_BETA = true;
|
||||||
|
|
||||||
|
@ -755,7 +779,8 @@ struct ser_streamplaceholder
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Allocator that clears its contents before deletion
|
// Allocator that locks its contents from being paged
|
||||||
|
// out of memory and clears its contents before deletion.
|
||||||
//
|
//
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct secure_allocator : public std::allocator<T>
|
struct secure_allocator : public std::allocator<T>
|
||||||
|
@ -777,10 +802,22 @@ struct secure_allocator : public std::allocator<T>
|
||||||
template<typename _Other> struct rebind
|
template<typename _Other> struct rebind
|
||||||
{ typedef secure_allocator<_Other> other; };
|
{ typedef secure_allocator<_Other> other; };
|
||||||
|
|
||||||
|
T* allocate(std::size_t n, const void *hint = 0)
|
||||||
|
{
|
||||||
|
T *p;
|
||||||
|
p = std::allocator<T>::allocate(n, hint);
|
||||||
|
if (p != NULL)
|
||||||
|
mlock(p, sizeof(T) * n);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
void deallocate(T* p, std::size_t n)
|
void deallocate(T* p, std::size_t n)
|
||||||
{
|
{
|
||||||
if (p != NULL)
|
if (p != NULL)
|
||||||
|
{
|
||||||
memset(p, 0, sizeof(T) * n);
|
memset(p, 0, sizeof(T) * n);
|
||||||
|
munlock(p, sizeof(T) * n);
|
||||||
|
}
|
||||||
std::allocator<T>::deallocate(p, n);
|
std::allocator<T>::deallocate(p, n);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
273
src/ui.cpp
273
src/ui.cpp
|
@ -245,6 +245,41 @@ void SetDefaultReceivingAddress(const string& strAddress)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GetWalletPassphrase()
|
||||||
|
{
|
||||||
|
if (pwalletMain->IsLocked())
|
||||||
|
{
|
||||||
|
string strWalletPass;
|
||||||
|
strWalletPass.reserve(100);
|
||||||
|
mlock(&strWalletPass[0], strWalletPass.capacity());
|
||||||
|
|
||||||
|
// obtain current wallet encrypt/decrypt key, from passphrase
|
||||||
|
// Note that the passphrase is not mlock()d during this entry and could potentially
|
||||||
|
// be obtained from disk long after bitcoin has run.
|
||||||
|
strWalletPass = wxGetPasswordFromUser(_("Enter the current passphrase to the wallet."),
|
||||||
|
_("Passphrase")).ToStdString();
|
||||||
|
|
||||||
|
if (!strWalletPass.size())
|
||||||
|
{
|
||||||
|
fill(strWalletPass.begin(), strWalletPass.end(), '\0');
|
||||||
|
munlock(&strWalletPass[0], strWalletPass.capacity());
|
||||||
|
wxMessageBox(_("Please supply the current wallet decryption passphrase."), "Bitcoin");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pwalletMain->Unlock(strWalletPass))
|
||||||
|
{
|
||||||
|
fill(strWalletPass.begin(), strWalletPass.end(), '\0');
|
||||||
|
munlock(&strWalletPass[0], strWalletPass.capacity());
|
||||||
|
wxMessageBox(_("The passphrase entered for the wallet decryption was incorrect."), "Bitcoin");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fill(strWalletPass.begin(), strWalletPass.end(), '\0');
|
||||||
|
munlock(&strWalletPass[0], strWalletPass.capacity());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -333,6 +368,11 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent)
|
||||||
if (CWalletDB(pwalletMain->strWalletFile,"r").ReadDefaultKey(vchPubKey))
|
if (CWalletDB(pwalletMain->strWalletFile,"r").ReadDefaultKey(vchPubKey))
|
||||||
m_textCtrlAddress->SetValue(PubKeyToAddress(vchPubKey));
|
m_textCtrlAddress->SetValue(PubKeyToAddress(vchPubKey));
|
||||||
|
|
||||||
|
if (pwalletMain->IsCrypted())
|
||||||
|
m_menuOptions->Remove(m_menuOptionsEncryptWallet);
|
||||||
|
else
|
||||||
|
m_menuOptions->Remove(m_menuOptionsChangeWalletPassphrase);
|
||||||
|
|
||||||
// Fill listctrl with wallet transactions
|
// Fill listctrl with wallet transactions
|
||||||
RefreshListCtrl();
|
RefreshListCtrl();
|
||||||
}
|
}
|
||||||
|
@ -1122,6 +1162,169 @@ void CMainFrame::OnMenuOptionsChangeYourAddress(wxCommandEvent& event)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CMainFrame::OnMenuOptionsEncryptWallet(wxCommandEvent& event)
|
||||||
|
{
|
||||||
|
// Options->Encrypt Wallet
|
||||||
|
if (pwalletMain->IsCrypted())
|
||||||
|
{
|
||||||
|
wxMessageBox(_("Wallet already encrypted."), "Bitcoin", wxOK | wxICON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string strWalletPass;
|
||||||
|
strWalletPass.reserve(100);
|
||||||
|
mlock(&strWalletPass[0], strWalletPass.capacity());
|
||||||
|
|
||||||
|
// obtain current wallet encrypt/decrypt key, from passphrase
|
||||||
|
// Note that the passphrase is not mlock()d during this entry and could potentially
|
||||||
|
// be obtained from disk long after bitcoin has run.
|
||||||
|
strWalletPass = wxGetPasswordFromUser(_("Enter the new passphrase to the wallet.\nPlease use a passphrase of 10 or more random characters, or eight or more words."),
|
||||||
|
_("Passphrase")).ToStdString();
|
||||||
|
|
||||||
|
if (!strWalletPass.size())
|
||||||
|
{
|
||||||
|
fill(strWalletPass.begin(), strWalletPass.end(), '\0');
|
||||||
|
munlock(&strWalletPass[0], strWalletPass.capacity());
|
||||||
|
wxMessageBox(_("Error: The supplied passphrase was too short."), "Bitcoin", wxOK | wxICON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(wxMessageBox(_("WARNING: If you encrypt your wallet and lose your passphrase, you will LOSE ALL OF YOUR BITCOINS!\nAre you sure you wish to encrypt your wallet?"), "Bitcoin", wxYES_NO) != wxYES)
|
||||||
|
return;
|
||||||
|
|
||||||
|
string strWalletPassTest;
|
||||||
|
strWalletPassTest.reserve(100);
|
||||||
|
mlock(&strWalletPassTest[0], strWalletPassTest.capacity());
|
||||||
|
strWalletPassTest = wxGetPasswordFromUser(_("Please re-enter your new wallet passphrase."),
|
||||||
|
_("Passphrase")).ToStdString();
|
||||||
|
|
||||||
|
if (strWalletPassTest != strWalletPass)
|
||||||
|
{
|
||||||
|
fill(strWalletPass.begin(), strWalletPass.end(), '\0');
|
||||||
|
fill(strWalletPassTest.begin(), strWalletPassTest.end(), '\0');
|
||||||
|
munlock(&strWalletPass[0], strWalletPass.capacity());
|
||||||
|
munlock(&strWalletPassTest[0], strWalletPassTest.capacity());
|
||||||
|
wxMessageBox(_("Error: the supplied passphrases didn't match."), "Bitcoin", wxOK | wxICON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pwalletMain->EncryptWallet(strWalletPass))
|
||||||
|
{
|
||||||
|
fill(strWalletPass.begin(), strWalletPass.end(), '\0');
|
||||||
|
fill(strWalletPassTest.begin(), strWalletPassTest.end(), '\0');
|
||||||
|
munlock(&strWalletPass[0], strWalletPass.capacity());
|
||||||
|
munlock(&strWalletPassTest[0], strWalletPassTest.capacity());
|
||||||
|
wxMessageBox(_("Wallet encryption failed."), "Bitcoin", wxOK | wxICON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fill(strWalletPass.begin(), strWalletPass.end(), '\0');
|
||||||
|
fill(strWalletPassTest.begin(), strWalletPassTest.end(), '\0');
|
||||||
|
munlock(&strWalletPass[0], strWalletPass.capacity());
|
||||||
|
munlock(&strWalletPassTest[0], strWalletPassTest.capacity());
|
||||||
|
wxMessageBox(_("Wallet Encrypted.\nRemember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer."), "Bitcoin");
|
||||||
|
|
||||||
|
m_menuOptions->Remove(m_menuOptionsEncryptWallet);
|
||||||
|
m_menuOptions->Insert(m_menuOptions->GetMenuItemCount() - 1, m_menuOptionsChangeWalletPassphrase);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMainFrame::OnMenuOptionsChangeWalletPassphrase(wxCommandEvent& event)
|
||||||
|
{
|
||||||
|
// Options->Change Wallet Encryption Passphrase
|
||||||
|
if (!pwalletMain->IsCrypted())
|
||||||
|
{
|
||||||
|
wxMessageBox(_("Wallet is unencrypted, please encrypt it first."), "Bitcoin", wxOK | wxICON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string strOldWalletPass;
|
||||||
|
strOldWalletPass.reserve(100);
|
||||||
|
mlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
||||||
|
|
||||||
|
// obtain current wallet encrypt/decrypt key, from passphrase
|
||||||
|
// Note that the passphrase is not mlock()d during this entry and could potentially
|
||||||
|
// be obtained from disk long after bitcoin has run.
|
||||||
|
strOldWalletPass = wxGetPasswordFromUser(_("Enter the current passphrase to the wallet."),
|
||||||
|
_("Passphrase")).ToStdString();
|
||||||
|
|
||||||
|
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
|
||||||
|
{
|
||||||
|
bool fWasLocked = pwalletMain->IsLocked();
|
||||||
|
pwalletMain->Lock();
|
||||||
|
|
||||||
|
if (!strOldWalletPass.size() || !pwalletMain->Unlock(strOldWalletPass))
|
||||||
|
{
|
||||||
|
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
|
||||||
|
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
||||||
|
wxMessageBox(_("The passphrase entered for the wallet decryption was incorrect."), "Bitcoin", wxOK | wxICON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fWasLocked)
|
||||||
|
pwalletMain->Lock();
|
||||||
|
|
||||||
|
string strNewWalletPass;
|
||||||
|
strNewWalletPass.reserve(100);
|
||||||
|
mlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
||||||
|
|
||||||
|
// obtain new wallet encrypt/decrypt key, from passphrase
|
||||||
|
// Note that the passphrase is not mlock()d during this entry and could potentially
|
||||||
|
// be obtained from disk long after bitcoin has run.
|
||||||
|
strNewWalletPass = wxGetPasswordFromUser(_("Enter the new passphrase for the wallet."),
|
||||||
|
_("Passphrase")).ToStdString();
|
||||||
|
|
||||||
|
if (!strNewWalletPass.size())
|
||||||
|
{
|
||||||
|
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
|
||||||
|
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
|
||||||
|
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
||||||
|
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
||||||
|
wxMessageBox(_("Error: The supplied passphrase was too short."), "Bitcoin", wxOK | wxICON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string strNewWalletPassTest;
|
||||||
|
strNewWalletPassTest.reserve(100);
|
||||||
|
mlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
|
||||||
|
|
||||||
|
// obtain new wallet encrypt/decrypt key, from passphrase
|
||||||
|
// Note that the passphrase is not mlock()d during this entry and could potentially
|
||||||
|
// be obtained from disk long after bitcoin has run.
|
||||||
|
strNewWalletPassTest = wxGetPasswordFromUser(_("Re-enter the new passphrase for the wallet."),
|
||||||
|
_("Passphrase")).ToStdString();
|
||||||
|
|
||||||
|
if (strNewWalletPassTest != strNewWalletPass)
|
||||||
|
{
|
||||||
|
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
|
||||||
|
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
|
||||||
|
fill(strNewWalletPassTest.begin(), strNewWalletPassTest.end(), '\0');
|
||||||
|
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
||||||
|
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
||||||
|
munlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
|
||||||
|
wxMessageBox(_("Error: the supplied passphrases didn't match."), "Bitcoin", wxOK | wxICON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
|
||||||
|
{
|
||||||
|
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
|
||||||
|
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
|
||||||
|
fill(strNewWalletPassTest.begin(), strNewWalletPassTest.end(), '\0');
|
||||||
|
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
||||||
|
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
||||||
|
munlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
|
||||||
|
wxMessageBox(_("The passphrase entered for the wallet decryption was incorrect."), "Bitcoin", wxOK | wxICON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
|
||||||
|
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
|
||||||
|
fill(strNewWalletPassTest.begin(), strNewWalletPassTest.end(), '\0');
|
||||||
|
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
||||||
|
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
||||||
|
munlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
|
||||||
|
wxMessageBox(_("Wallet Passphrase Changed."), "Bitcoin");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CMainFrame::OnMenuOptionsOptions(wxCommandEvent& event)
|
void CMainFrame::OnMenuOptionsOptions(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
// Options->Options
|
// Options->Options
|
||||||
|
@ -1182,8 +1385,19 @@ void CMainFrame::OnButtonNew(wxCommandEvent& event)
|
||||||
return;
|
return;
|
||||||
string strName = dialog.GetValue();
|
string strName = dialog.GetValue();
|
||||||
|
|
||||||
// Generate new key
|
string strAddress;
|
||||||
string strAddress = PubKeyToAddress(pwalletMain->GetKeyFromKeyPool());
|
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
|
||||||
|
{
|
||||||
|
bool fWasLocked = pwalletMain->IsLocked();
|
||||||
|
if (!GetWalletPassphrase())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Generate new key
|
||||||
|
strAddress = PubKeyToAddress(pwalletMain->GetOrReuseKeyFromPool());
|
||||||
|
|
||||||
|
if (fWasLocked)
|
||||||
|
pwalletMain->Lock();
|
||||||
|
}
|
||||||
|
|
||||||
// Save
|
// Save
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
||||||
|
@ -1947,7 +2161,12 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event)
|
||||||
if (fBitcoinAddress)
|
if (fBitcoinAddress)
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_main)
|
CRITICAL_BLOCK(cs_main)
|
||||||
|
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
|
||||||
{
|
{
|
||||||
|
bool fWasLocked = pwalletMain->IsLocked();
|
||||||
|
if (!GetWalletPassphrase())
|
||||||
|
return;
|
||||||
|
|
||||||
// Send to bitcoin address
|
// Send to bitcoin address
|
||||||
CScript scriptPubKey;
|
CScript scriptPubKey;
|
||||||
scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG;
|
scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG;
|
||||||
|
@ -1956,13 +2175,22 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event)
|
||||||
if (strError == "")
|
if (strError == "")
|
||||||
wxMessageBox(_("Payment sent "), _("Sending..."));
|
wxMessageBox(_("Payment sent "), _("Sending..."));
|
||||||
else if (strError == "ABORTED")
|
else if (strError == "ABORTED")
|
||||||
|
{
|
||||||
|
if (fWasLocked)
|
||||||
|
pwalletMain->Lock();
|
||||||
return; // leave send dialog open
|
return; // leave send dialog open
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wxMessageBox(strError + " ", _("Sending..."));
|
wxMessageBox(strError + " ", _("Sending..."));
|
||||||
EndModal(false);
|
EndModal(false);
|
||||||
|
if (fWasLocked)
|
||||||
|
pwalletMain->Lock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fWasLocked)
|
||||||
|
pwalletMain->Lock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2246,16 +2474,27 @@ void CSendingDialog::OnReply2(CDataStream& vRecv)
|
||||||
Error(_("Insufficient funds"));
|
Error(_("Insufficient funds"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CReserveKey reservekey(pwalletMain);
|
CReserveKey reservekey(pwalletMain);
|
||||||
int64 nFeeRequired;
|
int64 nFeeRequired;
|
||||||
if (!pwalletMain->CreateTransaction(scriptPubKey, nPrice, wtx, reservekey, nFeeRequired))
|
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
|
||||||
{
|
{
|
||||||
if (nPrice + nFeeRequired > pwalletMain->GetBalance())
|
bool fWasLocked = pwalletMain->IsLocked();
|
||||||
Error(strprintf(_("This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds"), FormatMoney(nFeeRequired).c_str()));
|
if (!GetWalletPassphrase())
|
||||||
else
|
return;
|
||||||
Error(_("Transaction creation failed"));
|
|
||||||
return;
|
if (!pwalletMain->CreateTransaction(scriptPubKey, nPrice, wtx, reservekey, nFeeRequired))
|
||||||
}
|
{
|
||||||
|
if (nPrice + nFeeRequired > pwalletMain->GetBalance())
|
||||||
|
Error(strprintf(_("This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds"), FormatMoney(nFeeRequired).c_str()));
|
||||||
|
else
|
||||||
|
Error(_("Transaction creation failed"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fWasLocked)
|
||||||
|
pwalletMain->Lock();
|
||||||
|
}
|
||||||
|
|
||||||
// Transaction fee
|
// Transaction fee
|
||||||
if (!ThreadSafeAskFee(nFeeRequired, _("Sending..."), this))
|
if (!ThreadSafeAskFee(nFeeRequired, _("Sending..."), this))
|
||||||
|
@ -2382,7 +2621,7 @@ CAddressBookDialog::CAddressBookDialog(wxWindow* parent, const wxString& strInit
|
||||||
m_listCtrlReceiving->SetFocus();
|
m_listCtrlReceiving->SetFocus();
|
||||||
|
|
||||||
// Fill listctrl with address book data
|
// Fill listctrl with address book data
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapKeys)
|
CRITICAL_BLOCK(pwalletMain->cs_KeyStore)
|
||||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
||||||
{
|
{
|
||||||
string strDefaultReceiving = (string)pframeMain->m_textCtrlAddress->GetValue();
|
string strDefaultReceiving = (string)pframeMain->m_textCtrlAddress->GetValue();
|
||||||
|
@ -2581,8 +2820,18 @@ void CAddressBookDialog::OnButtonNew(wxCommandEvent& event)
|
||||||
return;
|
return;
|
||||||
strName = dialog.GetValue();
|
strName = dialog.GetValue();
|
||||||
|
|
||||||
// Generate new key
|
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
|
||||||
strAddress = PubKeyToAddress(pwalletMain->GetKeyFromKeyPool());
|
{
|
||||||
|
bool fWasLocked = pwalletMain->IsLocked();
|
||||||
|
if (!GetWalletPassphrase())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Generate new key
|
||||||
|
strAddress = PubKeyToAddress(pwalletMain->GetOrReuseKeyFromPool());
|
||||||
|
|
||||||
|
if (fWasLocked)
|
||||||
|
pwalletMain->Lock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to list and select it
|
// Add to list and select it
|
||||||
|
|
2
src/ui.h
2
src/ui.h
|
@ -59,6 +59,8 @@ protected:
|
||||||
void OnMenuFileExit(wxCommandEvent& event);
|
void OnMenuFileExit(wxCommandEvent& event);
|
||||||
void OnUpdateUIOptionsGenerate(wxUpdateUIEvent& event);
|
void OnUpdateUIOptionsGenerate(wxUpdateUIEvent& event);
|
||||||
void OnMenuOptionsChangeYourAddress(wxCommandEvent& event);
|
void OnMenuOptionsChangeYourAddress(wxCommandEvent& event);
|
||||||
|
void OnMenuOptionsEncryptWallet(wxCommandEvent& event);
|
||||||
|
void OnMenuOptionsChangeWalletPassphrase(wxCommandEvent& event);
|
||||||
void OnMenuOptionsOptions(wxCommandEvent& event);
|
void OnMenuOptionsOptions(wxCommandEvent& event);
|
||||||
void OnMenuHelpAbout(wxCommandEvent& event);
|
void OnMenuHelpAbout(wxCommandEvent& event);
|
||||||
void OnButtonSend(wxCommandEvent& event);
|
void OnButtonSend(wxCommandEvent& event);
|
||||||
|
|
|
@ -32,6 +32,12 @@ CMainFrameBase::CMainFrameBase( wxWindow* parent, wxWindowID id, const wxString&
|
||||||
m_menuOptionsChangeYourAddress = new wxMenuItem( m_menuOptions, wxID_ANY, wxString( _("&Your Receiving Addresses...") ) , wxEmptyString, wxITEM_NORMAL );
|
m_menuOptionsChangeYourAddress = new wxMenuItem( m_menuOptions, wxID_ANY, wxString( _("&Your Receiving Addresses...") ) , wxEmptyString, wxITEM_NORMAL );
|
||||||
m_menuOptions->Append( m_menuOptionsChangeYourAddress );
|
m_menuOptions->Append( m_menuOptionsChangeYourAddress );
|
||||||
|
|
||||||
|
m_menuOptionsEncryptWallet = new wxMenuItem( m_menuOptions, wxID_ANY, wxString( _("&Encrypt Wallet...") ) , wxEmptyString, wxITEM_NORMAL );
|
||||||
|
m_menuOptions->Append( m_menuOptionsEncryptWallet );
|
||||||
|
|
||||||
|
m_menuOptionsChangeWalletPassphrase = new wxMenuItem( m_menuOptions, wxID_ANY, wxString( _("&Change Wallet Encryption Passphrase...") ) , wxEmptyString, wxITEM_NORMAL );
|
||||||
|
m_menuOptions->Append( m_menuOptionsChangeWalletPassphrase );
|
||||||
|
|
||||||
wxMenuItem* m_menuOptionsOptions;
|
wxMenuItem* m_menuOptionsOptions;
|
||||||
m_menuOptionsOptions = new wxMenuItem( m_menuOptions, wxID_PREFERENCES, wxString( _("&Options...") ) , wxEmptyString, wxITEM_NORMAL );
|
m_menuOptionsOptions = new wxMenuItem( m_menuOptions, wxID_PREFERENCES, wxString( _("&Options...") ) , wxEmptyString, wxITEM_NORMAL );
|
||||||
m_menuOptions->Append( m_menuOptionsOptions );
|
m_menuOptions->Append( m_menuOptionsOptions );
|
||||||
|
@ -187,6 +193,8 @@ CMainFrameBase::CMainFrameBase( wxWindow* parent, wxWindowID id, const wxString&
|
||||||
this->Connect( wxEVT_PAINT, wxPaintEventHandler( CMainFrameBase::OnPaint ) );
|
this->Connect( wxEVT_PAINT, wxPaintEventHandler( CMainFrameBase::OnPaint ) );
|
||||||
this->Connect( m_menuFileExit->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CMainFrameBase::OnMenuFileExit ) );
|
this->Connect( m_menuFileExit->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CMainFrameBase::OnMenuFileExit ) );
|
||||||
this->Connect( m_menuOptionsChangeYourAddress->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CMainFrameBase::OnMenuOptionsChangeYourAddress ) );
|
this->Connect( m_menuOptionsChangeYourAddress->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CMainFrameBase::OnMenuOptionsChangeYourAddress ) );
|
||||||
|
this->Connect( m_menuOptionsEncryptWallet->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CMainFrameBase::OnMenuOptionsEncryptWallet ) );
|
||||||
|
this->Connect( m_menuOptionsChangeWalletPassphrase->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CMainFrameBase::OnMenuOptionsChangeWalletPassphrase ) );
|
||||||
this->Connect( m_menuOptionsOptions->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CMainFrameBase::OnMenuOptionsOptions ) );
|
this->Connect( m_menuOptionsOptions->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CMainFrameBase::OnMenuOptionsOptions ) );
|
||||||
this->Connect( m_menuHelpAbout->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CMainFrameBase::OnMenuHelpAbout ) );
|
this->Connect( m_menuHelpAbout->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CMainFrameBase::OnMenuHelpAbout ) );
|
||||||
this->Connect( wxID_BUTTONSEND, wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( CMainFrameBase::OnButtonSend ) );
|
this->Connect( wxID_BUTTONSEND, wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( CMainFrameBase::OnButtonSend ) );
|
||||||
|
@ -245,6 +253,8 @@ CMainFrameBase::~CMainFrameBase()
|
||||||
this->Disconnect( wxEVT_PAINT, wxPaintEventHandler( CMainFrameBase::OnPaint ) );
|
this->Disconnect( wxEVT_PAINT, wxPaintEventHandler( CMainFrameBase::OnPaint ) );
|
||||||
this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CMainFrameBase::OnMenuFileExit ) );
|
this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CMainFrameBase::OnMenuFileExit ) );
|
||||||
this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CMainFrameBase::OnMenuOptionsChangeYourAddress ) );
|
this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CMainFrameBase::OnMenuOptionsChangeYourAddress ) );
|
||||||
|
this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CMainFrameBase::OnMenuOptionsEncryptWallet ) );
|
||||||
|
this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CMainFrameBase::OnMenuOptionsChangeWalletPassphrase ) );
|
||||||
this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CMainFrameBase::OnMenuOptionsOptions ) );
|
this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CMainFrameBase::OnMenuOptionsOptions ) );
|
||||||
this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CMainFrameBase::OnMenuHelpAbout ) );
|
this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CMainFrameBase::OnMenuHelpAbout ) );
|
||||||
this->Disconnect( wxID_BUTTONSEND, wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( CMainFrameBase::OnButtonSend ) );
|
this->Disconnect( wxID_BUTTONSEND, wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( CMainFrameBase::OnButtonSend ) );
|
||||||
|
|
|
@ -98,6 +98,8 @@ class CMainFrameBase : public wxFrame
|
||||||
virtual void OnPaint( wxPaintEvent& event ) { event.Skip(); }
|
virtual void OnPaint( wxPaintEvent& event ) { event.Skip(); }
|
||||||
virtual void OnMenuFileExit( wxCommandEvent& event ) { event.Skip(); }
|
virtual void OnMenuFileExit( wxCommandEvent& event ) { event.Skip(); }
|
||||||
virtual void OnMenuOptionsChangeYourAddress( wxCommandEvent& event ) { event.Skip(); }
|
virtual void OnMenuOptionsChangeYourAddress( wxCommandEvent& event ) { event.Skip(); }
|
||||||
|
virtual void OnMenuOptionsEncryptWallet( wxCommandEvent& event ) { event.Skip(); }
|
||||||
|
virtual void OnMenuOptionsChangeWalletPassphrase( wxCommandEvent& event ) { event.Skip(); }
|
||||||
virtual void OnMenuOptionsOptions( wxCommandEvent& event ) { event.Skip(); }
|
virtual void OnMenuOptionsOptions( wxCommandEvent& event ) { event.Skip(); }
|
||||||
virtual void OnMenuHelpAbout( wxCommandEvent& event ) { event.Skip(); }
|
virtual void OnMenuHelpAbout( wxCommandEvent& event ) { event.Skip(); }
|
||||||
virtual void OnButtonSend( wxCommandEvent& event ) { event.Skip(); }
|
virtual void OnButtonSend( wxCommandEvent& event ) { event.Skip(); }
|
||||||
|
@ -115,6 +117,8 @@ class CMainFrameBase : public wxFrame
|
||||||
|
|
||||||
public:
|
public:
|
||||||
wxMenu* m_menuOptions;
|
wxMenu* m_menuOptions;
|
||||||
|
wxMenuItem* m_menuOptionsEncryptWallet;
|
||||||
|
wxMenuItem* m_menuOptionsChangeWalletPassphrase;
|
||||||
wxStatusBar* m_statusBar;
|
wxStatusBar* m_statusBar;
|
||||||
wxTextCtrl* m_textCtrlAddress;
|
wxTextCtrl* m_textCtrlAddress;
|
||||||
wxListCtrl* m_listCtrlAll;
|
wxListCtrl* m_listCtrlAll;
|
||||||
|
|
|
@ -758,8 +758,8 @@ string GetPidFile()
|
||||||
|
|
||||||
void CreatePidFile(string pidFile, pid_t pid)
|
void CreatePidFile(string pidFile, pid_t pid)
|
||||||
{
|
{
|
||||||
FILE* file;
|
FILE* file = fopen(pidFile.c_str(), "w");
|
||||||
if (file = fopen(pidFile.c_str(), "w"))
|
if (file)
|
||||||
{
|
{
|
||||||
fprintf(file, "%d\n", pid);
|
fprintf(file, "%d\n", pid);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
@ -788,7 +788,9 @@ void ShrinkDebugFile()
|
||||||
fseek(file, -sizeof(pch), SEEK_END);
|
fseek(file, -sizeof(pch), SEEK_END);
|
||||||
int nBytes = fread(pch, 1, sizeof(pch), file);
|
int nBytes = fread(pch, 1, sizeof(pch), file);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
if (file = fopen(strFile.c_str(), "w"))
|
|
||||||
|
file = fopen(strFile.c_str(), "w");
|
||||||
|
if (file)
|
||||||
{
|
{
|
||||||
fwrite(pch, 1, nBytes, file);
|
fwrite(pch, 1, nBytes, file);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
|
|
@ -262,7 +262,7 @@ public:
|
||||||
// I'd rather be careful than suffer the other more error prone syntax.
|
// I'd rather be careful than suffer the other more error prone syntax.
|
||||||
// The compiler will optimise away all this loop junk.
|
// The compiler will optimise away all this loop junk.
|
||||||
#define CRITICAL_BLOCK(cs) \
|
#define CRITICAL_BLOCK(cs) \
|
||||||
for (bool fcriticalblockonce=true; fcriticalblockonce; assert(("break caught by CRITICAL_BLOCK!", !fcriticalblockonce)), fcriticalblockonce=false) \
|
for (bool fcriticalblockonce=true; fcriticalblockonce; assert("break caught by CRITICAL_BLOCK!" && !fcriticalblockonce), fcriticalblockonce=false) \
|
||||||
for (CCriticalBlock criticalblock(cs); fcriticalblockonce && (cs.pszFile=__FILE__, cs.nLine=__LINE__, true); fcriticalblockonce=false, cs.pszFile=NULL, cs.nLine=0)
|
for (CCriticalBlock criticalblock(cs); fcriticalblockonce && (cs.pszFile=__FILE__, cs.nLine=__LINE__, true); fcriticalblockonce=false, cs.pszFile=NULL, cs.nLine=0)
|
||||||
|
|
||||||
class CTryCriticalBlock
|
class CTryCriticalBlock
|
||||||
|
@ -276,7 +276,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TRY_CRITICAL_BLOCK(cs) \
|
#define TRY_CRITICAL_BLOCK(cs) \
|
||||||
for (bool fcriticalblockonce=true; fcriticalblockonce; assert(("break caught by TRY_CRITICAL_BLOCK!", !fcriticalblockonce)), fcriticalblockonce=false) \
|
for (bool fcriticalblockonce=true; fcriticalblockonce; assert("break caught by TRY_CRITICAL_BLOCK!" && !fcriticalblockonce), fcriticalblockonce=false) \
|
||||||
for (CTryCriticalBlock criticalblock(cs); fcriticalblockonce && (fcriticalblockonce = criticalblock.Entered()) && (cs.pszFile=__FILE__, cs.nLine=__LINE__, true); fcriticalblockonce=false, cs.pszFile=NULL, cs.nLine=0)
|
for (CTryCriticalBlock criticalblock(cs); fcriticalblockonce && (fcriticalblockonce = criticalblock.Entered()) && (cs.pszFile=__FILE__, cs.nLine=__LINE__, true); fcriticalblockonce=false, cs.pszFile=NULL, cs.nLine=0)
|
||||||
|
|
||||||
|
|
||||||
|
@ -646,7 +646,7 @@ inline bool TerminateThread(pthread_t hthread, unsigned int nExitCode)
|
||||||
return (pthread_cancel(hthread) == 0);
|
return (pthread_cancel(hthread) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void ExitThread(unsigned int nExitCode)
|
inline void ExitThread(size_t nExitCode)
|
||||||
{
|
{
|
||||||
pthread_exit((void*)nExitCode);
|
pthread_exit((void*)nExitCode);
|
||||||
}
|
}
|
||||||
|
|
275
src/wallet.cpp
275
src/wallet.cpp
|
@ -5,11 +5,11 @@
|
||||||
#include "headers.h"
|
#include "headers.h"
|
||||||
#include "db.h"
|
#include "db.h"
|
||||||
#include "cryptopp/sha.h"
|
#include "cryptopp/sha.h"
|
||||||
|
#include "crypter.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// mapWallet
|
// mapWallet
|
||||||
|
@ -17,10 +17,181 @@ using namespace std;
|
||||||
|
|
||||||
bool CWallet::AddKey(const CKey& key)
|
bool CWallet::AddKey(const CKey& key)
|
||||||
{
|
{
|
||||||
this->CKeyStore::AddKey(key);
|
if (!CCryptoKeyStore::AddKey(key))
|
||||||
|
return false;
|
||||||
if (!fFileBacked)
|
if (!fFileBacked)
|
||||||
return true;
|
return true;
|
||||||
return CWalletDB(strWalletFile).WriteKey(key.GetPubKey(), key.GetPrivKey());
|
if (!IsCrypted())
|
||||||
|
return CWalletDB(strWalletFile).WriteKey(key.GetPubKey(), key.GetPrivKey());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::AddCryptedKey(const vector<unsigned char> &vchPubKey, const vector<unsigned char> &vchCryptedSecret)
|
||||||
|
{
|
||||||
|
if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
|
||||||
|
return false;
|
||||||
|
if (!fFileBacked)
|
||||||
|
return true;
|
||||||
|
CRITICAL_BLOCK(cs_pwalletdbEncryption)
|
||||||
|
{
|
||||||
|
if (pwalletdbEncryption)
|
||||||
|
return pwalletdbEncryption->WriteCryptedKey(vchPubKey, vchCryptedSecret);
|
||||||
|
else
|
||||||
|
return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey, vchCryptedSecret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::Unlock(const string& strWalletPassphrase)
|
||||||
|
{
|
||||||
|
CRITICAL_BLOCK(cs_vMasterKey)
|
||||||
|
{
|
||||||
|
if (!IsLocked())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CCrypter crypter;
|
||||||
|
CKeyingMaterial vMasterKey;
|
||||||
|
|
||||||
|
BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
|
||||||
|
{
|
||||||
|
if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
|
||||||
|
return false;
|
||||||
|
if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
|
||||||
|
return false;
|
||||||
|
if (CCryptoKeyStore::Unlock(vMasterKey))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::ChangeWalletPassphrase(const string& strOldWalletPassphrase, const string& strNewWalletPassphrase)
|
||||||
|
{
|
||||||
|
CRITICAL_BLOCK(cs_vMasterKey)
|
||||||
|
{
|
||||||
|
bool fWasLocked = IsLocked();
|
||||||
|
|
||||||
|
Lock();
|
||||||
|
|
||||||
|
CCrypter crypter;
|
||||||
|
CKeyingMaterial vMasterKey;
|
||||||
|
BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
|
||||||
|
{
|
||||||
|
if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
|
||||||
|
return false;
|
||||||
|
if(!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
|
||||||
|
return false;
|
||||||
|
if (CCryptoKeyStore::Unlock(vMasterKey))
|
||||||
|
{
|
||||||
|
int64 nStartTime = GetTimeMillis();
|
||||||
|
crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
|
||||||
|
pMasterKey.second.nDeriveIterations = pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime)));
|
||||||
|
|
||||||
|
nStartTime = GetTimeMillis();
|
||||||
|
crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
|
||||||
|
pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
|
||||||
|
|
||||||
|
if (pMasterKey.second.nDeriveIterations < 25000)
|
||||||
|
pMasterKey.second.nDeriveIterations = 25000;
|
||||||
|
|
||||||
|
printf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
|
||||||
|
|
||||||
|
if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
|
||||||
|
return false;
|
||||||
|
if (!crypter.Encrypt(vMasterKey, pMasterKey.second.vchCryptedKey))
|
||||||
|
return false;
|
||||||
|
CWalletDB(strWalletFile).WriteMasterKey(pMasterKey.first, pMasterKey.second);
|
||||||
|
if (fWasLocked)
|
||||||
|
Lock();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This class implements an addrIncoming entry that causes pre-0.4
|
||||||
|
// clients to crash on startup if reading a private-key-encrypted wallet.
|
||||||
|
class CCorruptAddress
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IMPLEMENT_SERIALIZE
|
||||||
|
(
|
||||||
|
if (nType & SER_DISK)
|
||||||
|
READWRITE(nVersion);
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
bool CWallet::EncryptWallet(const string& strWalletPassphrase)
|
||||||
|
{
|
||||||
|
CRITICAL_BLOCK(cs_mapPubKeys)
|
||||||
|
CRITICAL_BLOCK(cs_KeyStore)
|
||||||
|
CRITICAL_BLOCK(cs_vMasterKey)
|
||||||
|
CRITICAL_BLOCK(cs_pwalletdbEncryption)
|
||||||
|
{
|
||||||
|
if (IsCrypted())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CKeyingMaterial vMasterKey;
|
||||||
|
RandAddSeedPerfmon();
|
||||||
|
|
||||||
|
vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
|
||||||
|
RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
|
||||||
|
|
||||||
|
CMasterKey kMasterKey;
|
||||||
|
|
||||||
|
RandAddSeedPerfmon();
|
||||||
|
kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
|
||||||
|
RAND_bytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
|
||||||
|
|
||||||
|
CCrypter crypter;
|
||||||
|
int64 nStartTime = GetTimeMillis();
|
||||||
|
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
|
||||||
|
kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
|
||||||
|
|
||||||
|
nStartTime = GetTimeMillis();
|
||||||
|
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
|
||||||
|
kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
|
||||||
|
|
||||||
|
if (kMasterKey.nDeriveIterations < 25000)
|
||||||
|
kMasterKey.nDeriveIterations = 25000;
|
||||||
|
|
||||||
|
printf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
|
||||||
|
|
||||||
|
if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
|
||||||
|
return false;
|
||||||
|
if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
|
||||||
|
if (fFileBacked)
|
||||||
|
{
|
||||||
|
pwalletdbEncryption = new CWalletDB(strWalletFile);
|
||||||
|
pwalletdbEncryption->TxnBegin();
|
||||||
|
pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!EncryptKeys(vMasterKey))
|
||||||
|
{
|
||||||
|
if (fFileBacked)
|
||||||
|
pwalletdbEncryption->TxnAbort();
|
||||||
|
exit(1); //We now probably have half of our keys encrypted in memory, and half not...die and let the user reload their unencrypted wallet.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fFileBacked)
|
||||||
|
{
|
||||||
|
CCorruptAddress corruptAddress;
|
||||||
|
pwalletdbEncryption->WriteSetting("addrIncoming", corruptAddress);
|
||||||
|
if (!pwalletdbEncryption->TxnCommit())
|
||||||
|
exit(1); //We now have keys encrypted in memory, but no on disk...die to avoid confusion and let the user reload their unencrypted wallet.
|
||||||
|
|
||||||
|
pwalletdbEncryption->Close();
|
||||||
|
pwalletdbEncryption = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lock();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWallet::WalletUpdateSpent(const CTransaction &tx)
|
void CWallet::WalletUpdateSpent(const CTransaction &tx)
|
||||||
|
@ -98,7 +269,10 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn)
|
||||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||||
{
|
{
|
||||||
if (txout.scriptPubKey == scriptDefaultKey)
|
if (txout.scriptPubKey == scriptDefaultKey)
|
||||||
SetDefaultKey(GetKeyFromKeyPool());
|
{
|
||||||
|
SetDefaultKey(GetOrReuseKeyFromPool());
|
||||||
|
SetAddressBookName(PubKeyToAddress(vchDefaultKey), "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// Notify UI
|
// Notify UI
|
||||||
|
@ -552,8 +726,6 @@ void CWallet::ResendWalletTransactions()
|
||||||
|
|
||||||
int64 CWallet::GetBalance() const
|
int64 CWallet::GetBalance() const
|
||||||
{
|
{
|
||||||
int64 nStart = GetTimeMillis();
|
|
||||||
|
|
||||||
int64 nTotal = 0;
|
int64 nTotal = 0;
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
CRITICAL_BLOCK(cs_mapWallet)
|
||||||
{
|
{
|
||||||
|
@ -566,7 +738,6 @@ int64 CWallet::GetBalance() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//printf("GetBalance() %"PRI64d"ms\n", GetTimeMillis() - nStart);
|
|
||||||
return nTotal;
|
return nTotal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -798,7 +969,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CW
|
||||||
|
|
||||||
// Reserve a new key pair from key pool
|
// Reserve a new key pair from key pool
|
||||||
vector<unsigned char> vchPubKey = reservekey.GetReservedKey();
|
vector<unsigned char> vchPubKey = reservekey.GetReservedKey();
|
||||||
assert(mapKeys.count(vchPubKey));
|
// 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;
|
||||||
|
@ -918,15 +1089,24 @@ string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew,
|
||||||
{
|
{
|
||||||
CReserveKey reservekey(this);
|
CReserveKey reservekey(this);
|
||||||
int64 nFeeRequired;
|
int64 nFeeRequired;
|
||||||
if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
|
CRITICAL_BLOCK(cs_vMasterKey)
|
||||||
{
|
{
|
||||||
string strError;
|
if (IsLocked())
|
||||||
if (nValue + nFeeRequired > GetBalance())
|
{
|
||||||
strError = strprintf(_("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds "), FormatMoney(nFeeRequired).c_str());
|
string strError = _("Error: Wallet locked, unable to create transaction ");
|
||||||
else
|
printf("SendMoney() : %s", strError.c_str());
|
||||||
strError = _("Error: Transaction creation failed ");
|
return strError;
|
||||||
printf("SendMoney() : %s", strError.c_str());
|
}
|
||||||
return strError;
|
if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
|
||||||
|
{
|
||||||
|
string strError;
|
||||||
|
if (nValue + nFeeRequired > GetBalance())
|
||||||
|
strError = strprintf(_("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds "), FormatMoney(nFeeRequired).c_str());
|
||||||
|
else
|
||||||
|
strError = _("Error: Transaction creation failed ");
|
||||||
|
printf("SendMoney() : %s", strError.c_str());
|
||||||
|
return strError;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL))
|
if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL))
|
||||||
|
@ -961,27 +1141,28 @@ string CWallet::SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWall
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool CWallet::LoadWallet(bool& fFirstRunRet)
|
int CWallet::LoadWallet(bool& fFirstRunRet)
|
||||||
{
|
{
|
||||||
if (!fFileBacked)
|
if (!fFileBacked)
|
||||||
return false;
|
return false;
|
||||||
fFirstRunRet = false;
|
fFirstRunRet = false;
|
||||||
if (!CWalletDB(strWalletFile,"cr+").LoadWallet(this))
|
int nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
|
||||||
return false;
|
if (nLoadWalletRet != DB_LOAD_OK)
|
||||||
|
return nLoadWalletRet;
|
||||||
fFirstRunRet = vchDefaultKey.empty();
|
fFirstRunRet = vchDefaultKey.empty();
|
||||||
|
|
||||||
if (!mapKeys.count(vchDefaultKey))
|
if (!HaveKey(vchDefaultKey))
|
||||||
{
|
{
|
||||||
// Create new default key
|
// Create new keyUser and set as default key
|
||||||
RandAddSeedPerfmon();
|
RandAddSeedPerfmon();
|
||||||
|
|
||||||
SetDefaultKey(GetKeyFromKeyPool());
|
SetDefaultKey(GetOrReuseKeyFromPool());
|
||||||
if (!SetAddressBookName(PubKeyToAddress(vchDefaultKey), ""))
|
if (!SetAddressBookName(PubKeyToAddress(vchDefaultKey), ""))
|
||||||
return false;
|
return DB_LOAD_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateThread(ThreadFlushWalletDB, &strWalletFile);
|
CreateThread(ThreadFlushWalletDB, &strWalletFile);
|
||||||
return true;
|
return DB_LOAD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1048,14 +1229,16 @@ bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
|
bool CWallet::TopUpKeyPool()
|
||||||
{
|
{
|
||||||
nIndex = -1;
|
|
||||||
keypool.vchPubKey.clear();
|
|
||||||
CRITICAL_BLOCK(cs_main)
|
CRITICAL_BLOCK(cs_main)
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
CRITICAL_BLOCK(cs_mapWallet)
|
||||||
CRITICAL_BLOCK(cs_setKeyPool)
|
CRITICAL_BLOCK(cs_setKeyPool)
|
||||||
|
CRITICAL_BLOCK(cs_vMasterKey)
|
||||||
{
|
{
|
||||||
|
if (IsLocked())
|
||||||
|
return false;
|
||||||
|
|
||||||
CWalletDB walletdb(strWalletFile);
|
CWalletDB walletdb(strWalletFile);
|
||||||
|
|
||||||
// Top up key pool
|
// Top up key pool
|
||||||
|
@ -1066,18 +1249,36 @@ void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
|
||||||
if (!setKeyPool.empty())
|
if (!setKeyPool.empty())
|
||||||
nEnd = *(--setKeyPool.end()) + 1;
|
nEnd = *(--setKeyPool.end()) + 1;
|
||||||
if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
|
if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
|
||||||
throw runtime_error("ReserveKeyFromKeyPool() : writing generated key failed");
|
throw runtime_error("TopUpKeyPool() : writing generated key failed");
|
||||||
setKeyPool.insert(nEnd);
|
setKeyPool.insert(nEnd);
|
||||||
printf("keypool added key %"PRI64d", size=%d\n", nEnd, setKeyPool.size());
|
printf("keypool added key %"PRI64d", size=%d\n", nEnd, setKeyPool.size());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
|
||||||
|
{
|
||||||
|
nIndex = -1;
|
||||||
|
keypool.vchPubKey.clear();
|
||||||
|
CRITICAL_BLOCK(cs_main)
|
||||||
|
CRITICAL_BLOCK(cs_mapWallet)
|
||||||
|
CRITICAL_BLOCK(cs_setKeyPool)
|
||||||
|
{
|
||||||
|
if (!IsLocked())
|
||||||
|
TopUpKeyPool();
|
||||||
|
|
||||||
// Get the oldest key
|
// Get the oldest key
|
||||||
assert(!setKeyPool.empty());
|
if(setKeyPool.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
CWalletDB walletdb(strWalletFile);
|
||||||
|
|
||||||
nIndex = *(setKeyPool.begin());
|
nIndex = *(setKeyPool.begin());
|
||||||
setKeyPool.erase(setKeyPool.begin());
|
setKeyPool.erase(setKeyPool.begin());
|
||||||
if (!walletdb.ReadPool(nIndex, keypool))
|
if (!walletdb.ReadPool(nIndex, keypool))
|
||||||
throw runtime_error("ReserveKeyFromKeyPool() : read failed");
|
throw runtime_error("ReserveKeyFromKeyPool() : read failed");
|
||||||
if (!mapKeys.count(keypool.vchPubKey))
|
if (!HaveKey(keypool.vchPubKey))
|
||||||
throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
|
throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
|
||||||
assert(!keypool.vchPubKey.empty());
|
assert(!keypool.vchPubKey.empty());
|
||||||
printf("keypool reserve %"PRI64d"\n", nIndex);
|
printf("keypool reserve %"PRI64d"\n", nIndex);
|
||||||
|
@ -1106,11 +1307,13 @@ void CWallet::ReturnKey(int64 nIndex)
|
||||||
printf("keypool return %"PRI64d"\n", nIndex);
|
printf("keypool return %"PRI64d"\n", nIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<unsigned char> CWallet::GetKeyFromKeyPool()
|
vector<unsigned char> CWallet::GetOrReuseKeyFromPool()
|
||||||
{
|
{
|
||||||
int64 nIndex = 0;
|
int64 nIndex = 0;
|
||||||
CKeyPool keypool;
|
CKeyPool keypool;
|
||||||
ReserveKeyFromKeyPool(nIndex, keypool);
|
ReserveKeyFromKeyPool(nIndex, keypool);
|
||||||
|
if(nIndex == -1)
|
||||||
|
return vchDefaultKey;
|
||||||
KeepKey(nIndex);
|
KeepKey(nIndex);
|
||||||
return keypool.vchPubKey;
|
return keypool.vchPubKey;
|
||||||
}
|
}
|
||||||
|
@ -1120,6 +1323,8 @@ int64 CWallet::GetOldestKeyPoolTime()
|
||||||
int64 nIndex = 0;
|
int64 nIndex = 0;
|
||||||
CKeyPool keypool;
|
CKeyPool keypool;
|
||||||
ReserveKeyFromKeyPool(nIndex, keypool);
|
ReserveKeyFromKeyPool(nIndex, keypool);
|
||||||
|
if (nIndex == -1)
|
||||||
|
return GetTime();
|
||||||
ReturnKey(nIndex);
|
ReturnKey(nIndex);
|
||||||
return keypool.nTime;
|
return keypool.nTime;
|
||||||
}
|
}
|
||||||
|
@ -1130,7 +1335,13 @@ vector<unsigned char> CReserveKey::GetReservedKey()
|
||||||
{
|
{
|
||||||
CKeyPool keypool;
|
CKeyPool keypool;
|
||||||
pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
|
pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
|
||||||
vchPubKey = keypool.vchPubKey;
|
if (nIndex != -1)
|
||||||
|
vchPubKey = keypool.vchPubKey;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("CReserveKey::GetReservedKey(): Warning: using default key instead of a new key, top up your keypool.");
|
||||||
|
vchPubKey = pwallet->vchDefaultKey;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
assert(!vchPubKey.empty());
|
assert(!vchPubKey.empty());
|
||||||
return vchPubKey;
|
return vchPubKey;
|
||||||
|
|
31
src/wallet.h
31
src/wallet.h
|
@ -12,12 +12,14 @@ class CWalletTx;
|
||||||
class CReserveKey;
|
class CReserveKey;
|
||||||
class CWalletDB;
|
class CWalletDB;
|
||||||
|
|
||||||
class CWallet : public CKeyStore
|
class CWallet : public CCryptoKeyStore
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const;
|
bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const;
|
||||||
bool SelectCoins(int64 nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const;
|
bool SelectCoins(int64 nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const;
|
||||||
|
|
||||||
|
CWalletDB *pwalletdbEncryption;
|
||||||
|
CCriticalSection cs_pwalletdbEncryption;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool fFileBacked;
|
bool fFileBacked;
|
||||||
|
@ -26,14 +28,22 @@ public:
|
||||||
std::set<int64> setKeyPool;
|
std::set<int64> setKeyPool;
|
||||||
CCriticalSection cs_setKeyPool;
|
CCriticalSection cs_setKeyPool;
|
||||||
|
|
||||||
|
typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
|
||||||
|
MasterKeyMap mapMasterKeys;
|
||||||
|
unsigned int nMasterKeyMaxID;
|
||||||
|
|
||||||
CWallet()
|
CWallet()
|
||||||
{
|
{
|
||||||
fFileBacked = false;
|
fFileBacked = false;
|
||||||
|
nMasterKeyMaxID = 0;
|
||||||
|
pwalletdbEncryption = NULL;
|
||||||
}
|
}
|
||||||
CWallet(std::string strWalletFileIn)
|
CWallet(std::string strWalletFileIn)
|
||||||
{
|
{
|
||||||
strWalletFile = strWalletFileIn;
|
strWalletFile = strWalletFileIn;
|
||||||
fFileBacked = true;
|
fFileBacked = true;
|
||||||
|
nMasterKeyMaxID = 0;
|
||||||
|
pwalletdbEncryption = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutable CCriticalSection cs_mapWallet;
|
mutable CCriticalSection cs_mapWallet;
|
||||||
|
@ -48,7 +58,16 @@ public:
|
||||||
|
|
||||||
std::vector<unsigned char> vchDefaultKey;
|
std::vector<unsigned char> vchDefaultKey;
|
||||||
|
|
||||||
|
// keystore implementation
|
||||||
bool AddKey(const CKey& key);
|
bool AddKey(const CKey& key);
|
||||||
|
bool LoadKey(const CKey& key) { return CCryptoKeyStore::AddKey(key); }
|
||||||
|
bool AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
|
||||||
|
bool LoadCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) { return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret); }
|
||||||
|
|
||||||
|
bool Unlock(const std::string& strWalletPassphrase);
|
||||||
|
bool ChangeWalletPassphrase(const std::string& strOldWalletPassphrase, const std::string& strNewWalletPassphrase);
|
||||||
|
bool EncryptWallet(const std::string& strWalletPassphrase);
|
||||||
|
|
||||||
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 EraseFromWallet(uint256 hash);
|
bool EraseFromWallet(uint256 hash);
|
||||||
|
@ -65,10 +84,11 @@ public:
|
||||||
std::string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
|
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);
|
std::string SendMoneyToBitcoinAddress(std::string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
|
||||||
|
|
||||||
|
bool TopUpKeyPool();
|
||||||
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);
|
||||||
std::vector<unsigned char> GetKeyFromKeyPool();
|
std::vector<unsigned char> GetOrReuseKeyFromPool();
|
||||||
int64 GetOldestKeyPoolTime();
|
int64 GetOldestKeyPoolTime();
|
||||||
|
|
||||||
bool IsMine(const CTxIn& txin) const;
|
bool IsMine(const CTxIn& txin) const;
|
||||||
|
@ -148,7 +168,7 @@ public:
|
||||||
walletdb.WriteBestBlock(loc);
|
walletdb.WriteBestBlock(loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadWallet(bool& fFirstRunRet);
|
int LoadWallet(bool& fFirstRunRet);
|
||||||
// bool BackupWallet(const std::string& strDest);
|
// bool BackupWallet(const std::string& strDest);
|
||||||
|
|
||||||
// requires cs_mapAddressBook lock
|
// requires cs_mapAddressBook lock
|
||||||
|
@ -175,6 +195,11 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GetKeyPoolSize()
|
||||||
|
{
|
||||||
|
return setKeyPool.size();
|
||||||
|
}
|
||||||
|
|
||||||
bool GetTransaction(const uint256 &hashTx, CWalletTx& wtx);
|
bool GetTransaction(const uint256 &hashTx, CWalletTx& wtx);
|
||||||
|
|
||||||
bool SetDefaultKey(const std::vector<unsigned char> &vchPubKey);
|
bool SetDefaultKey(const std::vector<unsigned char> &vchPubKey);
|
||||||
|
|
Loading…
Add table
Reference in a new issue