X-Git-Url: https://git.novaco.in/?p=novacoin.git;a=blobdiff_plain;f=src%2Fwallet.cpp;h=e49c2150e6265664992eca6de199d399f69bd45d;hp=eb83806e81cc8850841ced053fba4dfb68353de0;hb=16163ca1b076ee1e6e2c99cc67695e6e654a3293;hpb=bcbca1d182c8544d36058ce3017df04649d083ed diff --git a/src/wallet.cpp b/src/wallet.cpp index eb83806..e49c215 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -9,6 +9,7 @@ #include "ui_interface.h" #include "base58.h" #include "kernel.h" +#include using namespace std; extern int nStakeMaxAge; @@ -40,6 +41,14 @@ CPubKey CWallet::GenerateNewKey() if (fCompressed) SetMinVersion(FEATURE_COMPRPUBKEY); + CPubKey pubkey = key.GetPubKey(); + + // Create new metadata + int64 nCreationTime = GetTime(); + mapKeyMetadata[pubkey.GetID()] = CKeyMetadata(nCreationTime); + if (!nTimeFirstKey || nCreationTime < nTimeFirstKey) + nTimeFirstKey = nCreationTime; + if (!AddKey(key)) throw std::runtime_error("CWallet::GenerateNewKey() : AddKey failed"); return key.GetPubKey(); @@ -47,12 +56,14 @@ CPubKey CWallet::GenerateNewKey() bool CWallet::AddKey(const CKey& key) { + CPubKey pubkey = key.GetPubKey(); + if (!CCryptoKeyStore::AddKey(key)) return false; if (!fFileBacked) return true; if (!IsCrypted()) - return CWalletDB(strWalletFile).WriteKey(key.GetPubKey(), key.GetPrivKey()); + return CWalletDB(strWalletFile).WriteKey(pubkey, key.GetPrivKey(), mapKeyMetadata[pubkey.GetID()]); return true; } @@ -65,13 +76,22 @@ bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, const vectorWriteCryptedKey(vchPubKey, vchCryptedSecret); + return pwalletdbEncryption->WriteCryptedKey(vchPubKey, vchCryptedSecret, mapKeyMetadata[vchPubKey.GetID()]); else - return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey, vchCryptedSecret); + return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey, vchCryptedSecret, mapKeyMetadata[vchPubKey.GetID()]); } return false; } +bool CWallet::LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &meta) +{ + if (meta.nCreateTime && (!nTimeFirstKey || meta.nCreateTime < nTimeFirstKey)) + nTimeFirstKey = meta.nCreateTime; + + mapKeyMetadata[pubkey.GetID()] = meta; + return true; +} + bool CWallet::AddCScript(const CScript& redeemScript) { if (!CCryptoKeyStore::AddCScript(redeemScript)) @@ -482,6 +502,16 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn) // Notify UI of new or updated transaction NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED); + + // notify an external script when a wallet transaction comes in or is updated + std::string strCmd = GetArg("-walletnotify", ""); + + if ( !strCmd.empty()) + { + boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex()); + boost::thread t(runCommand, strCmd); // thread runs free + } + } return true; } @@ -956,7 +986,7 @@ int64 CWallet::GetBalance() const for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { const CWalletTx* pcoin = &(*it).second; - if (pcoin->IsFinal() && pcoin->IsConfirmed()) + if (pcoin->IsConfirmed()) nTotal += pcoin->GetAvailableCredit(); } } @@ -1338,8 +1368,8 @@ bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& w return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet); } -// NovaCoin: get current stake generation power -uint64 CWallet::GetStakeMintPower(const CKeyStore& keystore) +// NovaCoin: get current stake weight +uint64 CWallet::GetStakeWeight(const CKeyStore& keystore, enum StakeWeightMode mode) { LOCK2(cs_main, cs_wallet); @@ -1350,7 +1380,7 @@ uint64 CWallet::GetStakeMintPower(const CKeyStore& keystore) if (mapArgs.count("-reservebalance") && !ParseMoney(mapArgs["-reservebalance"], nReserveBalance)) { - error("CreateCoinStake : invalid reserve balance amount"); + error("GetStakeWeight : invalid reserve balance amount"); return 0; } @@ -1372,19 +1402,53 @@ uint64 CWallet::GetStakeMintPower(const CKeyStore& keystore) if (!txdb.ReadTxIndex(pcoin.first->GetHash(), txindex)) continue; - // Do not count input that is still too young - if (pcoin.first->nTime + nStakeMaxAge > GetTime()) - continue; + unsigned int nTime = pcoin.first->nTime; - CBigNum bnCentSecond = CBigNum(pcoin.first->vout[pcoin.second].nValue) * (GetTime()-pcoin.first->nTime) / CENT; - CBigNum bnCoinDay = bnCentSecond * CENT / COIN / (24 * 60 * 60); + switch(mode) + { + case STAKE_NORMAL: + // Do not count input that is still less than 30 days old + if (nTime + nStakeMinAge > GetTime()) + continue; + break; + case STAKE_MAXWEIGHT: + // Do not count input that is still less than 90 days old + if (nTime + nStakeMaxAge > GetTime()) + continue; + break; + case STAKE_MINWEIGHT: + // Count only inputs with suitable age (from 30 to 90 days old) + if (nTime + nStakeMaxAge < GetTime()) + continue; + if (nTime + nStakeMinAge > GetTime()) + continue; + break; + } + int64 nTimeWeight; - nCoinAge += bnCoinDay.getuint64(); + // Kernel hash weight starts from 0 at the 30-day min age + // this change increases active coins participating the hash and helps + // to secure the network when proof-of-stake difficulty is low + // + if(fTestNet || (STAKEWEIGHT_SWITCH_TIME < nTime)) + { + // New rule since 01 Jan 2014: Maximum TimeWeight is 90 days. + nTimeWeight = min((int64)GetTime() - nTime - nStakeMinAge, (int64)nStakeMaxAge); + } + else + { + // Current rule: Maximum TimeWeight is 60 days. + nTimeWeight = min((int64)GetTime() - nTime, (int64)nStakeMaxAge) - nStakeMinAge; + } + + CBigNum bnCoinDayWeight = CBigNum(pcoin.first->vout[pcoin.second].nValue) * nTimeWeight / COIN / (24 * 60 * 60); + + nCoinAge += bnCoinDayWeight.getuint64(); } if (fDebug && GetBoolArg("-printcoinage")) - printf("StakePower bnCoinDay=%"PRI64d"\n", nCoinAge); + printf("StakeWeight bnCoinDay=%"PRI64d"\n", nCoinAge); return nCoinAge; } @@ -1816,7 +1880,7 @@ bool CWallet::NewKeyPool() return true; } -bool CWallet::TopUpKeyPool() +bool CWallet::TopUpKeyPool(unsigned int nSize) { { LOCK(cs_wallet); @@ -1827,7 +1891,12 @@ bool CWallet::TopUpKeyPool() CWalletDB walletdb(strWalletFile); // Top up key pool - unsigned int nTargetSize = max(GetArg("-keypool", 100), 0LL); + unsigned int nTargetSize; + if (nSize > 0) + nTargetSize = nSize; + else + nTargetSize = max(GetArg("-keypool", 100), 0LL); + while (setKeyPool.size() < (nTargetSize + 1)) { int64 nEnd = 1; @@ -2172,7 +2241,7 @@ void CReserveKey::ReturnKey() vchPubKey = CPubKey(); } -void CWallet::GetAllReserveKeys(set& setAddress) +void CWallet::GetAllReserveKeys(set& setAddress) const { setAddress.clear(); @@ -2202,3 +2271,54 @@ void CWallet::UpdatedTransaction(const uint256 &hashTx) NotifyTransactionChanged(this, hashTx, CT_UPDATED); } } + +void CWallet::GetKeyBirthTimes(std::map &mapKeyBirth) const { + mapKeyBirth.clear(); + + // get birth times for keys with metadata + for (std::map::const_iterator it = mapKeyMetadata.begin(); it != mapKeyMetadata.end(); it++) + if (it->second.nCreateTime) + mapKeyBirth[it->first] = it->second.nCreateTime; + + // map in which we'll infer heights of other keys + CBlockIndex *pindexMax = FindBlockByHeight(std::max(0, nBestHeight - 144)); // the tip can be reorganised; use a 144-block safety margin + std::map mapKeyFirstBlock; + std::set setKeys; + GetKeys(setKeys); + BOOST_FOREACH(const CKeyID &keyid, setKeys) { + if (mapKeyBirth.count(keyid) == 0) + mapKeyFirstBlock[keyid] = pindexMax; + } + setKeys.clear(); + + // if there are no such keys, we're done + if (mapKeyFirstBlock.empty()) + return; + + // find first block that affects those keys, if there are any left + std::vector vAffected; + for (std::map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); it++) { + // iterate over all wallet transactions... + const CWalletTx &wtx = (*it).second; + std::map::const_iterator blit = mapBlockIndex.find(wtx.hashBlock); + if (blit != mapBlockIndex.end() && blit->second->IsInMainChain()) { + // ... which are already in a block + int nHeight = blit->second->nHeight; + BOOST_FOREACH(const CTxOut &txout, wtx.vout) { + // iterate over all their outputs + ::ExtractAffectedKeys(*this, txout.scriptPubKey, vAffected); + BOOST_FOREACH(const CKeyID &keyid, vAffected) { + // ... and all their affected keys + std::map::iterator rit = mapKeyFirstBlock.find(keyid); + if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight) + rit->second = blit->second; + } + vAffected.clear(); + } + } + } + + // Extract block timestamps for those keys + for (std::map::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++) + mapKeyBirth[it->first] = it->second->nTime - 7200; // block times can be 2h off +}