mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-01-12 16:17:53 +00:00
Merge pull request #5509
7f991e3
c++11: These look like user-defined literals. (Cory Fields)5a6155c
c++11: don't forward-declare types used in maps (Cory Fields)3447cf8
c++11: MOVEONLY: break circular dependency in wallet (Cory Fields)bbacd88
c++11: MOVEONLY: move function definitions out of the header (Cory Fields)a2b04dd
build: fix newer boost build with c++11 (Cory Fields)
This commit is contained in:
commit
31dedb463b
@ -156,11 +156,11 @@ public:
|
||||
vSeeds.push_back(CDNSSeedData("bitcoinstats.com", "seed.bitcoinstats.com"));
|
||||
vSeeds.push_back(CDNSSeedData("xf2.org", "bitseed.xf2.org"));
|
||||
|
||||
base58Prefixes[PUBKEY_ADDRESS] = boost::assign::list_of(0);
|
||||
base58Prefixes[SCRIPT_ADDRESS] = boost::assign::list_of(5);
|
||||
base58Prefixes[SECRET_KEY] = boost::assign::list_of(128);
|
||||
base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x88)(0xB2)(0x1E);
|
||||
base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x88)(0xAD)(0xE4);
|
||||
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,0);
|
||||
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,5);
|
||||
base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1,128);
|
||||
base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x88)(0xB2)(0x1E).convert_to_container<std::vector<unsigned char> >();
|
||||
base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x88)(0xAD)(0xE4).convert_to_container<std::vector<unsigned char> >();
|
||||
|
||||
convertSeed6(vFixedSeeds, pnSeed6_main, ARRAYLEN(pnSeed6_main));
|
||||
|
||||
@ -214,11 +214,11 @@ public:
|
||||
vSeeds.push_back(CDNSSeedData("bluematt.me", "testnet-seed.bluematt.me"));
|
||||
vSeeds.push_back(CDNSSeedData("bitcoin.schildbach.de", "testnet-seed.bitcoin.schildbach.de"));
|
||||
|
||||
base58Prefixes[PUBKEY_ADDRESS] = boost::assign::list_of(111);
|
||||
base58Prefixes[SCRIPT_ADDRESS] = boost::assign::list_of(196);
|
||||
base58Prefixes[SECRET_KEY] = boost::assign::list_of(239);
|
||||
base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF);
|
||||
base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94);
|
||||
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,111);
|
||||
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,196);
|
||||
base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1,239);
|
||||
base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container<std::vector<unsigned char> >();
|
||||
base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container<std::vector<unsigned char> >();
|
||||
|
||||
convertSeed6(vFixedSeeds, pnSeed6_test, ARRAYLEN(pnSeed6_test));
|
||||
|
||||
|
@ -7,8 +7,6 @@
|
||||
|
||||
#include "crypter.h"
|
||||
#include "key.h"
|
||||
#include "script/script.h"
|
||||
#include "script/standard.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
@ -8,14 +8,13 @@
|
||||
|
||||
#include "key.h"
|
||||
#include "pubkey.h"
|
||||
#include "script/script.h"
|
||||
#include "script/standard.h"
|
||||
#include "sync.h"
|
||||
|
||||
#include <boost/signals2/signal.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
class CScript;
|
||||
class CScriptID;
|
||||
|
||||
/** A virtual base class for key stores */
|
||||
class CKeyStore
|
||||
{
|
||||
|
@ -282,21 +282,21 @@ BOOST_AUTO_TEST_CASE(strprintf_numbers)
|
||||
{
|
||||
int64_t s64t = -9223372036854775807LL; /* signed 64 bit test value */
|
||||
uint64_t u64t = 18446744073709551615ULL; /* unsigned 64 bit test value */
|
||||
BOOST_CHECK(strprintf("%s %d %s", B, s64t, E) == B" -9223372036854775807 "E);
|
||||
BOOST_CHECK(strprintf("%s %u %s", B, u64t, E) == B" 18446744073709551615 "E);
|
||||
BOOST_CHECK(strprintf("%s %x %s", B, u64t, E) == B" ffffffffffffffff "E);
|
||||
BOOST_CHECK(strprintf("%s %d %s", B, s64t, E) == B" -9223372036854775807 " E);
|
||||
BOOST_CHECK(strprintf("%s %u %s", B, u64t, E) == B" 18446744073709551615 " E);
|
||||
BOOST_CHECK(strprintf("%s %x %s", B, u64t, E) == B" ffffffffffffffff " E);
|
||||
|
||||
size_t st = 12345678; /* unsigned size_t test value */
|
||||
ssize_t sst = -12345678; /* signed size_t test value */
|
||||
BOOST_CHECK(strprintf("%s %d %s", B, sst, E) == B" -12345678 "E);
|
||||
BOOST_CHECK(strprintf("%s %u %s", B, st, E) == B" 12345678 "E);
|
||||
BOOST_CHECK(strprintf("%s %x %s", B, st, E) == B" bc614e "E);
|
||||
BOOST_CHECK(strprintf("%s %d %s", B, sst, E) == B" -12345678 " E);
|
||||
BOOST_CHECK(strprintf("%s %u %s", B, st, E) == B" 12345678 " E);
|
||||
BOOST_CHECK(strprintf("%s %x %s", B, st, E) == B" bc614e " E);
|
||||
|
||||
ptrdiff_t pt = 87654321; /* positive ptrdiff_t test value */
|
||||
ptrdiff_t spt = -87654321; /* negative ptrdiff_t test value */
|
||||
BOOST_CHECK(strprintf("%s %d %s", B, spt, E) == B" -87654321 "E);
|
||||
BOOST_CHECK(strprintf("%s %u %s", B, pt, E) == B" 87654321 "E);
|
||||
BOOST_CHECK(strprintf("%s %x %s", B, pt, E) == B" 5397fb1 "E);
|
||||
BOOST_CHECK(strprintf("%s %d %s", B, spt, E) == B" -87654321 " E);
|
||||
BOOST_CHECK(strprintf("%s %u %s", B, pt, E) == B" 87654321 " E);
|
||||
BOOST_CHECK(strprintf("%s %x %s", B, pt, E) == B" 5397fb1 " E);
|
||||
}
|
||||
#undef B
|
||||
#undef E
|
||||
|
187
src/wallet.cpp
187
src/wallet.cpp
@ -1015,6 +1015,193 @@ set<uint256> CWalletTx::GetConflicts() const
|
||||
return result;
|
||||
}
|
||||
|
||||
CAmount CWalletTx::GetDebit(const isminefilter& filter) const
|
||||
{
|
||||
if (vin.empty())
|
||||
return 0;
|
||||
|
||||
CAmount debit = 0;
|
||||
if(filter & ISMINE_SPENDABLE)
|
||||
{
|
||||
if (fDebitCached)
|
||||
debit += nDebitCached;
|
||||
else
|
||||
{
|
||||
nDebitCached = pwallet->GetDebit(*this, ISMINE_SPENDABLE);
|
||||
fDebitCached = true;
|
||||
debit += nDebitCached;
|
||||
}
|
||||
}
|
||||
if(filter & ISMINE_WATCH_ONLY)
|
||||
{
|
||||
if(fWatchDebitCached)
|
||||
debit += nWatchDebitCached;
|
||||
else
|
||||
{
|
||||
nWatchDebitCached = pwallet->GetDebit(*this, ISMINE_WATCH_ONLY);
|
||||
fWatchDebitCached = true;
|
||||
debit += nWatchDebitCached;
|
||||
}
|
||||
}
|
||||
return debit;
|
||||
}
|
||||
|
||||
CAmount CWalletTx::GetCredit(const isminefilter& filter) const
|
||||
{
|
||||
// Must wait until coinbase is safely deep enough in the chain before valuing it
|
||||
if (IsCoinBase() && GetBlocksToMaturity() > 0)
|
||||
return 0;
|
||||
|
||||
int64_t credit = 0;
|
||||
if (filter & ISMINE_SPENDABLE)
|
||||
{
|
||||
// GetBalance can assume transactions in mapWallet won't change
|
||||
if (fCreditCached)
|
||||
credit += nCreditCached;
|
||||
else
|
||||
{
|
||||
nCreditCached = pwallet->GetCredit(*this, ISMINE_SPENDABLE);
|
||||
fCreditCached = true;
|
||||
credit += nCreditCached;
|
||||
}
|
||||
}
|
||||
if (filter & ISMINE_WATCH_ONLY)
|
||||
{
|
||||
if (fWatchCreditCached)
|
||||
credit += nWatchCreditCached;
|
||||
else
|
||||
{
|
||||
nWatchCreditCached = pwallet->GetCredit(*this, ISMINE_WATCH_ONLY);
|
||||
fWatchCreditCached = true;
|
||||
credit += nWatchCreditCached;
|
||||
}
|
||||
}
|
||||
return credit;
|
||||
}
|
||||
|
||||
CAmount CWalletTx::GetImmatureCredit(bool fUseCache) const
|
||||
{
|
||||
if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
|
||||
{
|
||||
if (fUseCache && fImmatureCreditCached)
|
||||
return nImmatureCreditCached;
|
||||
nImmatureCreditCached = pwallet->GetCredit(*this, ISMINE_SPENDABLE);
|
||||
fImmatureCreditCached = true;
|
||||
return nImmatureCreditCached;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CAmount CWalletTx::GetAvailableCredit(bool fUseCache) const
|
||||
{
|
||||
if (pwallet == 0)
|
||||
return 0;
|
||||
|
||||
// Must wait until coinbase is safely deep enough in the chain before valuing it
|
||||
if (IsCoinBase() && GetBlocksToMaturity() > 0)
|
||||
return 0;
|
||||
|
||||
if (fUseCache && fAvailableCreditCached)
|
||||
return nAvailableCreditCached;
|
||||
|
||||
CAmount nCredit = 0;
|
||||
uint256 hashTx = GetHash();
|
||||
for (unsigned int i = 0; i < vout.size(); i++)
|
||||
{
|
||||
if (!pwallet->IsSpent(hashTx, i))
|
||||
{
|
||||
const CTxOut &txout = vout[i];
|
||||
nCredit += pwallet->GetCredit(txout, ISMINE_SPENDABLE);
|
||||
if (!MoneyRange(nCredit))
|
||||
throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
|
||||
}
|
||||
}
|
||||
|
||||
nAvailableCreditCached = nCredit;
|
||||
fAvailableCreditCached = true;
|
||||
return nCredit;
|
||||
}
|
||||
|
||||
CAmount CWalletTx::GetImmatureWatchOnlyCredit(const bool& fUseCache) const
|
||||
{
|
||||
if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
|
||||
{
|
||||
if (fUseCache && fImmatureWatchCreditCached)
|
||||
return nImmatureWatchCreditCached;
|
||||
nImmatureWatchCreditCached = pwallet->GetCredit(*this, ISMINE_WATCH_ONLY);
|
||||
fImmatureWatchCreditCached = true;
|
||||
return nImmatureWatchCreditCached;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CAmount CWalletTx::GetAvailableWatchOnlyCredit(const bool& fUseCache) const
|
||||
{
|
||||
if (pwallet == 0)
|
||||
return 0;
|
||||
|
||||
// Must wait until coinbase is safely deep enough in the chain before valuing it
|
||||
if (IsCoinBase() && GetBlocksToMaturity() > 0)
|
||||
return 0;
|
||||
|
||||
if (fUseCache && fAvailableWatchCreditCached)
|
||||
return nAvailableWatchCreditCached;
|
||||
|
||||
CAmount nCredit = 0;
|
||||
for (unsigned int i = 0; i < vout.size(); i++)
|
||||
{
|
||||
if (!pwallet->IsSpent(GetHash(), i))
|
||||
{
|
||||
const CTxOut &txout = vout[i];
|
||||
nCredit += pwallet->GetCredit(txout, ISMINE_WATCH_ONLY);
|
||||
if (!MoneyRange(nCredit))
|
||||
throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
|
||||
}
|
||||
}
|
||||
|
||||
nAvailableWatchCreditCached = nCredit;
|
||||
fAvailableWatchCreditCached = true;
|
||||
return nCredit;
|
||||
}
|
||||
|
||||
CAmount CWalletTx::GetChange() const
|
||||
{
|
||||
if (fChangeCached)
|
||||
return nChangeCached;
|
||||
nChangeCached = pwallet->GetChange(*this);
|
||||
fChangeCached = true;
|
||||
return nChangeCached;
|
||||
}
|
||||
|
||||
bool CWalletTx::IsTrusted() const
|
||||
{
|
||||
// Quick answer in most cases
|
||||
if (!IsFinalTx(*this))
|
||||
return false;
|
||||
int nDepth = GetDepthInMainChain();
|
||||
if (nDepth >= 1)
|
||||
return true;
|
||||
if (nDepth < 0)
|
||||
return false;
|
||||
if (!bSpendZeroConfChange || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit
|
||||
return false;
|
||||
|
||||
// Trusted if all inputs are from us and are in the mempool:
|
||||
BOOST_FOREACH(const CTxIn& txin, vin)
|
||||
{
|
||||
// Transactions not sent by us: not trusted
|
||||
const CWalletTx* parent = pwallet->GetWalletTx(txin.prevout.hash);
|
||||
if (parent == NULL)
|
||||
return false;
|
||||
const CTxOut& parentOut = parent->vout[txin.prevout.n];
|
||||
if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CWallet::ResendWalletTransactions()
|
||||
{
|
||||
// Do this infrequently and randomly to avoid giving away
|
||||
|
825
src/wallet.h
825
src/wallet.h
@ -103,6 +103,329 @@ public:
|
||||
StringMap destdata;
|
||||
};
|
||||
|
||||
|
||||
typedef std::map<std::string, std::string> mapValue_t;
|
||||
|
||||
|
||||
static void ReadOrderPos(int64_t& nOrderPos, mapValue_t& mapValue)
|
||||
{
|
||||
if (!mapValue.count("n"))
|
||||
{
|
||||
nOrderPos = -1; // TODO: calculate elsewhere
|
||||
return;
|
||||
}
|
||||
nOrderPos = atoi64(mapValue["n"].c_str());
|
||||
}
|
||||
|
||||
|
||||
static void WriteOrderPos(const int64_t& nOrderPos, mapValue_t& mapValue)
|
||||
{
|
||||
if (nOrderPos == -1)
|
||||
return;
|
||||
mapValue["n"] = i64tostr(nOrderPos);
|
||||
}
|
||||
|
||||
struct COutputEntry
|
||||
{
|
||||
CTxDestination destination;
|
||||
CAmount amount;
|
||||
int vout;
|
||||
};
|
||||
|
||||
/** A transaction with a merkle branch linking it to the block chain. */
|
||||
class CMerkleTx : public CTransaction
|
||||
{
|
||||
private:
|
||||
int GetDepthInMainChainINTERNAL(const CBlockIndex* &pindexRet) const;
|
||||
|
||||
public:
|
||||
uint256 hashBlock;
|
||||
std::vector<uint256> vMerkleBranch;
|
||||
int nIndex;
|
||||
|
||||
// memory only
|
||||
mutable bool fMerkleVerified;
|
||||
|
||||
|
||||
CMerkleTx()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
CMerkleTx(const CTransaction& txIn) : CTransaction(txIn)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
hashBlock = uint256();
|
||||
nIndex = -1;
|
||||
fMerkleVerified = false;
|
||||
}
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(*(CTransaction*)this);
|
||||
nVersion = this->nVersion;
|
||||
READWRITE(hashBlock);
|
||||
READWRITE(vMerkleBranch);
|
||||
READWRITE(nIndex);
|
||||
}
|
||||
|
||||
int SetMerkleBranch(const CBlock& block);
|
||||
|
||||
|
||||
/**
|
||||
* Return depth of transaction in blockchain:
|
||||
* -1 : not in blockchain, and not in memory pool (conflicted transaction)
|
||||
* 0 : in memory pool, waiting to be included in a block
|
||||
* >=1 : this many blocks deep in the main chain
|
||||
*/
|
||||
int GetDepthInMainChain(const CBlockIndex* &pindexRet) const;
|
||||
int GetDepthInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); }
|
||||
bool IsInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChainINTERNAL(pindexRet) > 0; }
|
||||
int GetBlocksToMaturity() const;
|
||||
bool AcceptToMemoryPool(bool fLimitFree=true, bool fRejectAbsurdFee=true);
|
||||
};
|
||||
|
||||
/**
|
||||
* A transaction with a bunch of additional info that only the owner cares about.
|
||||
* It includes any unrecorded transactions needed to link it back to the block chain.
|
||||
*/
|
||||
class CWalletTx : public CMerkleTx
|
||||
{
|
||||
private:
|
||||
const CWallet* pwallet;
|
||||
|
||||
public:
|
||||
mapValue_t mapValue;
|
||||
std::vector<std::pair<std::string, std::string> > vOrderForm;
|
||||
unsigned int fTimeReceivedIsTxTime;
|
||||
unsigned int nTimeReceived; //! time received by this node
|
||||
unsigned int nTimeSmart;
|
||||
char fFromMe;
|
||||
std::string strFromAccount;
|
||||
int64_t nOrderPos; //! position in ordered transaction list
|
||||
|
||||
// memory only
|
||||
mutable bool fDebitCached;
|
||||
mutable bool fCreditCached;
|
||||
mutable bool fImmatureCreditCached;
|
||||
mutable bool fAvailableCreditCached;
|
||||
mutable bool fWatchDebitCached;
|
||||
mutable bool fWatchCreditCached;
|
||||
mutable bool fImmatureWatchCreditCached;
|
||||
mutable bool fAvailableWatchCreditCached;
|
||||
mutable bool fChangeCached;
|
||||
mutable CAmount nDebitCached;
|
||||
mutable CAmount nCreditCached;
|
||||
mutable CAmount nImmatureCreditCached;
|
||||
mutable CAmount nAvailableCreditCached;
|
||||
mutable CAmount nWatchDebitCached;
|
||||
mutable CAmount nWatchCreditCached;
|
||||
mutable CAmount nImmatureWatchCreditCached;
|
||||
mutable CAmount nAvailableWatchCreditCached;
|
||||
mutable CAmount nChangeCached;
|
||||
|
||||
CWalletTx()
|
||||
{
|
||||
Init(NULL);
|
||||
}
|
||||
|
||||
CWalletTx(const CWallet* pwalletIn)
|
||||
{
|
||||
Init(pwalletIn);
|
||||
}
|
||||
|
||||
CWalletTx(const CWallet* pwalletIn, const CMerkleTx& txIn) : CMerkleTx(txIn)
|
||||
{
|
||||
Init(pwalletIn);
|
||||
}
|
||||
|
||||
CWalletTx(const CWallet* pwalletIn, const CTransaction& txIn) : CMerkleTx(txIn)
|
||||
{
|
||||
Init(pwalletIn);
|
||||
}
|
||||
|
||||
void Init(const CWallet* pwalletIn)
|
||||
{
|
||||
pwallet = pwalletIn;
|
||||
mapValue.clear();
|
||||
vOrderForm.clear();
|
||||
fTimeReceivedIsTxTime = false;
|
||||
nTimeReceived = 0;
|
||||
nTimeSmart = 0;
|
||||
fFromMe = false;
|
||||
strFromAccount.clear();
|
||||
fDebitCached = false;
|
||||
fCreditCached = false;
|
||||
fImmatureCreditCached = false;
|
||||
fAvailableCreditCached = false;
|
||||
fWatchDebitCached = false;
|
||||
fWatchCreditCached = false;
|
||||
fImmatureWatchCreditCached = false;
|
||||
fAvailableWatchCreditCached = false;
|
||||
fChangeCached = false;
|
||||
nDebitCached = 0;
|
||||
nCreditCached = 0;
|
||||
nImmatureCreditCached = 0;
|
||||
nAvailableCreditCached = 0;
|
||||
nWatchDebitCached = 0;
|
||||
nWatchCreditCached = 0;
|
||||
nAvailableWatchCreditCached = 0;
|
||||
nImmatureWatchCreditCached = 0;
|
||||
nChangeCached = 0;
|
||||
nOrderPos = -1;
|
||||
}
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
if (ser_action.ForRead())
|
||||
Init(NULL);
|
||||
char fSpent = false;
|
||||
|
||||
if (!ser_action.ForRead())
|
||||
{
|
||||
mapValue["fromaccount"] = strFromAccount;
|
||||
|
||||
WriteOrderPos(nOrderPos, mapValue);
|
||||
|
||||
if (nTimeSmart)
|
||||
mapValue["timesmart"] = strprintf("%u", nTimeSmart);
|
||||
}
|
||||
|
||||
READWRITE(*(CMerkleTx*)this);
|
||||
std::vector<CMerkleTx> vUnused; //! Used to be vtxPrev
|
||||
READWRITE(vUnused);
|
||||
READWRITE(mapValue);
|
||||
READWRITE(vOrderForm);
|
||||
READWRITE(fTimeReceivedIsTxTime);
|
||||
READWRITE(nTimeReceived);
|
||||
READWRITE(fFromMe);
|
||||
READWRITE(fSpent);
|
||||
|
||||
if (ser_action.ForRead())
|
||||
{
|
||||
strFromAccount = mapValue["fromaccount"];
|
||||
|
||||
ReadOrderPos(nOrderPos, mapValue);
|
||||
|
||||
nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(mapValue["timesmart"]) : 0;
|
||||
}
|
||||
|
||||
mapValue.erase("fromaccount");
|
||||
mapValue.erase("version");
|
||||
mapValue.erase("spent");
|
||||
mapValue.erase("n");
|
||||
mapValue.erase("timesmart");
|
||||
}
|
||||
|
||||
//! make sure balances are recalculated
|
||||
void MarkDirty()
|
||||
{
|
||||
fCreditCached = false;
|
||||
fAvailableCreditCached = false;
|
||||
fWatchDebitCached = false;
|
||||
fWatchCreditCached = false;
|
||||
fAvailableWatchCreditCached = false;
|
||||
fImmatureWatchCreditCached = false;
|
||||
fDebitCached = false;
|
||||
fChangeCached = false;
|
||||
}
|
||||
|
||||
void BindWallet(CWallet *pwalletIn)
|
||||
{
|
||||
pwallet = pwalletIn;
|
||||
MarkDirty();
|
||||
}
|
||||
|
||||
//! filter decides which addresses will count towards the debit
|
||||
CAmount GetDebit(const isminefilter& filter) const;
|
||||
CAmount GetCredit(const isminefilter& filter) const;
|
||||
CAmount GetImmatureCredit(bool fUseCache=true) const;
|
||||
CAmount GetAvailableCredit(bool fUseCache=true) const;
|
||||
CAmount GetImmatureWatchOnlyCredit(const bool& fUseCache=true) const;
|
||||
CAmount GetAvailableWatchOnlyCredit(const bool& fUseCache=true) const;
|
||||
CAmount GetChange() const;
|
||||
|
||||
void GetAmounts(std::list<COutputEntry>& listReceived,
|
||||
std::list<COutputEntry>& listSent, CAmount& nFee, std::string& strSentAccount, const isminefilter& filter) const;
|
||||
|
||||
void GetAccountAmounts(const std::string& strAccount, CAmount& nReceived,
|
||||
CAmount& nSent, CAmount& nFee, const isminefilter& filter) const;
|
||||
|
||||
bool IsFromMe(const isminefilter& filter) const
|
||||
{
|
||||
return (GetDebit(filter) > 0);
|
||||
}
|
||||
|
||||
bool IsTrusted() const;
|
||||
|
||||
bool WriteToDisk(CWalletDB *pwalletdb);
|
||||
|
||||
int64_t GetTxTime() const;
|
||||
int GetRequestCount() const;
|
||||
|
||||
void RelayWalletTransaction();
|
||||
|
||||
std::set<uint256> GetConflicts() const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class COutput
|
||||
{
|
||||
public:
|
||||
const CWalletTx *tx;
|
||||
int i;
|
||||
int nDepth;
|
||||
bool fSpendable;
|
||||
|
||||
COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn)
|
||||
{
|
||||
tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn;
|
||||
}
|
||||
|
||||
std::string ToString() const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/** Private key that includes an expiration date in case it never gets used. */
|
||||
class CWalletKey
|
||||
{
|
||||
public:
|
||||
CPrivKey vchPrivKey;
|
||||
int64_t nTimeCreated;
|
||||
int64_t nTimeExpires;
|
||||
std::string strComment;
|
||||
//! todo: add something to note what created it (user, getnewaddress, change)
|
||||
//! maybe should have a map<string, string> property map
|
||||
|
||||
CWalletKey(int64_t nExpires=0);
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
if (!(nType & SER_GETHASH))
|
||||
READWRITE(nVersion);
|
||||
READWRITE(vchPrivKey);
|
||||
READWRITE(nTimeCreated);
|
||||
READWRITE(nTimeExpires);
|
||||
READWRITE(LIMITED_STRING(strComment, 65536));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,
|
||||
* and provides the ability to create new transactions.
|
||||
@ -464,508 +787,6 @@ public:
|
||||
};
|
||||
|
||||
|
||||
typedef std::map<std::string, std::string> mapValue_t;
|
||||
|
||||
|
||||
static void ReadOrderPos(int64_t& nOrderPos, mapValue_t& mapValue)
|
||||
{
|
||||
if (!mapValue.count("n"))
|
||||
{
|
||||
nOrderPos = -1; // TODO: calculate elsewhere
|
||||
return;
|
||||
}
|
||||
nOrderPos = atoi64(mapValue["n"].c_str());
|
||||
}
|
||||
|
||||
|
||||
static void WriteOrderPos(const int64_t& nOrderPos, mapValue_t& mapValue)
|
||||
{
|
||||
if (nOrderPos == -1)
|
||||
return;
|
||||
mapValue["n"] = i64tostr(nOrderPos);
|
||||
}
|
||||
|
||||
struct COutputEntry
|
||||
{
|
||||
CTxDestination destination;
|
||||
CAmount amount;
|
||||
int vout;
|
||||
};
|
||||
|
||||
/** A transaction with a merkle branch linking it to the block chain. */
|
||||
class CMerkleTx : public CTransaction
|
||||
{
|
||||
private:
|
||||
int GetDepthInMainChainINTERNAL(const CBlockIndex* &pindexRet) const;
|
||||
|
||||
public:
|
||||
uint256 hashBlock;
|
||||
std::vector<uint256> vMerkleBranch;
|
||||
int nIndex;
|
||||
|
||||
// memory only
|
||||
mutable bool fMerkleVerified;
|
||||
|
||||
|
||||
CMerkleTx()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
CMerkleTx(const CTransaction& txIn) : CTransaction(txIn)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
hashBlock = uint256();
|
||||
nIndex = -1;
|
||||
fMerkleVerified = false;
|
||||
}
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(*(CTransaction*)this);
|
||||
nVersion = this->nVersion;
|
||||
READWRITE(hashBlock);
|
||||
READWRITE(vMerkleBranch);
|
||||
READWRITE(nIndex);
|
||||
}
|
||||
|
||||
int SetMerkleBranch(const CBlock& block);
|
||||
|
||||
|
||||
/**
|
||||
* Return depth of transaction in blockchain:
|
||||
* -1 : not in blockchain, and not in memory pool (conflicted transaction)
|
||||
* 0 : in memory pool, waiting to be included in a block
|
||||
* >=1 : this many blocks deep in the main chain
|
||||
*/
|
||||
int GetDepthInMainChain(const CBlockIndex* &pindexRet) const;
|
||||
int GetDepthInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); }
|
||||
bool IsInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChainINTERNAL(pindexRet) > 0; }
|
||||
int GetBlocksToMaturity() const;
|
||||
bool AcceptToMemoryPool(bool fLimitFree=true, bool fRejectAbsurdFee=true);
|
||||
};
|
||||
|
||||
/**
|
||||
* A transaction with a bunch of additional info that only the owner cares about.
|
||||
* It includes any unrecorded transactions needed to link it back to the block chain.
|
||||
*/
|
||||
class CWalletTx : public CMerkleTx
|
||||
{
|
||||
private:
|
||||
const CWallet* pwallet;
|
||||
|
||||
public:
|
||||
mapValue_t mapValue;
|
||||
std::vector<std::pair<std::string, std::string> > vOrderForm;
|
||||
unsigned int fTimeReceivedIsTxTime;
|
||||
unsigned int nTimeReceived; //! time received by this node
|
||||
unsigned int nTimeSmart;
|
||||
char fFromMe;
|
||||
std::string strFromAccount;
|
||||
int64_t nOrderPos; //! position in ordered transaction list
|
||||
|
||||
// memory only
|
||||
mutable bool fDebitCached;
|
||||
mutable bool fCreditCached;
|
||||
mutable bool fImmatureCreditCached;
|
||||
mutable bool fAvailableCreditCached;
|
||||
mutable bool fWatchDebitCached;
|
||||
mutable bool fWatchCreditCached;
|
||||
mutable bool fImmatureWatchCreditCached;
|
||||
mutable bool fAvailableWatchCreditCached;
|
||||
mutable bool fChangeCached;
|
||||
mutable CAmount nDebitCached;
|
||||
mutable CAmount nCreditCached;
|
||||
mutable CAmount nImmatureCreditCached;
|
||||
mutable CAmount nAvailableCreditCached;
|
||||
mutable CAmount nWatchDebitCached;
|
||||
mutable CAmount nWatchCreditCached;
|
||||
mutable CAmount nImmatureWatchCreditCached;
|
||||
mutable CAmount nAvailableWatchCreditCached;
|
||||
mutable CAmount nChangeCached;
|
||||
|
||||
CWalletTx()
|
||||
{
|
||||
Init(NULL);
|
||||
}
|
||||
|
||||
CWalletTx(const CWallet* pwalletIn)
|
||||
{
|
||||
Init(pwalletIn);
|
||||
}
|
||||
|
||||
CWalletTx(const CWallet* pwalletIn, const CMerkleTx& txIn) : CMerkleTx(txIn)
|
||||
{
|
||||
Init(pwalletIn);
|
||||
}
|
||||
|
||||
CWalletTx(const CWallet* pwalletIn, const CTransaction& txIn) : CMerkleTx(txIn)
|
||||
{
|
||||
Init(pwalletIn);
|
||||
}
|
||||
|
||||
void Init(const CWallet* pwalletIn)
|
||||
{
|
||||
pwallet = pwalletIn;
|
||||
mapValue.clear();
|
||||
vOrderForm.clear();
|
||||
fTimeReceivedIsTxTime = false;
|
||||
nTimeReceived = 0;
|
||||
nTimeSmart = 0;
|
||||
fFromMe = false;
|
||||
strFromAccount.clear();
|
||||
fDebitCached = false;
|
||||
fCreditCached = false;
|
||||
fImmatureCreditCached = false;
|
||||
fAvailableCreditCached = false;
|
||||
fWatchDebitCached = false;
|
||||
fWatchCreditCached = false;
|
||||
fImmatureWatchCreditCached = false;
|
||||
fAvailableWatchCreditCached = false;
|
||||
fChangeCached = false;
|
||||
nDebitCached = 0;
|
||||
nCreditCached = 0;
|
||||
nImmatureCreditCached = 0;
|
||||
nAvailableCreditCached = 0;
|
||||
nWatchDebitCached = 0;
|
||||
nWatchCreditCached = 0;
|
||||
nAvailableWatchCreditCached = 0;
|
||||
nImmatureWatchCreditCached = 0;
|
||||
nChangeCached = 0;
|
||||
nOrderPos = -1;
|
||||
}
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
if (ser_action.ForRead())
|
||||
Init(NULL);
|
||||
char fSpent = false;
|
||||
|
||||
if (!ser_action.ForRead())
|
||||
{
|
||||
mapValue["fromaccount"] = strFromAccount;
|
||||
|
||||
WriteOrderPos(nOrderPos, mapValue);
|
||||
|
||||
if (nTimeSmart)
|
||||
mapValue["timesmart"] = strprintf("%u", nTimeSmart);
|
||||
}
|
||||
|
||||
READWRITE(*(CMerkleTx*)this);
|
||||
std::vector<CMerkleTx> vUnused; //! Used to be vtxPrev
|
||||
READWRITE(vUnused);
|
||||
READWRITE(mapValue);
|
||||
READWRITE(vOrderForm);
|
||||
READWRITE(fTimeReceivedIsTxTime);
|
||||
READWRITE(nTimeReceived);
|
||||
READWRITE(fFromMe);
|
||||
READWRITE(fSpent);
|
||||
|
||||
if (ser_action.ForRead())
|
||||
{
|
||||
strFromAccount = mapValue["fromaccount"];
|
||||
|
||||
ReadOrderPos(nOrderPos, mapValue);
|
||||
|
||||
nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(mapValue["timesmart"]) : 0;
|
||||
}
|
||||
|
||||
mapValue.erase("fromaccount");
|
||||
mapValue.erase("version");
|
||||
mapValue.erase("spent");
|
||||
mapValue.erase("n");
|
||||
mapValue.erase("timesmart");
|
||||
}
|
||||
|
||||
//! make sure balances are recalculated
|
||||
void MarkDirty()
|
||||
{
|
||||
fCreditCached = false;
|
||||
fAvailableCreditCached = false;
|
||||
fWatchDebitCached = false;
|
||||
fWatchCreditCached = false;
|
||||
fAvailableWatchCreditCached = false;
|
||||
fImmatureWatchCreditCached = false;
|
||||
fDebitCached = false;
|
||||
fChangeCached = false;
|
||||
}
|
||||
|
||||
void BindWallet(CWallet *pwalletIn)
|
||||
{
|
||||
pwallet = pwalletIn;
|
||||
MarkDirty();
|
||||
}
|
||||
|
||||
//! filter decides which addresses will count towards the debit
|
||||
CAmount GetDebit(const isminefilter& filter) const
|
||||
{
|
||||
if (vin.empty())
|
||||
return 0;
|
||||
|
||||
CAmount debit = 0;
|
||||
if(filter & ISMINE_SPENDABLE)
|
||||
{
|
||||
if (fDebitCached)
|
||||
debit += nDebitCached;
|
||||
else
|
||||
{
|
||||
nDebitCached = pwallet->GetDebit(*this, ISMINE_SPENDABLE);
|
||||
fDebitCached = true;
|
||||
debit += nDebitCached;
|
||||
}
|
||||
}
|
||||
if(filter & ISMINE_WATCH_ONLY)
|
||||
{
|
||||
if(fWatchDebitCached)
|
||||
debit += nWatchDebitCached;
|
||||
else
|
||||
{
|
||||
nWatchDebitCached = pwallet->GetDebit(*this, ISMINE_WATCH_ONLY);
|
||||
fWatchDebitCached = true;
|
||||
debit += nWatchDebitCached;
|
||||
}
|
||||
}
|
||||
return debit;
|
||||
}
|
||||
|
||||
CAmount GetCredit(const isminefilter& filter) const
|
||||
{
|
||||
// Must wait until coinbase is safely deep enough in the chain before valuing it
|
||||
if (IsCoinBase() && GetBlocksToMaturity() > 0)
|
||||
return 0;
|
||||
|
||||
int64_t credit = 0;
|
||||
if (filter & ISMINE_SPENDABLE)
|
||||
{
|
||||
// GetBalance can assume transactions in mapWallet won't change
|
||||
if (fCreditCached)
|
||||
credit += nCreditCached;
|
||||
else
|
||||
{
|
||||
nCreditCached = pwallet->GetCredit(*this, ISMINE_SPENDABLE);
|
||||
fCreditCached = true;
|
||||
credit += nCreditCached;
|
||||
}
|
||||
}
|
||||
if (filter & ISMINE_WATCH_ONLY)
|
||||
{
|
||||
if (fWatchCreditCached)
|
||||
credit += nWatchCreditCached;
|
||||
else
|
||||
{
|
||||
nWatchCreditCached = pwallet->GetCredit(*this, ISMINE_WATCH_ONLY);
|
||||
fWatchCreditCached = true;
|
||||
credit += nWatchCreditCached;
|
||||
}
|
||||
}
|
||||
return credit;
|
||||
}
|
||||
|
||||
CAmount GetImmatureCredit(bool fUseCache=true) const
|
||||
{
|
||||
if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
|
||||
{
|
||||
if (fUseCache && fImmatureCreditCached)
|
||||
return nImmatureCreditCached;
|
||||
nImmatureCreditCached = pwallet->GetCredit(*this, ISMINE_SPENDABLE);
|
||||
fImmatureCreditCached = true;
|
||||
return nImmatureCreditCached;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CAmount GetAvailableCredit(bool fUseCache=true) const
|
||||
{
|
||||
if (pwallet == 0)
|
||||
return 0;
|
||||
|
||||
// Must wait until coinbase is safely deep enough in the chain before valuing it
|
||||
if (IsCoinBase() && GetBlocksToMaturity() > 0)
|
||||
return 0;
|
||||
|
||||
if (fUseCache && fAvailableCreditCached)
|
||||
return nAvailableCreditCached;
|
||||
|
||||
CAmount nCredit = 0;
|
||||
uint256 hashTx = GetHash();
|
||||
for (unsigned int i = 0; i < vout.size(); i++)
|
||||
{
|
||||
if (!pwallet->IsSpent(hashTx, i))
|
||||
{
|
||||
const CTxOut &txout = vout[i];
|
||||
nCredit += pwallet->GetCredit(txout, ISMINE_SPENDABLE);
|
||||
if (!MoneyRange(nCredit))
|
||||
throw std::runtime_error("CWalletTx::GetAvailableCredit(): value out of range");
|
||||
}
|
||||
}
|
||||
|
||||
nAvailableCreditCached = nCredit;
|
||||
fAvailableCreditCached = true;
|
||||
return nCredit;
|
||||
}
|
||||
|
||||
CAmount GetImmatureWatchOnlyCredit(const bool& fUseCache=true) const
|
||||
{
|
||||
if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
|
||||
{
|
||||
if (fUseCache && fImmatureWatchCreditCached)
|
||||
return nImmatureWatchCreditCached;
|
||||
nImmatureWatchCreditCached = pwallet->GetCredit(*this, ISMINE_WATCH_ONLY);
|
||||
fImmatureWatchCreditCached = true;
|
||||
return nImmatureWatchCreditCached;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CAmount GetAvailableWatchOnlyCredit(const bool& fUseCache=true) const
|
||||
{
|
||||
if (pwallet == 0)
|
||||
return 0;
|
||||
|
||||
// Must wait until coinbase is safely deep enough in the chain before valuing it
|
||||
if (IsCoinBase() && GetBlocksToMaturity() > 0)
|
||||
return 0;
|
||||
|
||||
if (fUseCache && fAvailableWatchCreditCached)
|
||||
return nAvailableWatchCreditCached;
|
||||
|
||||
CAmount nCredit = 0;
|
||||
for (unsigned int i = 0; i < vout.size(); i++)
|
||||
{
|
||||
if (!pwallet->IsSpent(GetHash(), i))
|
||||
{
|
||||
const CTxOut &txout = vout[i];
|
||||
nCredit += pwallet->GetCredit(txout, ISMINE_WATCH_ONLY);
|
||||
if (!MoneyRange(nCredit))
|
||||
throw std::runtime_error("CWalletTx::GetAvailableCredit(): value out of range");
|
||||
}
|
||||
}
|
||||
|
||||
nAvailableWatchCreditCached = nCredit;
|
||||
fAvailableWatchCreditCached = true;
|
||||
return nCredit;
|
||||
}
|
||||
|
||||
CAmount GetChange() const
|
||||
{
|
||||
if (fChangeCached)
|
||||
return nChangeCached;
|
||||
nChangeCached = pwallet->GetChange(*this);
|
||||
fChangeCached = true;
|
||||
return nChangeCached;
|
||||
}
|
||||
|
||||
void GetAmounts(std::list<COutputEntry>& listReceived,
|
||||
std::list<COutputEntry>& listSent, CAmount& nFee, std::string& strSentAccount, const isminefilter& filter) const;
|
||||
|
||||
void GetAccountAmounts(const std::string& strAccount, CAmount& nReceived,
|
||||
CAmount& nSent, CAmount& nFee, const isminefilter& filter) const;
|
||||
|
||||
bool IsFromMe(const isminefilter& filter) const
|
||||
{
|
||||
return (GetDebit(filter) > 0);
|
||||
}
|
||||
|
||||
bool IsTrusted() const
|
||||
{
|
||||
// Quick answer in most cases
|
||||
if (!IsFinalTx(*this))
|
||||
return false;
|
||||
int nDepth = GetDepthInMainChain();
|
||||
if (nDepth >= 1)
|
||||
return true;
|
||||
if (nDepth < 0)
|
||||
return false;
|
||||
if (!bSpendZeroConfChange || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit
|
||||
return false;
|
||||
|
||||
// Trusted if all inputs are from us and are in the mempool:
|
||||
BOOST_FOREACH(const CTxIn& txin, vin)
|
||||
{
|
||||
// Transactions not sent by us: not trusted
|
||||
const CWalletTx* parent = pwallet->GetWalletTx(txin.prevout.hash);
|
||||
if (parent == NULL)
|
||||
return false;
|
||||
const CTxOut& parentOut = parent->vout[txin.prevout.n];
|
||||
if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteToDisk(CWalletDB *pwalletdb);
|
||||
|
||||
int64_t GetTxTime() const;
|
||||
int GetRequestCount() const;
|
||||
|
||||
void RelayWalletTransaction();
|
||||
|
||||
std::set<uint256> GetConflicts() const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class COutput
|
||||
{
|
||||
public:
|
||||
const CWalletTx *tx;
|
||||
int i;
|
||||
int nDepth;
|
||||
bool fSpendable;
|
||||
|
||||
COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn)
|
||||
{
|
||||
tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn;
|
||||
}
|
||||
|
||||
std::string ToString() const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/** Private key that includes an expiration date in case it never gets used. */
|
||||
class CWalletKey
|
||||
{
|
||||
public:
|
||||
CPrivKey vchPrivKey;
|
||||
int64_t nTimeCreated;
|
||||
int64_t nTimeExpires;
|
||||
std::string strComment;
|
||||
//! todo: add something to note what created it (user, getnewaddress, change)
|
||||
//! maybe should have a map<string, string> property map
|
||||
|
||||
CWalletKey(int64_t nExpires=0);
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
if (!(nType & SER_GETHASH))
|
||||
READWRITE(nVersion);
|
||||
READWRITE(vchPrivKey);
|
||||
READWRITE(nTimeCreated);
|
||||
READWRITE(nTimeExpires);
|
||||
READWRITE(LIMITED_STRING(strComment, 65536));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Account information.
|
||||
* Stored in wallet with key "acc"+string account name.
|
||||
|
Loading…
Reference in New Issue
Block a user