main: spentindex for the mempool
Zcash: Adapted to older mempool code
This commit is contained in:
parent
fc5d4a55fe
commit
6e50c56edd
|
@ -95,13 +95,22 @@ class SpentIndexTest(BitcoinTestFramework):
|
|||
self.nodes[0].importprivkey(privkey)
|
||||
signed_tx2 = self.nodes[0].signrawtransaction(binascii.hexlify(tx2.serialize()).decode("utf-8"))
|
||||
txid2 = self.nodes[0].sendrawtransaction(signed_tx2["hex"], True)
|
||||
|
||||
# Check the mempool index
|
||||
self.sync_all()
|
||||
txVerbose3 = self.nodes[1].getrawtransaction(txid2, 1)
|
||||
assert_equal(txVerbose3["vin"][0]["address"], address2)
|
||||
assert_equal(txVerbose3["vin"][0]["value"], Decimal(unspent[0]["amount"]))
|
||||
assert_equal(txVerbose3["vin"][0]["valueSat"], amount)
|
||||
|
||||
# Check the database index
|
||||
self.nodes[0].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
txVerbose3 = self.nodes[3].getrawtransaction(txid2, 1)
|
||||
assert_equal(txVerbose3["vin"][0]["address"], address2)
|
||||
assert_equal(txVerbose2["vin"][0]["value"], Decimal(unspent[0]["amount"]))
|
||||
assert_equal(txVerbose2["vin"][0]["valueSat"], amount)
|
||||
txVerbose4 = self.nodes[3].getrawtransaction(txid2, 1)
|
||||
assert_equal(txVerbose4["vin"][0]["address"], address2)
|
||||
assert_equal(txVerbose4["vin"][0]["value"], Decimal(unspent[0]["amount"]))
|
||||
assert_equal(txVerbose4["vin"][0]["valueSat"], amount)
|
||||
|
||||
print "Passed\n"
|
||||
|
||||
|
|
|
@ -114,6 +114,7 @@ LIBZCASH_H = \
|
|||
# bitcoin core #
|
||||
BITCOIN_CORE_H = \
|
||||
addressindex.h \
|
||||
spentindex.h \
|
||||
addrman.h \
|
||||
alert.h \
|
||||
amount.h \
|
||||
|
|
10
src/main.cpp
10
src/main.cpp
|
@ -1578,9 +1578,16 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
|||
|
||||
// Store transaction in memory
|
||||
pool.addUnchecked(hash, entry, !IsInitialBlockDownload());
|
||||
|
||||
// Add memory address index
|
||||
if (fAddressIndex) {
|
||||
pool.addAddressIndex(entry, view);
|
||||
}
|
||||
|
||||
// Add memory spent index
|
||||
if (fSpentIndex) {
|
||||
pool.addSpentIndex(entry, view);
|
||||
}
|
||||
}
|
||||
|
||||
SyncWithWallets(tx, NULL);
|
||||
|
@ -1604,6 +1611,9 @@ bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value)
|
|||
if (!fSpentIndex)
|
||||
return false;
|
||||
|
||||
if (mempool.getSpentIndex(key, value))
|
||||
return true;
|
||||
|
||||
if (!pblocktree->ReadSpentIndex(key, value))
|
||||
return error("unable to get spent info");
|
||||
|
||||
|
|
76
src/main.h
76
src/main.h
|
@ -22,6 +22,7 @@
|
|||
#include "script/script.h"
|
||||
#include "script/sigcache.h"
|
||||
#include "script/standard.h"
|
||||
#include "spentindex.h"
|
||||
#include "sync.h"
|
||||
#include "tinyformat.h"
|
||||
#include "txmempool.h"
|
||||
|
@ -271,81 +272,6 @@ struct CNodeStateStats {
|
|||
std::vector<int> vHeightInFlight;
|
||||
};
|
||||
|
||||
struct CSpentIndexKey {
|
||||
uint256 txid;
|
||||
unsigned int outputIndex;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(txid);
|
||||
READWRITE(outputIndex);
|
||||
}
|
||||
|
||||
CSpentIndexKey(uint256 t, unsigned int i) {
|
||||
txid = t;
|
||||
outputIndex = i;
|
||||
}
|
||||
|
||||
CSpentIndexKey() {
|
||||
SetNull();
|
||||
}
|
||||
|
||||
void SetNull() {
|
||||
txid.SetNull();
|
||||
outputIndex = 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct CSpentIndexValue {
|
||||
uint256 txid;
|
||||
unsigned int inputIndex;
|
||||
int blockHeight;
|
||||
CAmount satoshis;
|
||||
int addressType;
|
||||
uint160 addressHash;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(txid);
|
||||
READWRITE(inputIndex);
|
||||
READWRITE(blockHeight);
|
||||
READWRITE(satoshis);
|
||||
READWRITE(addressType);
|
||||
READWRITE(addressHash);
|
||||
}
|
||||
|
||||
CSpentIndexValue(uint256 t, unsigned int i, int h, CAmount s, int type, uint160 a) {
|
||||
txid = t;
|
||||
inputIndex = i;
|
||||
blockHeight = h;
|
||||
satoshis = s;
|
||||
addressType = type;
|
||||
addressHash = a;
|
||||
}
|
||||
|
||||
CSpentIndexValue() {
|
||||
SetNull();
|
||||
}
|
||||
|
||||
void SetNull() {
|
||||
txid.SetNull();
|
||||
inputIndex = 0;
|
||||
blockHeight = 0;
|
||||
satoshis = 0;
|
||||
addressType = 0;
|
||||
addressHash.SetNull();
|
||||
}
|
||||
|
||||
bool IsNull() const {
|
||||
return txid.IsNull();
|
||||
}
|
||||
};
|
||||
|
||||
struct CTimestampIndexIteratorKey {
|
||||
unsigned int timestamp;
|
||||
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2015 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_SPENTINDEX_H
|
||||
#define BITCOIN_SPENTINDEX_H
|
||||
|
||||
#include "uint256.h"
|
||||
#include "amount.h"
|
||||
|
||||
struct CSpentIndexKey {
|
||||
uint256 txid;
|
||||
unsigned int outputIndex;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(txid);
|
||||
READWRITE(outputIndex);
|
||||
}
|
||||
|
||||
CSpentIndexKey(uint256 t, unsigned int i) {
|
||||
txid = t;
|
||||
outputIndex = i;
|
||||
}
|
||||
|
||||
CSpentIndexKey() {
|
||||
SetNull();
|
||||
}
|
||||
|
||||
void SetNull() {
|
||||
txid.SetNull();
|
||||
outputIndex = 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct CSpentIndexValue {
|
||||
uint256 txid;
|
||||
unsigned int inputIndex;
|
||||
int blockHeight;
|
||||
CAmount satoshis;
|
||||
int addressType;
|
||||
uint160 addressHash;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(txid);
|
||||
READWRITE(inputIndex);
|
||||
READWRITE(blockHeight);
|
||||
READWRITE(satoshis);
|
||||
READWRITE(addressType);
|
||||
READWRITE(addressHash);
|
||||
}
|
||||
|
||||
CSpentIndexValue(uint256 t, unsigned int i, int h, CAmount s, int type, uint160 a) {
|
||||
txid = t;
|
||||
inputIndex = i;
|
||||
blockHeight = h;
|
||||
satoshis = s;
|
||||
addressType = type;
|
||||
addressHash = a;
|
||||
}
|
||||
|
||||
CSpentIndexValue() {
|
||||
SetNull();
|
||||
}
|
||||
|
||||
void SetNull() {
|
||||
txid.SetNull();
|
||||
inputIndex = 0;
|
||||
blockHeight = 0;
|
||||
satoshis = 0;
|
||||
addressType = 0;
|
||||
addressHash.SetNull();
|
||||
}
|
||||
|
||||
bool IsNull() const {
|
||||
return txid.IsNull();
|
||||
}
|
||||
};
|
||||
|
||||
struct CSpentIndexKeyCompare
|
||||
{
|
||||
bool operator()(const CSpentIndexKey& a, const CSpentIndexKey& b) const {
|
||||
if (a.txid == b.txid) {
|
||||
return a.outputIndex < b.outputIndex;
|
||||
} else {
|
||||
return a.txid < b.txid;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // BITCOIN_SPENTINDEX_H
|
|
@ -195,6 +195,71 @@ bool CTxMemPool::removeAddressIndex(const uint256 txhash)
|
|||
return true;
|
||||
}
|
||||
|
||||
void CTxMemPool::addSpentIndex(const CTxMemPoolEntry &entry, const CCoinsViewCache &view)
|
||||
{
|
||||
LOCK(cs);
|
||||
|
||||
const CTransaction& tx = entry.GetTx();
|
||||
std::vector<CSpentIndexKey> inserted;
|
||||
|
||||
uint256 txhash = tx.GetHash();
|
||||
for (unsigned int j = 0; j < tx.vin.size(); j++) {
|
||||
const CTxIn input = tx.vin[j];
|
||||
const CTxOut &prevout = view.GetOutputFor(input);
|
||||
uint160 addressHash;
|
||||
int addressType;
|
||||
|
||||
if (prevout.scriptPubKey.IsPayToScriptHash()) {
|
||||
addressHash = uint160(vector<unsigned char> (prevout.scriptPubKey.begin()+2, prevout.scriptPubKey.begin()+22));
|
||||
addressType = 2;
|
||||
} else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) {
|
||||
addressHash = uint160(vector<unsigned char> (prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23));
|
||||
addressType = 1;
|
||||
} else {
|
||||
addressHash.SetNull();
|
||||
addressType = 0;
|
||||
}
|
||||
|
||||
CSpentIndexKey key = CSpentIndexKey(input.prevout.hash, input.prevout.n);
|
||||
CSpentIndexValue value = CSpentIndexValue(txhash, j, -1, prevout.nValue, addressType, addressHash);
|
||||
|
||||
mapSpent.insert(make_pair(key, value));
|
||||
inserted.push_back(key);
|
||||
|
||||
}
|
||||
|
||||
mapSpentInserted.insert(make_pair(txhash, inserted));
|
||||
}
|
||||
|
||||
bool CTxMemPool::getSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value)
|
||||
{
|
||||
LOCK(cs);
|
||||
mapSpentIndex::iterator it;
|
||||
|
||||
it = mapSpent.find(key);
|
||||
if (it != mapSpent.end()) {
|
||||
value = it->second;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CTxMemPool::removeSpentIndex(const uint256 txhash)
|
||||
{
|
||||
LOCK(cs);
|
||||
mapSpentIndexInserted::iterator it = mapSpentInserted.find(txhash);
|
||||
|
||||
if (it != mapSpentInserted.end()) {
|
||||
std::vector<CSpentIndexKey> keys = (*it).second;
|
||||
for (std::vector<CSpentIndexKey>::iterator mit = keys.begin(); mit != keys.end(); mit++) {
|
||||
mapSpent.erase(*mit);
|
||||
}
|
||||
mapSpentInserted.erase(it);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CTxMemPool::remove(const CTransaction &origTx, std::list<CTransaction>& removed, bool fRecursive)
|
||||
{
|
||||
// Remove transaction from memory pool
|
||||
|
@ -246,6 +311,7 @@ void CTxMemPool::remove(const CTransaction &origTx, std::list<CTransaction>& rem
|
|||
nTransactionsUpdated++;
|
||||
minerPolicyEstimator->removeTx(hash);
|
||||
removeAddressIndex(hash);
|
||||
removeSpentIndex(hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <list>
|
||||
|
||||
#include "addressindex.h"
|
||||
#include "spentindex.h"
|
||||
#include "amount.h"
|
||||
#include "coins.h"
|
||||
#include "primitives/transaction.h"
|
||||
|
@ -161,6 +162,12 @@ private:
|
|||
typedef std::map<uint256, std::vector<CMempoolAddressDeltaKey> > addressDeltaMapInserted;
|
||||
addressDeltaMapInserted mapAddressInserted;
|
||||
|
||||
typedef std::map<CSpentIndexKey, CSpentIndexValue, CSpentIndexKeyCompare> mapSpentIndex;
|
||||
mapSpentIndex mapSpent;
|
||||
|
||||
typedef std::map<uint256, std::vector<CSpentIndexKey> > mapSpentIndexInserted;
|
||||
mapSpentIndexInserted mapSpentInserted;
|
||||
|
||||
public:
|
||||
std::map<COutPoint, CInPoint> mapNextTx;
|
||||
std::map<uint256, std::pair<double, CAmount> > mapDeltas;
|
||||
|
@ -184,6 +191,10 @@ public:
|
|||
std::vector<std::pair<CMempoolAddressDeltaKey, CMempoolAddressDelta> > &results);
|
||||
bool removeAddressIndex(const uint256 txhash);
|
||||
|
||||
void addSpentIndex(const CTxMemPoolEntry &entry, const CCoinsViewCache &view);
|
||||
bool getSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value);
|
||||
bool removeSpentIndex(const uint256 txhash);
|
||||
|
||||
void remove(const CTransaction &tx, std::list<CTransaction>& removed, bool fRecursive = false);
|
||||
void removeWithAnchor(const uint256 &invalidRoot, ShieldedType type);
|
||||
void removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags);
|
||||
|
|
Loading…
Reference in New Issue