#ifndef BITCOIN_COINS_H
#define BITCOIN_COINS_H
+#define KOMODO_ENABLE_INTEREST //enabling this is a hardfork, activate with new RR method
+
#include "compressor.h"
+#include "core_memusage.h"
#include "memusage.h"
#include "serialize.h"
#include "uint256.h"
+#include "base58.h"
+#include "pubkey.h"
#include <assert.h>
#include <stdint.h>
+#include <vector>
+#include <unordered_map>
#include <boost/foreach.hpp>
#include <boost/unordered_map.hpp>
+#include "zcash/IncrementalMerkleTree.hpp"
+#include "veruslaunch.h"
/**
* Pruned version of CTransaction: only retains metadata and unspent transaction outputs
//! version of the CTransaction; accesses to this value should probably check for nHeight as well,
//! as new tx version will probably only be introduced at certain heights
int nVersion;
+ //uint32_t nLockTime;
void FromTx(const CTransaction &tx, int nHeightIn) {
fCoinBase = tx.IsCoinBase();
vout = tx.vout;
nHeight = nHeightIn;
nVersion = tx.nVersion;
+ //nLockTime = tx.nLockTime;
ClearUnspendable();
}
nSize += ::GetSerializeSize(VARINT(nCode), nType, nVersion);
// spentness bitmask
nSize += nMaskSize;
- // txouts themself
+ // txouts
for (unsigned int i = 0; i < vout.size(); i++)
if (!vout[i].IsNull())
nSize += ::GetSerializeSize(CTxOutCompressor(REF(vout[i])), nType, nVersion);
size_t DynamicMemoryUsage() const {
size_t ret = memusage::DynamicUsage(vout);
BOOST_FOREACH(const CTxOut &out, vout) {
- const std::vector<unsigned char> *script = &out.scriptPubKey;
- ret += memusage::DynamicUsage(*script);
+ ret += RecursiveDynamicUsage(out.scriptPubKey);
}
return ret;
}
+
+ int64_t TotalTxValue() const {
+ int64_t total = 0;
+ BOOST_FOREACH(const CTxOut &out, vout) {
+ total += out.nValue;
+ }
+ return total;
+ }
};
class CCoinsKeyHasher
CCoinsCacheEntry() : coins(), flags(0) {}
};
+struct CAnchorsCacheEntry
+{
+ bool entered; // This will be false if the anchor is removed from the cache
+ ZCIncrementalMerkleTree tree; // The tree itself
+ unsigned char flags;
+
+ enum Flags {
+ DIRTY = (1 << 0), // This cache entry is potentially different from the version in the parent view.
+ };
+
+ CAnchorsCacheEntry() : entered(false), flags(0) {}
+};
+
+struct CNullifiersCacheEntry
+{
+ bool entered; // If the nullifier is spent or not
+ unsigned char flags;
+
+ enum Flags {
+ DIRTY = (1 << 0), // This cache entry is potentially different from the version in the parent view.
+ };
+
+ CNullifiersCacheEntry() : entered(false), flags(0) {}
+};
+
typedef boost::unordered_map<uint256, CCoinsCacheEntry, CCoinsKeyHasher> CCoinsMap;
+typedef boost::unordered_map<uint256, CAnchorsCacheEntry, CCoinsKeyHasher> CAnchorsMap;
+typedef boost::unordered_map<uint256, CNullifiersCacheEntry, CCoinsKeyHasher> CNullifiersMap;
struct CCoinsStats
{
class CCoinsView
{
public:
+ //! Retrieve the tree at a particular anchored root in the chain
+ virtual bool GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const;
+
+ //! Determine whether a nullifier is spent or not
+ virtual bool GetNullifier(const uint256 &nullifier) const;
+
//! Retrieve the CCoins (unspent transaction outputs) for a given txid
virtual bool GetCoins(const uint256 &txid, CCoins &coins) const;
//! Retrieve the block hash whose state this CCoinsView currently represents
virtual uint256 GetBestBlock() const;
+ //! Get the current "tip" or the latest anchored tree root in the chain
+ virtual uint256 GetBestAnchor() const;
+
//! Do a bulk modification (multiple CCoins changes + BestBlock change).
//! The passed mapCoins can be modified.
- virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock);
+ virtual bool BatchWrite(CCoinsMap &mapCoins,
+ const uint256 &hashBlock,
+ const uint256 &hashAnchor,
+ CAnchorsMap &mapAnchors,
+ CNullifiersMap &mapNullifiers);
//! Calculate statistics about the unspent transaction output set
virtual bool GetStats(CCoinsStats &stats) const;
public:
CCoinsViewBacked(CCoinsView *viewIn);
+ bool GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const;
+ bool GetNullifier(const uint256 &nullifier) const;
bool GetCoins(const uint256 &txid, CCoins &coins) const;
bool HaveCoins(const uint256 &txid) const;
uint256 GetBestBlock() const;
+ uint256 GetBestAnchor() const;
void SetBackend(CCoinsView &viewIn);
- bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock);
+ bool BatchWrite(CCoinsMap &mapCoins,
+ const uint256 &hashBlock,
+ const uint256 &hashAnchor,
+ CAnchorsMap &mapAnchors,
+ CNullifiersMap &mapNullifiers);
bool GetStats(CCoinsStats &stats) const;
};
friend class CCoinsViewCache;
};
+class CTransactionExceptionData
+{
+ public:
+ CScript scriptPubKey;
+ uint64_t voutMask;
+ CTransactionExceptionData() : scriptPubKey(), voutMask() {}
+};
+
+class CLaunchMap
+{
+ public:
+ std::unordered_map<std::string, CTransactionExceptionData> lmap;
+ CLaunchMap() : lmap()
+ {
+ //printf("txid: %s -> addr: %s\n", whitelist_ids[i], whitelist_addrs[i]);
+ CBitcoinAddress bcaddr(whitelist_address);
+ CKeyID key;
+ if (bcaddr.GetKeyID_NoCheck(key))
+ {
+ std::vector<unsigned char> address = std::vector<unsigned char>(key.begin(), key.end());
+ for (int i = 0; i < WHITELIST_COUNT; i++)
+ {
+ std::string hash = uint256S(whitelist_ids[i]).ToString();
+ lmap[hash].scriptPubKey << OP_DUP << OP_HASH160 << address << OP_EQUALVERIFY << OP_CHECKSIG;
+ lmap[hash].voutMask = whitelist_masks[i];
+ }
+ }
+ }
+};
+static CLaunchMap launchMap = CLaunchMap();
+
/** CCoinsView that adds a memory cache for transactions to another CCoinsView */
class CCoinsViewCache : public CCoinsViewBacked
{
/* 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".
*/
mutable uint256 hashBlock;
mutable CCoinsMap cacheCoins;
+ mutable uint256 hashAnchor;
+ mutable CAnchorsMap cacheAnchors;
+ mutable CNullifiersMap cacheNullifiers;
/* Cached dynamic memory usage for the inner CCoins objects. */
mutable size_t cachedCoinsUsage;
~CCoinsViewCache();
// Standard CCoinsView methods
+ static CLaunchMap &LaunchMap() { return launchMap; }
+ bool GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const;
+ bool GetNullifier(const uint256 &nullifier) const;
bool GetCoins(const uint256 &txid, CCoins &coins) const;
bool HaveCoins(const uint256 &txid) const;
uint256 GetBestBlock() const;
+ uint256 GetBestAnchor() const;
void SetBestBlock(const uint256 &hashBlock);
- bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock);
+ bool BatchWrite(CCoinsMap &mapCoins,
+ const uint256 &hashBlock,
+ const uint256 &hashAnchor,
+ CAnchorsMap &mapAnchors,
+ CNullifiersMap &mapNullifiers);
+
+
+ // Adds the tree to mapAnchors and sets the current commitment
+ // root to this root.
+ void PushAnchor(const ZCIncrementalMerkleTree &tree);
+
+ // Removes the current commitment root from mapAnchors and sets
+ // the new current root.
+ void PopAnchor(const uint256 &rt);
+
+ // Marks a nullifier as spent or not.
+ void SetNullifier(const uint256 &nullifier, bool spent);
/**
* Return a pointer to CCoins in the cache, or NULL if not found. This is
* @param[in] tx transaction for which we are checking input total
* @return Sum of value of all inputs (scriptSigs)
*/
- CAmount GetValueIn(const CTransaction& tx) const;
+ CAmount GetValueIn(int32_t nHeight,int64_t *interestp,const CTransaction& tx,uint32_t prevblocktime) const;
//! Check whether all prevouts of the transaction are present in the UTXO set represented by this view
bool HaveInputs(const CTransaction& tx) const;
+ //! Check whether all joinsplit requirements (anchors/nullifiers) are satisfied
+ bool HaveJoinSplitRequirements(const CTransaction& tx) const;
+
//! Return priority of tx at height nHeight
double GetPriority(const CTransaction &tx, int nHeight) const;
const CTxOut &GetOutputFor(const CTxIn& input) const;
+ const CScript &GetSpendFor(const CTxIn& input) const;
+ static const CScript &GetSpendFor(const CCoins *coins, const CTxIn& input);
friend class CCoinsModifier;