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.
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
++) {
18 for (unsigned int i
= 0; i
< 8 && 2+b
*8+i
< vout
.size(); i
++) {
19 if (!vout
[2+b
*8+i
].IsNull()) {
25 nLastUsedByte
= b
+ 1;
29 nBytes
+= nLastUsedByte
;
32 bool CCoins::Spend(const COutPoint
&out
, CTxInUndo
&undo
) {
33 if (out
.n
>= vout
.size())
35 if (vout
[out
.n
].IsNull())
37 undo
= CTxInUndo(vout
[out
.n
]);
38 vout
[out
.n
].SetNull();
40 if (vout
.size() == 0) {
41 undo
.nHeight
= nHeight
;
42 undo
.fCoinBase
= fCoinBase
;
43 undo
.nVersion
= this->nVersion
;
48 bool CCoins::Spend(int nPos
) {
50 COutPoint
out(0, nPos
);
51 return Spend(out
, undo
);
55 bool CCoinsView::GetCoins(const uint256
&txid
, CCoins
&coins
) { return false; }
56 bool CCoinsView::SetCoins(const uint256
&txid
, const CCoins
&coins
) { return false; }
57 bool CCoinsView::HaveCoins(const uint256
&txid
) { return false; }
58 uint256
CCoinsView::GetBestBlock() { return uint256(0); }
59 bool CCoinsView::SetBestBlock(const uint256
&hashBlock
) { return false; }
60 bool CCoinsView::BatchWrite(const CCoinsMap
&mapCoins
, const uint256
&hashBlock
) { return false; }
61 bool CCoinsView::GetStats(CCoinsStats
&stats
) { return false; }
64 CCoinsViewBacked::CCoinsViewBacked(CCoinsView
&viewIn
) : base(&viewIn
) { }
65 bool CCoinsViewBacked::GetCoins(const uint256
&txid
, CCoins
&coins
) { return base
->GetCoins(txid
, coins
); }
66 bool CCoinsViewBacked::SetCoins(const uint256
&txid
, const CCoins
&coins
) { return base
->SetCoins(txid
, coins
); }
67 bool CCoinsViewBacked::HaveCoins(const uint256
&txid
) { return base
->HaveCoins(txid
); }
68 uint256
CCoinsViewBacked::GetBestBlock() { return base
->GetBestBlock(); }
69 bool CCoinsViewBacked::SetBestBlock(const uint256
&hashBlock
) { return base
->SetBestBlock(hashBlock
); }
70 void CCoinsViewBacked::SetBackend(CCoinsView
&viewIn
) { base
= &viewIn
; }
71 bool CCoinsViewBacked::BatchWrite(const CCoinsMap
&mapCoins
, const uint256
&hashBlock
) { return base
->BatchWrite(mapCoins
, hashBlock
); }
72 bool CCoinsViewBacked::GetStats(CCoinsStats
&stats
) { return base
->GetStats(stats
); }
74 CCoinsKeyHasher::CCoinsKeyHasher() : salt(GetRandHash()) {}
76 CCoinsViewCache::CCoinsViewCache(CCoinsView
&baseIn
, bool fDummy
) : CCoinsViewBacked(baseIn
), hashBlock(0) { }
78 bool CCoinsViewCache::GetCoins(const uint256
&txid
, CCoins
&coins
) {
79 if (cacheCoins
.count(txid
)) {
80 coins
= cacheCoins
[txid
];
83 if (base
->GetCoins(txid
, coins
)) {
84 cacheCoins
[txid
] = coins
;
90 CCoinsMap::iterator
CCoinsViewCache::FetchCoins(const uint256
&txid
) {
91 CCoinsMap::iterator it
= cacheCoins
.find(txid
);
92 if (it
!= cacheCoins
.end())
95 if (!base
->GetCoins(txid
,tmp
))
96 return cacheCoins
.end();
97 CCoinsMap::iterator ret
= cacheCoins
.insert(it
, std::make_pair(txid
, CCoins()));
98 tmp
.swap(ret
->second
);
102 CCoins
&CCoinsViewCache::GetCoins(const uint256
&txid
) {
103 CCoinsMap::iterator it
= FetchCoins(txid
);
104 assert(it
!= cacheCoins
.end());
108 bool CCoinsViewCache::SetCoins(const uint256
&txid
, const CCoins
&coins
) {
109 cacheCoins
[txid
] = coins
;
113 bool CCoinsViewCache::HaveCoins(const uint256
&txid
) {
114 CCoinsMap::iterator it
= FetchCoins(txid
);
115 // We're using vtx.empty() instead of IsPruned here for performance reasons,
116 // as we only care about the case where an transaction was replaced entirely
117 // in a reorganization (which wipes vout entirely, as opposed to spending
118 // which just cleans individual outputs).
119 return (it
!= cacheCoins
.end() && !it
->second
.vout
.empty());
122 uint256
CCoinsViewCache::GetBestBlock() {
123 if (hashBlock
== uint256(0))
124 hashBlock
= base
->GetBestBlock();
128 bool CCoinsViewCache::SetBestBlock(const uint256
&hashBlockIn
) {
129 hashBlock
= hashBlockIn
;
133 bool CCoinsViewCache::BatchWrite(const CCoinsMap
&mapCoins
, const uint256
&hashBlockIn
) {
134 for (CCoinsMap::const_iterator it
= mapCoins
.begin(); it
!= mapCoins
.end(); it
++)
135 cacheCoins
[it
->first
] = it
->second
;
136 hashBlock
= hashBlockIn
;
140 bool CCoinsViewCache::Flush() {
141 bool fOk
= base
->BatchWrite(cacheCoins
, hashBlock
);
147 unsigned int CCoinsViewCache::GetCacheSize() {
148 return cacheCoins
.size();
151 const CTxOut
&CCoinsViewCache::GetOutputFor(const CTxIn
& input
)
153 const CCoins
&coins
= GetCoins(input
.prevout
.hash
);
154 assert(coins
.IsAvailable(input
.prevout
.n
));
155 return coins
.vout
[input
.prevout
.n
];
158 int64_t CCoinsViewCache::GetValueIn(const CTransaction
& tx
)
164 for (unsigned int i
= 0; i
< tx
.vin
.size(); i
++)
165 nResult
+= GetOutputFor(tx
.vin
[i
]).nValue
;
170 bool CCoinsViewCache::HaveInputs(const CTransaction
& tx
)
172 if (!tx
.IsCoinBase()) {
173 // first check whether information about the prevout hash is available
174 for (unsigned int i
= 0; i
< tx
.vin
.size(); i
++) {
175 const COutPoint
&prevout
= tx
.vin
[i
].prevout
;
176 if (!HaveCoins(prevout
.hash
))
180 // then check whether the actual outputs are available
181 for (unsigned int i
= 0; i
< tx
.vin
.size(); i
++) {
182 const COutPoint
&prevout
= tx
.vin
[i
].prevout
;
183 const CCoins
&coins
= GetCoins(prevout
.hash
);
184 if (!coins
.IsAvailable(prevout
.n
))
191 double CCoinsViewCache::GetPriority(const CTransaction
&tx
, int nHeight
)
195 double dResult
= 0.0;
196 BOOST_FOREACH(const CTxIn
& txin
, tx
.vin
)
198 const CCoins
&coins
= GetCoins(txin
.prevout
.hash
);
199 if (!coins
.IsAvailable(txin
.prevout
.n
)) continue;
200 if (coins
.nHeight
< nHeight
) {
201 dResult
+= coins
.vout
[txin
.prevout
.n
].nValue
* (nHeight
-coins
.nHeight
);
204 return tx
.ComputePriority(dResult
);