]> Git Repo - VerusCoin.git/blame - src/coins.cpp
Merge pull request #4986
[VerusCoin.git] / src / coins.cpp
CommitLineData
a0fa20a1
PW
1// Copyright (c) 2012-2013 The Bitcoin developers
2// Distributed under the MIT/X11 software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#include "coins.h"
6
bc42503f
PW
7#include "random.h"
8
a0fa20a1
PW
9#include <assert.h>
10
11// calculate number of bytes for the bitmask, and its number of non-zero bytes
12// each bit in the bitmask represents the availability of one output, but the
13// availabilities of the first two outputs are encoded separately
14void CCoins::CalcMaskSize(unsigned int &nBytes, unsigned int &nNonzeroBytes) const {
15 unsigned int nLastUsedByte = 0;
16 for (unsigned int b = 0; 2+b*8 < vout.size(); b++) {
17 bool fZero = true;
18 for (unsigned int i = 0; i < 8 && 2+b*8+i < vout.size(); i++) {
19 if (!vout[2+b*8+i].IsNull()) {
20 fZero = false;
21 continue;
22 }
23 }
24 if (!fZero) {
25 nLastUsedByte = b + 1;
26 nNonzeroBytes++;
27 }
28 }
29 nBytes += nLastUsedByte;
30}
31
32bool CCoins::Spend(const COutPoint &out, CTxInUndo &undo) {
33 if (out.n >= vout.size())
34 return false;
35 if (vout[out.n].IsNull())
36 return false;
37 undo = CTxInUndo(vout[out.n]);
38 vout[out.n].SetNull();
39 Cleanup();
40 if (vout.size() == 0) {
41 undo.nHeight = nHeight;
42 undo.fCoinBase = fCoinBase;
43 undo.nVersion = this->nVersion;
44 }
45 return true;
46}
47
48bool CCoins::Spend(int nPos) {
49 CTxInUndo undo;
50 COutPoint out(0, nPos);
51 return Spend(out, undo);
52}
53
54
a3dc587a 55bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) const { return false; }
a0fa20a1 56bool CCoinsView::SetCoins(const uint256 &txid, const CCoins &coins) { return false; }
a3dc587a
DK
57bool CCoinsView::HaveCoins(const uint256 &txid) const { return false; }
58uint256 CCoinsView::GetBestBlock() const { return uint256(0); }
a0fa20a1 59bool CCoinsView::SetBestBlock(const uint256 &hashBlock) { return false; }
b0875eb3 60bool CCoinsView::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return false; }
a3dc587a 61bool CCoinsView::GetStats(CCoinsStats &stats) const { return false; }
a0fa20a1
PW
62
63
64CCoinsViewBacked::CCoinsViewBacked(CCoinsView &viewIn) : base(&viewIn) { }
a3dc587a 65bool CCoinsViewBacked::GetCoins(const uint256 &txid, CCoins &coins) const { return base->GetCoins(txid, coins); }
a0fa20a1 66bool CCoinsViewBacked::SetCoins(const uint256 &txid, const CCoins &coins) { return base->SetCoins(txid, coins); }
a3dc587a
DK
67bool CCoinsViewBacked::HaveCoins(const uint256 &txid) const { return base->HaveCoins(txid); }
68uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); }
a0fa20a1
PW
69bool CCoinsViewBacked::SetBestBlock(const uint256 &hashBlock) { return base->SetBestBlock(hashBlock); }
70void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
b0875eb3 71bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); }
a3dc587a 72bool CCoinsViewBacked::GetStats(CCoinsStats &stats) const { return base->GetStats(stats); }
a0fa20a1 73
bc42503f
PW
74CCoinsKeyHasher::CCoinsKeyHasher() : salt(GetRandHash()) {}
75
a0fa20a1
PW
76CCoinsViewCache::CCoinsViewCache(CCoinsView &baseIn, bool fDummy) : CCoinsViewBacked(baseIn), hashBlock(0) { }
77
a3dc587a 78bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) const {
a0fa20a1
PW
79 if (cacheCoins.count(txid)) {
80 coins = cacheCoins[txid];
81 return true;
82 }
83 if (base->GetCoins(txid, coins)) {
84 cacheCoins[txid] = coins;
85 return true;
86 }
87 return false;
88}
89
dd638dd7 90CCoinsMap::iterator CCoinsViewCache::FetchCoins(const uint256 &txid) {
bc42503f
PW
91 CCoinsMap::iterator it = cacheCoins.find(txid);
92 if (it != cacheCoins.end())
a0fa20a1
PW
93 return it;
94 CCoins tmp;
95 if (!base->GetCoins(txid,tmp))
96 return cacheCoins.end();
dd638dd7 97 CCoinsMap::iterator ret = cacheCoins.insert(it, std::make_pair(txid, CCoins()));
a0fa20a1
PW
98 tmp.swap(ret->second);
99 return ret;
100}
101
a3dc587a
DK
102CCoinsMap::const_iterator CCoinsViewCache::FetchCoins(const uint256 &txid) const {
103 /* Avoid redundant implementation with the const-cast. */
104 return const_cast<CCoinsViewCache*>(this)->FetchCoins(txid);
105}
106
a0fa20a1 107CCoins &CCoinsViewCache::GetCoins(const uint256 &txid) {
dd638dd7 108 CCoinsMap::iterator it = FetchCoins(txid);
a0fa20a1
PW
109 assert(it != cacheCoins.end());
110 return it->second;
111}
112
629d75fa
PW
113const CCoins* CCoinsViewCache::AccessCoins(const uint256 &txid) const {
114 CCoinsMap::const_iterator it = FetchCoins(txid);
115 if (it == cacheCoins.end()) {
116 return NULL;
117 } else {
118 return &it->second;
119 }
a3dc587a
DK
120}
121
a0fa20a1
PW
122bool CCoinsViewCache::SetCoins(const uint256 &txid, const CCoins &coins) {
123 cacheCoins[txid] = coins;
124 return true;
125}
126
a3dc587a
DK
127bool CCoinsViewCache::HaveCoins(const uint256 &txid) const {
128 CCoinsMap::const_iterator it = FetchCoins(txid);
d4d3fbd8
PW
129 // We're using vtx.empty() instead of IsPruned here for performance reasons,
130 // as we only care about the case where an transaction was replaced entirely
131 // in a reorganization (which wipes vout entirely, as opposed to spending
132 // which just cleans individual outputs).
133 return (it != cacheCoins.end() && !it->second.vout.empty());
a0fa20a1
PW
134}
135
a3dc587a 136uint256 CCoinsViewCache::GetBestBlock() const {
a0fa20a1
PW
137 if (hashBlock == uint256(0))
138 hashBlock = base->GetBestBlock();
139 return hashBlock;
140}
141
142bool CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) {
143 hashBlock = hashBlockIn;
144 return true;
145}
146
b0875eb3
PW
147bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn) {
148 for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
149 cacheCoins[it->first].swap(it->second);
150 CCoinsMap::iterator itOld = it++;
151 mapCoins.erase(itOld);
152 }
a0fa20a1
PW
153 hashBlock = hashBlockIn;
154 return true;
155}
156
157bool CCoinsViewCache::Flush() {
158 bool fOk = base->BatchWrite(cacheCoins, hashBlock);
b0875eb3 159 cacheCoins.clear();
a0fa20a1
PW
160 return fOk;
161}
162
a3dc587a 163unsigned int CCoinsViewCache::GetCacheSize() const {
a0fa20a1
PW
164 return cacheCoins.size();
165}
166
a3dc587a 167const CTxOut &CCoinsViewCache::GetOutputFor(const CTxIn& input) const
a0fa20a1 168{
629d75fa
PW
169 const CCoins* coins = AccessCoins(input.prevout.hash);
170 assert(coins && coins->IsAvailable(input.prevout.n));
171 return coins->vout[input.prevout.n];
a0fa20a1
PW
172}
173
a3dc587a 174int64_t CCoinsViewCache::GetValueIn(const CTransaction& tx) const
a0fa20a1
PW
175{
176 if (tx.IsCoinBase())
177 return 0;
178
179 int64_t nResult = 0;
180 for (unsigned int i = 0; i < tx.vin.size(); i++)
181 nResult += GetOutputFor(tx.vin[i]).nValue;
182
183 return nResult;
184}
185
a3dc587a 186bool CCoinsViewCache::HaveInputs(const CTransaction& tx) const
a0fa20a1
PW
187{
188 if (!tx.IsCoinBase()) {
a0fa20a1
PW
189 for (unsigned int i = 0; i < tx.vin.size(); i++) {
190 const COutPoint &prevout = tx.vin[i].prevout;
629d75fa
PW
191 const CCoins* coins = AccessCoins(prevout.hash);
192 if (!coins || !coins->IsAvailable(prevout.n)) {
a0fa20a1 193 return false;
629d75fa 194 }
a0fa20a1
PW
195 }
196 }
197 return true;
198}
4d707d51 199
a3dc587a 200double CCoinsViewCache::GetPriority(const CTransaction &tx, int nHeight) const
4d707d51
GA
201{
202 if (tx.IsCoinBase())
203 return 0.0;
204 double dResult = 0.0;
205 BOOST_FOREACH(const CTxIn& txin, tx.vin)
206 {
629d75fa
PW
207 const CCoins* coins = AccessCoins(txin.prevout.hash);
208 assert(coins);
209 if (!coins->IsAvailable(txin.prevout.n)) continue;
210 if (coins->nHeight < nHeight) {
211 dResult += coins->vout[txin.prevout.n].nValue * (nHeight-coins->nHeight);
4d707d51
GA
212 }
213 }
214 return tx.ComputePriority(dResult);
215}
This page took 0.11484 seconds and 4 git commands to generate.