aboutsummaryrefslogtreecommitdiff
path: root/src/wallet.cpp
diff options
context:
space:
mode:
authorJonas Schnelli <[email protected]>2013-06-03 15:18:41 +0200
committerJonas Schnelli <[email protected]>2013-06-03 15:18:41 +0200
commit39fe9de6b2b255969971beca8fa25a33ad2e5750 (patch)
tree6686041f6b801d0ea5185b026a480a5be61510e6 /src/wallet.cpp
parentMaxOSX: settings fixes (#2371) (diff)
parentMerge pull request #2672 from Diapolo/Qt_testnet (diff)
downloaddiscoin-39fe9de6b2b255969971beca8fa25a33ad2e5750.tar.xz
discoin-39fe9de6b2b255969971beca8fa25a33ad2e5750.zip
Merge branch 'master' of git://github.com/bitcoin/bitcoin into prefsFix
Signed-off-by: Jonas Schnelli <[email protected]> Conflicts: bitcoin-qt.pro
Diffstat (limited to 'src/wallet.cpp')
-rw-r--r--src/wallet.cpp134
1 files changed, 89 insertions, 45 deletions
diff --git a/src/wallet.cpp b/src/wallet.cpp
index c7eb4f74e..27aab08ec 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -32,26 +32,28 @@ CPubKey CWallet::GenerateNewKey()
bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
RandAddSeedPerfmon();
- CKey key;
- key.MakeNewKey(fCompressed);
+ CKey secret;
+ secret.MakeNewKey(fCompressed);
// Compressed public keys were introduced in version 0.6.0
if (fCompressed)
SetMinVersion(FEATURE_COMPRPUBKEY);
- if (!AddKey(key))
+ CPubKey pubkey = secret.GetPubKey();
+ if (!AddKeyPubKey(secret, pubkey))
throw std::runtime_error("CWallet::GenerateNewKey() : AddKey failed");
- return key.GetPubKey();
+ return pubkey;
}
-bool CWallet::AddKey(const CKey& key)
+bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
{
- if (!CCryptoKeyStore::AddKey(key))
+ if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey))
return false;
if (!fFileBacked)
return true;
- if (!IsCrypted())
- return CWalletDB(strWalletFile).WriteKey(key.GetPubKey(), key.GetPrivKey());
+ if (!IsCrypted()) {
+ return CWalletDB(strWalletFile).WriteKey(pubkey, secret.GetPrivKey());
+ }
return true;
}
@@ -71,6 +73,11 @@ bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, const vector<unsigned char
return false;
}
+bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
+{
+ return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret);
+}
+
bool CWallet::AddCScript(const CScript& redeemScript)
{
if (!CCryptoKeyStore::AddCScript(redeemScript))
@@ -82,9 +89,6 @@ bool CWallet::AddCScript(const CScript& redeemScript)
bool CWallet::Unlock(const SecureString& strWalletPassphrase)
{
- if (!IsLocked())
- return false;
-
CCrypter crypter;
CKeyingMaterial vMasterKey;
@@ -95,7 +99,7 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase)
if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
return false;
if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
- return false;
+ continue; // try another master key
if (CCryptoKeyStore::Unlock(vMasterKey))
return true;
}
@@ -457,17 +461,19 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn)
return false;
#ifndef QT_GUI
// If default receiving address gets used, replace it with a new one
- CScript scriptDefaultKey;
- scriptDefaultKey.SetDestination(vchDefaultKey.GetID());
- BOOST_FOREACH(const CTxOut& txout, wtx.vout)
- {
- if (txout.scriptPubKey == scriptDefaultKey)
+ if (vchDefaultKey.IsValid()) {
+ CScript scriptDefaultKey;
+ scriptDefaultKey.SetDestination(vchDefaultKey.GetID());
+ BOOST_FOREACH(const CTxOut& txout, wtx.vout)
{
- CPubKey newDefaultKey;
- if (GetKeyFromPool(newDefaultKey, false))
+ if (txout.scriptPubKey == scriptDefaultKey)
{
- SetDefaultKey(newDefaultKey);
- SetAddressBookName(vchDefaultKey.GetID(), "");
+ CPubKey newDefaultKey;
+ if (GetKeyFromPool(newDefaultKey, false))
+ {
+ SetDefaultKey(newDefaultKey);
+ SetAddressBookName(vchDefaultKey.GetID(), "");
+ }
}
}
}
@@ -773,7 +779,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
if (AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, fUpdate))
ret++;
}
- pindex = pindex->pnext;
+ pindex = pindex->GetNextInMainChain();
}
}
return ret;
@@ -1134,17 +1140,24 @@ bool CWallet::SelectCoins(int64 nTargetValue, set<pair<const CWalletTx*,unsigned
-bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
+bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend,
+ CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, std::string& strFailReason)
{
int64 nValue = 0;
BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
{
if (nValue < 0)
+ {
+ strFailReason = _("Transaction amounts must be positive");
return false;
+ }
nValue += s.second;
}
if (vecSend.empty() || nValue < 0)
+ {
+ strFailReason = _("Transaction amounts must be positive");
return false;
+ }
wtxNew.BindWallet(this);
@@ -1162,13 +1175,24 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CW
double dPriority = 0;
// vouts to the payees
BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
- wtxNew.vout.push_back(CTxOut(s.second, s.first));
+ {
+ CTxOut txout(s.second, s.first);
+ if (txout.IsDust())
+ {
+ strFailReason = _("Transaction amount too small");
+ return false;
+ }
+ wtxNew.vout.push_back(txout);
+ }
// Choose coins to use
set<pair<const CWalletTx*,unsigned int> > setCoins;
int64 nValueIn = 0;
if (!SelectCoins(nTotalValue, setCoins, nValueIn))
+ {
+ strFailReason = _("Insufficient funds");
return false;
+ }
BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
{
int64 nCredit = pcoin.first->vout[pcoin.second].nValue;
@@ -1179,12 +1203,12 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CW
}
int64 nChange = nValueIn - nValue - nFeeRet;
- // if sub-cent change is required, the fee must be raised to at least MIN_TX_FEE
+ // if sub-cent change is required, the fee must be raised to at least nMinTxFee
// or until nChange becomes zero
// NOTE: this depends on the exact behaviour of GetMinFee
- if (nFeeRet < MIN_TX_FEE && nChange > 0 && nChange < CENT)
+ if (nFeeRet < CTransaction::nMinTxFee && nChange > 0 && nChange < CENT)
{
- int64 nMoveToFee = min(nChange, MIN_TX_FEE - nFeeRet);
+ int64 nMoveToFee = min(nChange, CTransaction::nMinTxFee - nFeeRet);
nChange -= nMoveToFee;
nFeeRet += nMoveToFee;
}
@@ -1199,8 +1223,8 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CW
// post-backup change.
// Reserve a new key pair from key pool
- CPubKey vchPubKey = reservekey.GetReservedKey();
- // assert(mapKeys.count(vchPubKey));
+ CPubKey vchPubKey;
+ assert(reservekey.GetReservedKey(vchPubKey)); // should never fail, as we just unlocked
// Fill a vout to ourself
// TODO: pass in scriptChange instead of reservekey so
@@ -1208,9 +1232,21 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CW
CScript scriptChange;
scriptChange.SetDestination(vchPubKey.GetID());
- // Insert change txn at random position:
- vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size()+1);
- wtxNew.vout.insert(position, CTxOut(nChange, scriptChange));
+ CTxOut newTxOut(nChange, scriptChange);
+
+ // Never create dust outputs; if we would, just
+ // add the dust to the fee.
+ if (newTxOut.IsDust())
+ {
+ nFeeRet += nChange;
+ reservekey.ReturnKey();
+ }
+ else
+ {
+ // Insert change txn at random position:
+ vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size()+1);
+ wtxNew.vout.insert(position, newTxOut);
+ }
}
else
reservekey.ReturnKey();
@@ -1223,12 +1259,18 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CW
int nIn = 0;
BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
if (!SignSignature(*this, *coin.first, wtxNew, nIn++))
+ {
+ strFailReason = _("Signing transaction failed");
return false;
+ }
// Limit size
unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION);
if (nBytes >= MAX_STANDARD_TX_SIZE)
+ {
+ strFailReason = _("Transaction too large");
return false;
+ }
dPriority /= nBytes;
// Check that enough fee is included
@@ -1252,11 +1294,12 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CW
return true;
}
-bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
+bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue,
+ CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, std::string& strFailReason)
{
vector< pair<CScript, int64> > vecSend;
vecSend.push_back(make_pair(scriptPubKey, nValue));
- return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet);
+ return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, strFailReason);
}
// Call after CreateTransaction unless you want to abort
@@ -1322,14 +1365,12 @@ string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew,
printf("SendMoney() : %s", strError.c_str());
return strError;
}
- if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
+ string strError;
+ if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired, strError))
{
- 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());
+ printf("SendMoney() : %s\n", strError.c_str());
return strError;
}
@@ -1737,7 +1778,7 @@ set< set<CTxDestination> > CWallet::GetAddressGroupings()
return ret;
}
-CPubKey CReserveKey::GetReservedKey()
+bool CReserveKey::GetReservedKey(CPubKey& pubkey)
{
if (nIndex == -1)
{
@@ -1745,14 +1786,17 @@ CPubKey CReserveKey::GetReservedKey()
pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
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;
+ else {
+ if (pwallet->vchDefaultKey.IsValid()) {
+ printf("CReserveKey::GetReservedKey(): Warning: Using default key instead of a new key, top up your keypool!");
+ vchPubKey = pwallet->vchDefaultKey;
+ } else
+ return false;
}
}
assert(vchPubKey.IsValid());
- return vchPubKey;
+ pubkey = vchPubKey;
+ return true;
}
void CReserveKey::KeepKey()