return key.GetPubKey();
}
+CMalleableKeyView CWallet::GenerateNewMalleableKey()
+{
+ RandAddSeedPerfmon();
+
+ // Compressed public keys were introduced in version 0.6.0
+ SetMinVersion(FEATURE_MALLKEY);
+
+ CMalleableKey mKey;
+ mKey.MakeNewKeys();
+ const CMalleableKeyView &keyView(mKey);
+
+ // Create new metadata
+ int64_t nCreationTime = GetTime();
+ mapMalleableKeyMetadata[keyView] = CKeyMetadata(nCreationTime);
+ if (!nTimeFirstKey || nCreationTime < nTimeFirstKey)
+ nTimeFirstKey = nCreationTime;
+
+ if (!AddMalleableKey(mKey))
+ throw std::runtime_error("CWallet::GenerateNewMalleableKey() : AddMalleableKey failed");
+ return CMalleableKeyView(mKey);
+}
+
bool CWallet::AddKey(const CKey& key)
{
CPubKey pubkey = key.GetPubKey();
return true;
}
+bool CWallet::AddMalleableKey(const CMalleableKey& mKey)
+{
+ CMalleableKeyView keyView = CMalleableKeyView(mKey);
+ if (!CCryptoKeyStore::AddMalleableKey(mKey))
+ return false;
+ if (!fFileBacked)
+ return true;
+ if (!IsCrypted())
+ return CWalletDB(strWalletFile).WriteMalleableKey(keyView, mKey, mapMalleableKeyMetadata[keyView]);
+ return true;
+}
+
bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, const vector<unsigned char> &vchCryptedSecret)
{
if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
return true;
}
+bool CWallet::LoadMalleableKeyMetadata(const CMalleableKeyView &keyView, const CKeyMetadata &metadata)
+{
+ if (metadata.nCreateTime && (!nTimeFirstKey || metadata.nCreateTime < nTimeFirstKey))
+ nTimeFirstKey = metadata.nCreateTime;
+
+ mapMalleableKeyMetadata[keyView] = metadata;
+ return true;
+}
+
bool CWallet::AddCScript(const CScript& redeemScript)
{
if (!CCryptoKeyStore::AddCScript(redeemScript))
{
int64_t nStartTime = GetTimeMillis();
crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
- pMasterKey.second.nDeriveIterations = pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime)));
+ double nFirstMultiplier = 1e2 / (GetTimeMillis() - nStartTime);
+ pMasterKey.second.nDeriveIterations = (uint32_t)(pMasterKey.second.nDeriveIterations *nFirstMultiplier);
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;
+ double nSecondMultiplier = 1e2 / (GetTimeMillis() - nStartTime);
+ pMasterKey.second.nDeriveIterations = (uint32_t)((pMasterKey.second.nDeriveIterations + pMasterKey.second.nDeriveIterations * nSecondMultiplier) / 2);
if (pMasterKey.second.nDeriveIterations < 25000)
pMasterKey.second.nDeriveIterations = 25000;
CCrypter crypter;
int64_t nStartTime = GetTimeMillis();
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
- kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
+ int64_t nDivider = GetTimeMillis() - nStartTime;
+ kMasterKey.nDeriveIterations = (uint32_t)(25e5 / (double)(nDivider));
nStartTime = GetTimeMillis();
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
- kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
+ double nMultiplier = 1e2 / (GetTimeMillis() - nStartTime);
+ kMasterKey.nDeriveIterations = (uint32_t)((kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * nMultiplier) / 2);
if (kMasterKey.nDeriveIterations < 25000)
kMasterKey.nDeriveIterations = 25000;
uint256 hash = tx.GetHash();
{
LOCK(cs_wallet);
- bool fExisted = mapWallet.count(hash);
+ bool fExisted = mapWallet.count(hash) != 0;
if (fExisted && !fUpdate) return false;
if (fExisted || IsMine(tx) || IsFromMe(tx))
{
{
// Do this infrequently and randomly to avoid giving away
// that these are our transactions.
- static int64_t nNextTime;
+ static int64_t nNextTime = GetRand(GetTime() + 30 * 60);
if (GetTime() < nNextTime)
return;
bool fFirst = (nNextTime == 0);
return;
// Only do it if there's been a new block since last time
- static int64_t nLastTime;
+ static int64_t nLastTime = 0;
if (nTimeBestReceived < nLastTime)
return;
nLastTime = GetTime();
void CWallet::GetStakeWeightFromValue(const int64_t& nTime, const int64_t& nValue, uint64_t& nWeight)
{
- int64_t nTimeWeight = GetWeight(nTime, (int64_t)GetTime());
+ int64_t nTimeWeight = GetWeight(nTime, GetTime());
// If time weight is lower or equal to zero then weight is zero.
if (nTimeWeight <= 0)
return;
}
- CBigNum bnCoinDayWeight = CBigNum(nValue) * nTimeWeight / COIN / (24 * 60 * 60);
+ CBigNum bnCoinDayWeight = CBigNum(nValue) * nTimeWeight / COIN / nOneDay;
nWeight = bnCoinDayWeight.getuint64();
}
-
-// NovaCoin: get current stake miner statistics
-void CWallet::GetStakeStats(float &nKernelsRate, float &nCoinDaysRate)
-{
- static uint64_t nLastKernels = 0, nLastCoinDays = 0;
- static float nLastKernelsRate = 0, nLastCoinDaysRate = 0;
- static int64_t nLastTime = GetTime();
-
- if (nKernelsTried < nLastKernels)
- {
- nLastKernels = 0;
- nLastCoinDays = 0;
-
- nLastTime = GetTime();
- }
-
- int64_t nInterval = GetTime() - nLastTime;
- //if (nKernelsTried > 1000 && nInterval > 5)
- if (nInterval > 10)
- {
- nKernelsRate = nLastKernelsRate = ( nKernelsTried - nLastKernels ) / (float) nInterval;
- nCoinDaysRate = nLastCoinDaysRate = ( nCoinDaysTried - nLastCoinDays ) / (float) nInterval;
-
- nLastKernels = nKernelsTried;
- nLastCoinDays = nCoinDaysTried;
- nLastTime = GetTime();
- }
- else
- {
- nKernelsRate = nLastKernelsRate;
- nCoinDaysRate = nLastCoinDaysRate;
- }
-}
-
bool CWallet::MergeCoins(const int64_t& nAmount, const int64_t& nMinValue, const int64_t& nOutputValue, list<uint256>& listMerged)
{
int64_t nBalance = GetBalance();
if (setCoins.empty())
return false;
- bool fMaxTimeWeight = false;
+ bool fDontSplitCoins = false;
if (GetWeight((int64_t)wtx.nTime, (int64_t)nGenerationTime) == nStakeMaxAge)
{
// Only one output for old kernel inputs
vwtxPrev.push_back(pcoin->first);
}
- fMaxTimeWeight = true;
+ fDontSplitCoins = true;
}
else
{
- // Split stake input if maximum weight isn't reached yet
- txNew.vout.push_back(CTxOut(0, scriptPubKeyOut));
- txNew.vout.push_back(CTxOut(0, scriptPubKeyOut));
+ int64_t nSplitThreshold = GetArg("-splitthreshold", nCombineThreshold);
if (fDebug && GetBoolArg("-printcoinstake"))
- printf("CreateCoinStake : maximum time weight isn't reached, splitting coinstake\n");
+ printf("CreateCoinStake : nSplitThreshold=%" PRId64 "\n", nSplitThreshold);
+
+ if (nCredit > nSplitThreshold)
+ {
+ // Split stake input if credit is lower than combine threshold and maximum weight isn't reached yet
+ txNew.vout.push_back(CTxOut(0, scriptPubKeyOut));
+ txNew.vout.push_back(CTxOut(0, scriptPubKeyOut));
+
+ if (fDebug && GetBoolArg("-printcoinstake"))
+ printf("CreateCoinStake : splitting coinstake\n");
+ }
+ else
+ {
+ txNew.vout.push_back(CTxOut(0, scriptPubKeyOut));
+ fDontSplitCoins = true;
+ }
}
// Calculate coin age reward
while (true)
{
// Set output amount
- if (fMaxTimeWeight)
+ if (fDontSplitCoins)
txNew.vout[1].nValue = nCredit - nMinFee;
else
{
string CWallet::SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew, bool fAskFee)
{
+ // Check amount
+ if (nValue <= 0)
+ return _("Invalid amount");
+ if (nValue + nTransactionFee > GetBalance())
+ return _("Insufficient funds");
+
CReserveKey reservekey(this);
int64_t nFeeRequired;
return "";
}
-
-
-string CWallet::SendMoneyToDestination(const CTxDestination& address, int64_t nValue, CWalletTx& wtxNew, bool fAskFee)
-{
- // Check amount
- if (nValue <= 0)
- return _("Invalid amount");
- if (nValue + nTransactionFee > GetBalance())
- return _("Insufficient funds");
-
- // Parse Bitcoin address
- CScript scriptPubKey;
- scriptPubKey.SetDestination(address);
-
- return SendMoney(scriptPubKey, nValue, wtxNew, fAskFee);
-}
-
-
-
-
DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
{
if (!fFileBacked)
{
std::map<CTxDestination, std::string>::iterator mi = mapAddressBook.find(address);
mapAddressBook[address] = strName;
- NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address), (mi == mapAddressBook.end()) ? CT_NEW : CT_UPDATED);
+ NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address) != MINE_NO, (mi == mapAddressBook.end()) ? CT_NEW : CT_UPDATED);
if (!fFileBacked)
return false;
return CWalletDB(strWalletFile).WriteName(CBitcoinAddress(address).ToString(), strName);
bool CWallet::DelAddressBookName(const CTxDestination& address)
{
mapAddressBook.erase(address);
- NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address), CT_DELETED);
+ NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address) != MINE_NO, CT_DELETED);
if (!fFileBacked)
return false;
return CWalletDB(strWalletFile).EraseName(CBitcoinAddress(address).ToString());
{
if (IsMine(pcoin->vout[n]) && pcoin->IsSpent(n) && (txindex.vSpent.size() <= n || txindex.vSpent[n].IsNull()))
{
- printf("FixSpentCoins found lost coin %sppc %s[%d], %s\n",
+ printf("FixSpentCoins found lost coin %sppc %s[%u], %s\n",
FormatMoney(pcoin->vout[n].nValue).c_str(), pcoin->GetHash().ToString().c_str(), n, fCheckOnly? "repair not attempted" : "repairing");
nMismatchFound++;
nBalanceInQuestion += pcoin->vout[n].nValue;
}
else if (IsMine(pcoin->vout[n]) && !pcoin->IsSpent(n) && (txindex.vSpent.size() > n && !txindex.vSpent[n].IsNull()))
{
- printf("FixSpentCoins found spent coin %sppc %s[%d], %s\n",
+ printf("FixSpentCoins found spent coin %sppc %s[%u], %s\n",
FormatMoney(pcoin->vout[n].nValue).c_str(), pcoin->GetHash().ToString().c_str(), n, fCheckOnly? "repair not attempted" : "repairing");
nMismatchFound++;
nBalanceInQuestion += pcoin->vout[n].nValue;
for(list<uint256>::const_iterator it = orphans.begin(); it != orphans.end(); ++it)
EraseFromWallet(*it);
}
+
+bool CWallet::ExtractAddress(const CScript& scriptPubKey, std::string& addressRet)
+{
+ vector<valtype> vSolutions;
+ txnouttype whichType;
+ if (!Solver(scriptPubKey, whichType, vSolutions))
+ return false;
+
+ if (whichType == TX_PUBKEY)
+ {
+ addressRet = CBitcoinAddress(CPubKey(vSolutions[0]).GetID()).ToString();
+ return true;
+ }
+ if (whichType == TX_PUBKEY_DROP)
+ {
+ // Pay-to-Pubkey-R
+ CMalleableKeyView view;
+ if (!CheckOwnership(CPubKey(vSolutions[0]), CPubKey(vSolutions[1]), view))
+ return false;
+
+ addressRet = view.GetMalleablePubKey().ToString();
+ return true;
+ }
+ else if (whichType == TX_PUBKEYHASH)
+ {
+ addressRet = CBitcoinAddress(CKeyID(uint160(vSolutions[0]))).ToString();
+ return true;
+ }
+ else if (whichType == TX_SCRIPTHASH)
+ {
+ addressRet = CBitcoinAddress(CScriptID(uint160(vSolutions[0]))).ToString();
+ return true;
+ }
+ // Multisig txns have more than one address...
+ return false;
+}