Skip to content

Commit c5b1b04

Browse files
author
Braydon Fuller
committed
main: spentindex for the mempool
1 parent 5e54311 commit c5b1b04

File tree

7 files changed

+200
-79
lines changed

7 files changed

+200
-79
lines changed

qa/rpc-tests/spentindex.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,22 @@ def run_test(self):
9595
self.nodes[0].importprivkey(privkey)
9696
signed_tx2 = self.nodes[0].signrawtransaction(binascii.hexlify(tx2.serialize()).decode("utf-8"))
9797
txid2 = self.nodes[0].sendrawtransaction(signed_tx2["hex"], True)
98+
99+
# Check the mempool index
100+
self.sync_all()
101+
txVerbose3 = self.nodes[1].getrawtransaction(txid2, 1)
102+
assert_equal(txVerbose3["vin"][0]["address"], address2)
103+
assert_equal(txVerbose3["vin"][0]["value"], Decimal(unspent[0]["amount"]))
104+
assert_equal(txVerbose3["vin"][0]["valueSat"], amount)
105+
106+
# Check the database index
98107
self.nodes[0].generate(1)
99108
self.sync_all()
100109

101-
txVerbose3 = self.nodes[3].getrawtransaction(txid2, 1)
102-
assert_equal(txVerbose3["vin"][0]["address"], address2)
103-
assert_equal(txVerbose2["vin"][0]["value"], Decimal(unspent[0]["amount"]))
104-
assert_equal(txVerbose2["vin"][0]["valueSat"], amount)
110+
txVerbose4 = self.nodes[3].getrawtransaction(txid2, 1)
111+
assert_equal(txVerbose4["vin"][0]["address"], address2)
112+
assert_equal(txVerbose4["vin"][0]["value"], Decimal(unspent[0]["amount"]))
113+
assert_equal(txVerbose4["vin"][0]["valueSat"], amount)
105114

106115
print "Passed\n"
107116

src/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ endif
8080
# bitcoin core #
8181
BITCOIN_CORE_H = \
8282
addressindex.h \
83+
spentindex.h \
8384
addrman.h \
8485
alert.h \
8586
amount.h \

src/main.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,10 +1209,17 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
12091209

12101210
// Store transaction in memory
12111211
pool.addUnchecked(hash, entry, setAncestors, !IsInitialBlockDownload());
1212+
1213+
// Add memory address index
12121214
if (fAddressIndex) {
12131215
pool.addAddressIndex(entry, view);
12141216
}
12151217

1218+
// Add memory spent index
1219+
if (fSpentIndex) {
1220+
pool.addSpentIndex(entry, view);
1221+
}
1222+
12161223
// trim mempool and check if tx was trimmed
12171224
if (!fOverrideMempoolLimit) {
12181225
LimitMempoolSize(pool, GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60);
@@ -1254,6 +1261,9 @@ bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value)
12541261
if (!fSpentIndex)
12551262
return false;
12561263

1264+
if (mempool.getSpentIndex(key, value))
1265+
return true;
1266+
12571267
if (!pblocktree->ReadSpentIndex(key, value))
12581268
return error("unable to get spent info");
12591269

src/main.h

Lines changed: 1 addition & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "net.h"
1717
#include "script/script_error.h"
1818
#include "sync.h"
19+
#include "spentindex.h"
1920

2021
#include <algorithm>
2122
#include <exception>
@@ -284,81 +285,6 @@ struct CNodeStateStats {
284285
std::vector<int> vHeightInFlight;
285286
};
286287

287-
struct CSpentIndexKey {
288-
uint256 txid;
289-
unsigned int outputIndex;
290-
291-
ADD_SERIALIZE_METHODS;
292-
293-
template <typename Stream, typename Operation>
294-
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
295-
READWRITE(txid);
296-
READWRITE(outputIndex);
297-
}
298-
299-
CSpentIndexKey(uint256 t, unsigned int i) {
300-
txid = t;
301-
outputIndex = i;
302-
}
303-
304-
CSpentIndexKey() {
305-
SetNull();
306-
}
307-
308-
void SetNull() {
309-
txid.SetNull();
310-
outputIndex = 0;
311-
}
312-
313-
};
314-
315-
struct CSpentIndexValue {
316-
uint256 txid;
317-
unsigned int inputIndex;
318-
int blockHeight;
319-
CAmount satoshis;
320-
int addressType;
321-
uint160 addressHash;
322-
323-
ADD_SERIALIZE_METHODS;
324-
325-
template <typename Stream, typename Operation>
326-
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
327-
READWRITE(txid);
328-
READWRITE(inputIndex);
329-
READWRITE(blockHeight);
330-
READWRITE(satoshis);
331-
READWRITE(addressType);
332-
READWRITE(addressHash);
333-
}
334-
335-
CSpentIndexValue(uint256 t, unsigned int i, int h, CAmount s, int type, uint160 a) {
336-
txid = t;
337-
inputIndex = i;
338-
blockHeight = h;
339-
satoshis = s;
340-
addressType = type;
341-
addressHash = a;
342-
}
343-
344-
CSpentIndexValue() {
345-
SetNull();
346-
}
347-
348-
void SetNull() {
349-
txid.SetNull();
350-
inputIndex = 0;
351-
blockHeight = 0;
352-
satoshis = 0;
353-
addressType = 0;
354-
addressHash.SetNull();
355-
}
356-
357-
bool IsNull() const {
358-
return txid.IsNull();
359-
}
360-
};
361-
362288
struct CTimestampIndexIteratorKey {
363289
unsigned int timestamp;
364290

src/spentindex.h

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// Copyright (c) 2009-2010 Satoshi Nakamoto
2+
// Copyright (c) 2009-2015 The Bitcoin Core developers
3+
// Distributed under the MIT software license, see the accompanying
4+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5+
6+
#ifndef BITCOIN_SPENTINDEX_H
7+
#define BITCOIN_SPENTINDEX_H
8+
9+
#include "uint256.h"
10+
#include "amount.h"
11+
12+
struct CSpentIndexKey {
13+
uint256 txid;
14+
unsigned int outputIndex;
15+
16+
ADD_SERIALIZE_METHODS;
17+
18+
template <typename Stream, typename Operation>
19+
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
20+
READWRITE(txid);
21+
READWRITE(outputIndex);
22+
}
23+
24+
CSpentIndexKey(uint256 t, unsigned int i) {
25+
txid = t;
26+
outputIndex = i;
27+
}
28+
29+
CSpentIndexKey() {
30+
SetNull();
31+
}
32+
33+
void SetNull() {
34+
txid.SetNull();
35+
outputIndex = 0;
36+
}
37+
38+
};
39+
40+
struct CSpentIndexValue {
41+
uint256 txid;
42+
unsigned int inputIndex;
43+
int blockHeight;
44+
CAmount satoshis;
45+
int addressType;
46+
uint160 addressHash;
47+
48+
ADD_SERIALIZE_METHODS;
49+
50+
template <typename Stream, typename Operation>
51+
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
52+
READWRITE(txid);
53+
READWRITE(inputIndex);
54+
READWRITE(blockHeight);
55+
READWRITE(satoshis);
56+
READWRITE(addressType);
57+
READWRITE(addressHash);
58+
}
59+
60+
CSpentIndexValue(uint256 t, unsigned int i, int h, CAmount s, int type, uint160 a) {
61+
txid = t;
62+
inputIndex = i;
63+
blockHeight = h;
64+
satoshis = s;
65+
addressType = type;
66+
addressHash = a;
67+
}
68+
69+
CSpentIndexValue() {
70+
SetNull();
71+
}
72+
73+
void SetNull() {
74+
txid.SetNull();
75+
inputIndex = 0;
76+
blockHeight = 0;
77+
satoshis = 0;
78+
addressType = 0;
79+
addressHash.SetNull();
80+
}
81+
82+
bool IsNull() const {
83+
return txid.IsNull();
84+
}
85+
};
86+
87+
struct CSpentIndexKeyCompare
88+
{
89+
bool operator()(const CSpentIndexKey& a, const CSpentIndexKey& b) const {
90+
if (a.txid == b.txid) {
91+
return a.outputIndex < b.outputIndex;
92+
} else {
93+
return a.txid < b.txid;
94+
}
95+
}
96+
};
97+
98+
#endif // BITCOIN_SPENTINDEX_H

src/txmempool.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,71 @@ bool CTxMemPool::removeAddressIndex(const uint256 txhash)
491491
return true;
492492
}
493493

494+
void CTxMemPool::addSpentIndex(const CTxMemPoolEntry &entry, const CCoinsViewCache &view)
495+
{
496+
LOCK(cs);
497+
498+
const CTransaction& tx = entry.GetTx();
499+
std::vector<CSpentIndexKey> inserted;
500+
501+
uint256 txhash = tx.GetHash();
502+
for (unsigned int j = 0; j < tx.vin.size(); j++) {
503+
const CTxIn input = tx.vin[j];
504+
const CTxOut &prevout = view.GetOutputFor(input);
505+
uint160 addressHash;
506+
int addressType;
507+
508+
if (prevout.scriptPubKey.IsPayToScriptHash()) {
509+
addressHash = uint160(vector<unsigned char> (prevout.scriptPubKey.begin()+2, prevout.scriptPubKey.begin()+22));
510+
addressType = 2;
511+
} else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) {
512+
addressHash = uint160(vector<unsigned char> (prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23));
513+
addressType = 1;
514+
} else {
515+
addressHash.SetNull();
516+
addressType = 0;
517+
}
518+
519+
CSpentIndexKey key = CSpentIndexKey(input.prevout.hash, input.prevout.n);
520+
CSpentIndexValue value = CSpentIndexValue(txhash, j, -1, prevout.nValue, addressType, addressHash);
521+
522+
mapSpent.insert(make_pair(key, value));
523+
inserted.push_back(key);
524+
525+
}
526+
527+
mapSpentInserted.insert(make_pair(txhash, inserted));
528+
}
529+
530+
bool CTxMemPool::getSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value)
531+
{
532+
LOCK(cs);
533+
mapSpentIndex::iterator it;
534+
535+
it = mapSpent.find(key);
536+
if (it != mapSpent.end()) {
537+
value = it->second;
538+
return true;
539+
}
540+
return false;
541+
}
542+
543+
bool CTxMemPool::removeSpentIndex(const uint256 txhash)
544+
{
545+
LOCK(cs);
546+
mapSpentIndexInserted::iterator it = mapSpentInserted.find(txhash);
547+
548+
if (it != mapSpentInserted.end()) {
549+
std::vector<CSpentIndexKey> keys = (*it).second;
550+
for (std::vector<CSpentIndexKey>::iterator mit = keys.begin(); mit != keys.end(); mit++) {
551+
mapSpent.erase(*mit);
552+
}
553+
mapSpentInserted.erase(it);
554+
}
555+
556+
return true;
557+
}
558+
494559
void CTxMemPool::removeUnchecked(txiter it)
495560
{
496561
const uint256 hash = it->GetTx().GetHash();
@@ -505,6 +570,7 @@ void CTxMemPool::removeUnchecked(txiter it)
505570
nTransactionsUpdated++;
506571
minerPolicyEstimator->removeTx(hash);
507572
removeAddressIndex(hash);
573+
removeSpentIndex(hash);
508574
}
509575

510576
// Calculates descendants of entry that are not already in setDescendants, and adds to

src/txmempool.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <set>
1111

1212
#include "addressindex.h"
13+
#include "spentindex.h"
1314
#include "amount.h"
1415
#include "coins.h"
1516
#include "primitives/transaction.h"
@@ -396,6 +397,12 @@ class CTxMemPool
396397
typedef std::map<uint256, std::vector<CMempoolAddressDeltaKey> > addressDeltaMapInserted;
397398
addressDeltaMapInserted mapAddressInserted;
398399

400+
typedef std::map<CSpentIndexKey, CSpentIndexValue, CSpentIndexKeyCompare> mapSpentIndex;
401+
mapSpentIndex mapSpent;
402+
403+
typedef std::map<uint256, std::vector<CSpentIndexKey> > mapSpentIndexInserted;
404+
mapSpentIndexInserted mapSpentInserted;
405+
399406
void UpdateParent(txiter entry, txiter parent, bool add);
400407
void UpdateChild(txiter entry, txiter child, bool add);
401408

@@ -432,6 +439,10 @@ class CTxMemPool
432439
std::vector<std::pair<CMempoolAddressDeltaKey, CMempoolAddressDelta> > &results);
433440
bool removeAddressIndex(const uint256 txhash);
434441

442+
void addSpentIndex(const CTxMemPoolEntry &entry, const CCoinsViewCache &view);
443+
bool getSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value);
444+
bool removeSpentIndex(const uint256 txhash);
445+
435446
void remove(const CTransaction &tx, std::list<CTransaction>& removed, bool fRecursive = false);
436447
void removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags);
437448
void removeConflicts(const CTransaction &tx, std::list<CTransaction>& removed);

0 commit comments

Comments
 (0)