aboutsummaryrefslogtreecommitdiff
path: root/src/coins.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/coins.h')
-rw-r--r--src/coins.h81
1 files changed, 63 insertions, 18 deletions
diff --git a/src/coins.h b/src/coins.h
index 2583475323..b8f1e5bcc5 100644
--- a/src/coins.h
+++ b/src/coins.h
@@ -83,11 +83,26 @@ public:
// as new tx version will probably only be introduced at certain heights
int nVersion;
- // construct a CCoins from a CTransaction, at a given height
- CCoins(const CTransaction &tx, int nHeightIn) : fCoinBase(tx.IsCoinBase()), vout(tx.vout), nHeight(nHeightIn), nVersion(tx.nVersion) {
+ void FromTx(const CTransaction &tx, int nHeightIn) {
+ fCoinBase = tx.IsCoinBase();
+ vout = tx.vout;
+ nHeight = nHeightIn;
+ nVersion = tx.nVersion;
ClearUnspendable();
}
+ // construct a CCoins from a CTransaction, at a given height
+ CCoins(const CTransaction &tx, int nHeightIn) {
+ FromTx(tx, nHeightIn);
+ }
+
+ void Clear() {
+ fCoinBase = false;
+ std::vector<CTxOut>().swap(vout);
+ nHeight = 0;
+ nVersion = 0;
+ }
+
// empty constructor
CCoins() : fCoinBase(false), vout(0), nHeight(0), nVersion(0) { }
@@ -256,7 +271,20 @@ public:
}
};
-typedef boost::unordered_map<uint256, CCoins, CCoinsKeyHasher> CCoinsMap;
+struct CCoinsCacheEntry
+{
+ CCoins coins; // The actual cached data.
+ unsigned char flags;
+
+ enum Flags {
+ DIRTY = (1 << 0), // This cache entry is potentially different from the version in the parent view.
+ FRESH = (1 << 1), // The parent view does not have this entry (or it is pruned).
+ };
+
+ CCoinsCacheEntry() : coins(), flags(0) {}
+};
+
+typedef boost::unordered_map<uint256, CCoinsCacheEntry, CCoinsKeyHasher> CCoinsMap;
struct CCoinsStats
{
@@ -279,9 +307,6 @@ public:
// Retrieve the CCoins (unspent transaction outputs) for a given txid
virtual bool GetCoins(const uint256 &txid, CCoins &coins) const;
- // Modify the CCoins for a given txid
- virtual bool SetCoins(const uint256 &txid, const CCoins &coins);
-
// Just check whether we have data for a given txid.
// This may (but cannot always) return true for fully spent transactions
virtual bool HaveCoins(const uint256 &txid) const;
@@ -289,10 +314,7 @@ public:
// Retrieve the block hash whose state this CCoinsView currently represents
virtual uint256 GetBestBlock() const;
- // Modify the currently active block hash
- virtual bool SetBestBlock(const uint256 &hashBlock);
-
- // Do a bulk modification (multiple SetCoins + one SetBestBlock).
+ // Do a bulk modification (multiple CCoins changes + BestBlock change).
// The passed mapCoins can be modified.
virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock);
@@ -311,22 +333,41 @@ protected:
CCoinsView *base;
public:
- CCoinsViewBacked(CCoinsView &viewIn);
+ CCoinsViewBacked(CCoinsView *viewIn);
bool GetCoins(const uint256 &txid, CCoins &coins) const;
- bool SetCoins(const uint256 &txid, const CCoins &coins);
bool HaveCoins(const uint256 &txid) const;
uint256 GetBestBlock() const;
- bool SetBestBlock(const uint256 &hashBlock);
void SetBackend(CCoinsView &viewIn);
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock);
bool GetStats(CCoinsStats &stats) const;
};
+class CCoinsViewCache;
+
+/** A reference to a mutable cache entry. Encapsulating it allows us to run
+ * cleanup code after the modification is finished, and keeping track of
+ * concurrent modifications. */
+class CCoinsModifier
+{
+private:
+ CCoinsViewCache& cache;
+ CCoinsMap::iterator it;
+ CCoinsModifier(CCoinsViewCache& cache_, CCoinsMap::iterator it_);
+
+public:
+ CCoins* operator->() { return &it->second.coins; }
+ CCoins& operator*() { return it->second.coins; }
+ ~CCoinsModifier();
+ friend class CCoinsViewCache;
+};
+
/** CCoinsView that adds a memory cache for transactions to another CCoinsView */
class CCoinsViewCache : public CCoinsViewBacked
{
protected:
+ /* Whether this cache has an active modifier. */
+ bool hasModifier;
/* Make mutable so that we can "fill the cache" even from Get-methods
declared as "const". */
@@ -334,14 +375,14 @@ protected:
mutable CCoinsMap cacheCoins;
public:
- CCoinsViewCache(CCoinsView &baseIn, bool fDummy = false);
+ CCoinsViewCache(CCoinsView *baseIn);
+ ~CCoinsViewCache();
// Standard CCoinsView methods
bool GetCoins(const uint256 &txid, CCoins &coins) const;
- bool SetCoins(const uint256 &txid, const CCoins &coins);
bool HaveCoins(const uint256 &txid) const;
uint256 GetBestBlock() const;
- bool SetBestBlock(const uint256 &hashBlock);
+ void SetBestBlock(const uint256 &hashBlock);
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock);
// Return a pointer to CCoins in the cache, or NULL if not found. This is
@@ -349,8 +390,10 @@ public:
// allowed while accessing the returned pointer.
const CCoins* AccessCoins(const uint256 &txid) const;
- // Return a modifiable reference to a CCoins. Check HaveCoins first.
- CCoins &GetCoins(const uint256 &txid);
+ // Return a modifiable reference to a CCoins. If no entry with the given
+ // txid exists, a new one is created. Simultaneous modifications are not
+ // allowed.
+ CCoinsModifier ModifyCoins(const uint256 &txid);
// Push the modifications applied to this cache to its base.
// Failure to call this method before destruction will cause the changes to be forgotten.
@@ -377,6 +420,8 @@ public:
const CTxOut &GetOutputFor(const CTxIn& input) const;
+ friend class CCoinsModifier;
+
private:
CCoinsMap::iterator FetchCoins(const uint256 &txid);
CCoinsMap::const_iterator FetchCoins(const uint256 &txid) const;