]>
Commit | Line | Data |
---|---|---|
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 | |
14 | void 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 | ||
32 | bool 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 | ||
48 | bool CCoins::Spend(int nPos) { | |
49 | CTxInUndo undo; | |
50 | COutPoint out(0, nPos); | |
51 | return Spend(out, undo); | |
52 | } | |
53 | ||
54 | ||
a3dc587a | 55 | bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) const { return false; } |
a0fa20a1 | 56 | bool CCoinsView::SetCoins(const uint256 &txid, const CCoins &coins) { return false; } |
a3dc587a DK |
57 | bool CCoinsView::HaveCoins(const uint256 &txid) const { return false; } |
58 | uint256 CCoinsView::GetBestBlock() const { return uint256(0); } | |
a0fa20a1 | 59 | bool CCoinsView::SetBestBlock(const uint256 &hashBlock) { return false; } |
b0875eb3 | 60 | bool CCoinsView::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return false; } |
a3dc587a | 61 | bool CCoinsView::GetStats(CCoinsStats &stats) const { return false; } |
a0fa20a1 PW |
62 | |
63 | ||
64 | CCoinsViewBacked::CCoinsViewBacked(CCoinsView &viewIn) : base(&viewIn) { } | |
a3dc587a | 65 | bool CCoinsViewBacked::GetCoins(const uint256 &txid, CCoins &coins) const { return base->GetCoins(txid, coins); } |
a0fa20a1 | 66 | bool CCoinsViewBacked::SetCoins(const uint256 &txid, const CCoins &coins) { return base->SetCoins(txid, coins); } |
a3dc587a DK |
67 | bool CCoinsViewBacked::HaveCoins(const uint256 &txid) const { return base->HaveCoins(txid); } |
68 | uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); } | |
a0fa20a1 PW |
69 | bool CCoinsViewBacked::SetBestBlock(const uint256 &hashBlock) { return base->SetBestBlock(hashBlock); } |
70 | void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; } | |
b0875eb3 | 71 | bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); } |
a3dc587a | 72 | bool CCoinsViewBacked::GetStats(CCoinsStats &stats) const { return base->GetStats(stats); } |
a0fa20a1 | 73 | |
bc42503f PW |
74 | CCoinsKeyHasher::CCoinsKeyHasher() : salt(GetRandHash()) {} |
75 | ||
a0fa20a1 PW |
76 | CCoinsViewCache::CCoinsViewCache(CCoinsView &baseIn, bool fDummy) : CCoinsViewBacked(baseIn), hashBlock(0) { } |
77 | ||
a3dc587a | 78 | bool 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 | 90 | CCoinsMap::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 |
102 | CCoinsMap::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 | 107 | CCoins &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 |
113 | const 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 |
122 | bool CCoinsViewCache::SetCoins(const uint256 &txid, const CCoins &coins) { |
123 | cacheCoins[txid] = coins; | |
124 | return true; | |
125 | } | |
126 | ||
a3dc587a DK |
127 | bool 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 | 136 | uint256 CCoinsViewCache::GetBestBlock() const { |
a0fa20a1 PW |
137 | if (hashBlock == uint256(0)) |
138 | hashBlock = base->GetBestBlock(); | |
139 | return hashBlock; | |
140 | } | |
141 | ||
142 | bool CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) { | |
143 | hashBlock = hashBlockIn; | |
144 | return true; | |
145 | } | |
146 | ||
b0875eb3 PW |
147 | bool 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 | ||
157 | bool CCoinsViewCache::Flush() { | |
158 | bool fOk = base->BatchWrite(cacheCoins, hashBlock); | |
b0875eb3 | 159 | cacheCoins.clear(); |
a0fa20a1 PW |
160 | return fOk; |
161 | } | |
162 | ||
a3dc587a | 163 | unsigned int CCoinsViewCache::GetCacheSize() const { |
a0fa20a1 PW |
164 | return cacheCoins.size(); |
165 | } | |
166 | ||
a3dc587a | 167 | const 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 | 174 | int64_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 | 186 | bool 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 | 200 | double 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 | } |