Skip to content

Commit 2e06091

Browse files
committed
Merge pull request #107 from matiu/bug/fix-double-spent2
Bug/fix double spent2
2 parents 4dabb9f + 7becad0 commit 2e06091

File tree

6 files changed

+51
-28
lines changed

6 files changed

+51
-28
lines changed

README.md

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,16 @@ Alternatively, a total resync can be made, running `$ util/sync.js -D`
2626
## IMPORTANT: v0.2 Caching schema
2727

2828
In v0.2 a new cache schema has been introduced. Only information from transactions with
29-
SAFE_CONFIRMATIONS+ settings will be cached (by default SAFE_CONFIRMATIONS=6). There
29+
INSIGHT_SAFE_CONFIRMATIONS+ settings will be cached (by default SAFE_CONFIRMATIONS=6). There
3030
are 3 different caches:
3131
* nr. of confirmations
3232
* transaction spent information
3333
* scriptPubKey for unspent transactions
3434

35-
Cache data is only completed on request, i.e., only after accessing the required data for
36-
the first time, the information is cached, there is not pre-caching procedure.
35+
Cache data is only populated on request, i.e., only after accessing the required data for
36+
the first time, the information is cached, there is not pre-caching procedure. To ignore
37+
cache by default, use INSIGHT_IGNORE_CACHE. Also, address related calls support `?noCache=1`
38+
to ignore the cache in a particular API request.
3739

3840
## Prerequisites
3941

@@ -91,7 +93,9 @@ BITCOIND_PASS # RPC password
9193
BITCOIND_DATADIR # bitcoind datadir for livenet, or datadir/testnet3 for testnet
9294
INSIGHT_NETWORK [= 'livenet' | 'testnet']
9395
INSIGHT_DB # Path where to store insight's internal DB. (defaults to $HOME/.insight)
94-
SAFE_CONFIRMATIONS=6 # Nr. of confirmation needed to start caching transaction information
96+
INSIGHT_SAFE_CONFIRMATIONS=6 # Nr. of confirmation needed to start caching transaction information
97+
INSIGHT_IGNORE_CACHE # True to ignore cache of spents in transaction, with more than INSIGHT_SAFE_CONFIRMATIONS confirmations. This is useful for tracking double spents for old transactions.
98+
9599
```
96100

97101
Make sure that bitcoind is configured to [accept incoming connections using 'rpcallowip'](https://en.bitcoin.it/wiki/Running_Bitcoin).
@@ -163,12 +167,12 @@ The end-points are:
163167
```
164168
### Address
165169
```
166-
/api/addr/[:addr][?noTxList=1]
170+
/api/addr/[:addr][?noTxList=1&noCache=1]
167171
/api/addr/mmvP3mTe53qxHdPqXEvdu8WdC7GfQ2vmx5?noTxList=1
168172
```
169173
### Unspent Outputs
170174
```
171-
/api/addr/[:addr]/utxo
175+
/api/addr/[:addr]/utxo[?noCache=1]
172176
```
173177
Sample return:
174178
``` json
@@ -193,8 +197,8 @@ Sample return:
193197
}
194198
]
195199
```
196-
Please not that in case confirmations are cached and are more that SAFE_CONFIRMATIONS setting, the
197-
return can be a string of the form 'SAFE_CONFIRMATIONS+'
200+
Please not that in case confirmations are cached and are more that INSIGHT_SAFE_CONFIRMATIONS setting, the
201+
return can be a string of the form `SAFE_CONFIRMATIONS+`, e.g.: the string `6+`
198202
199203
200204
### Unspent Outputs for multiple addresses

app/controllers/addresses.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ exports.show = function(req, res, next) {
5353
} else {
5454
return res.jsonp(a.getObj());
5555
}
56-
}, {txLimit: req.query.noTxList?0:-1});
56+
}, {txLimit: req.query.noTxList?0:-1, ignoreCache: req.param('noCache')});
5757
}
5858
};
5959

@@ -68,7 +68,7 @@ exports.utxo = function(req, res, next) {
6868
else {
6969
return res.jsonp(a.unspent);
7070
}
71-
}, {onlyUnspent: 1});
71+
}, {onlyUnspent:1, ignoreCache: req.param('noCache')});
7272
}
7373
};
7474

@@ -81,7 +81,7 @@ exports.multiutxo = function(req, res, next) {
8181
if (err) callback(err);
8282
utxos = utxos.concat(a.unspent);
8383
callback();
84-
}, {onlyUnspent:1});
84+
}, {onlyUnspent:1, ignoreCache: req.param('noCache')});
8585
}, function(err) { // finished callback
8686
if (err) return common.handleErrors(err, res);
8787
res.jsonp(utxos);
@@ -99,7 +99,7 @@ exports.balance = function(req, res, next) {
9999
} else {
100100
return res.jsonp(a.balanceSat);
101101
}
102-
});
102+
}, {ignoreCache: req.param('noCache')});
103103
};
104104

105105
exports.totalReceived = function(req, res, next) {
@@ -111,7 +111,7 @@ exports.totalReceived = function(req, res, next) {
111111
} else {
112112
return res.jsonp(a.totalReceivedSat);
113113
}
114-
});
114+
}, {ignoreCache: req.param('noCache')});
115115
};
116116

117117
exports.totalSent = function(req, res, next) {
@@ -123,7 +123,7 @@ exports.totalSent = function(req, res, next) {
123123
} else {
124124
return res.jsonp(a.totalSentSat);
125125
}
126-
});
126+
}, {ignoreCache: req.param('noCache')});
127127
};
128128

129129
exports.unconfirmedBalance = function(req, res, next) {
@@ -135,5 +135,5 @@ exports.unconfirmedBalance = function(req, res, next) {
135135
} else {
136136
return res.jsonp(a.unconfirmedBalanceSat);
137137
}
138-
});
138+
}, {ignoreCache: req.param('noCache')});
139139
};

app/models/Address.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,15 @@ Address.prototype.update = function(next, opts) {
149149
if (!self.addrStr) return next();
150150
opts = opts || {};
151151

152+
if (! ('ignoreCache' in opts) )
153+
opts.ignoreCache = config.ignoreCache;
154+
155+
// should collect txList from address?
152156
var txList = opts.txLimit === 0 ? null: [];
157+
153158
var tDb = TransactionDb;
154159
var bDb = BlockDb;
155-
tDb.fromAddr(self.addrStr, function(err,txOut){
160+
tDb.fromAddr(self.addrStr, opts, function(err,txOut){
156161
if (err) return next(err);
157162

158163
bDb.fillConfirmations(txOut, function(err) {
@@ -184,7 +189,9 @@ Address.prototype.update = function(next, opts) {
184189
txOut.forEach(function(txItem){
185190
self._addTxItem(txItem, txList);
186191
});
187-
if (txList) self.transactions = txList;
192+
if (txList)
193+
self.transactions = txList;
194+
188195
return next();
189196
}
190197
});

config/config.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ if (!dataDir) {
6060
}
6161
dataDir += network === 'testnet' ? 'testnet3' : '';
6262

63-
var safeConfirmations = process.env.SAFE_CONFIRMATIONS || 6;
63+
var safeConfirmations = process.env.INSIGHT_SAFE_CONFIRMATIONS || 6;
64+
var ignoreCache = process.env.INSIGHT_IGNORE_CACHE || 0;
6465

6566

6667
var bitcoindConf = {
@@ -88,7 +89,8 @@ console.log(
8889
# Configuration:\n\
8990
\t\tNetwork: %s\tINSIGHT_NETWORK\n\
9091
\t\tDatabase Path: %s\tINSIGHT_DB\n\
91-
\t\tSafe Confirmations: %s\tSAFE_CONFIRMATIONS\n\
92+
\t\tSafe Confirmations: %s\tINSIGHT_SAFE_CONFIRMATIONS\n\
93+
\t\tIgnore Cache: %s\tINSIGHT_IGNORE_CACHE\n\
9294
# Bicoind Connection configuration:\n\
9395
\t\tRPC Username: %s\tBITCOIND_USER\n\
9496
\t\tRPC Password: %s\tBITCOIND_PASS\n\
@@ -102,7 +104,7 @@ console.log(
102104
$ INSIGHT_NETWORK="testnet" BITCOIND_HOST="123.123.123.123" ./insight.js\
103105
\n\n',
104106
version,
105-
network, home, safeConfirmations,
107+
network, home, safeConfirmations, ignoreCache?'yes':'no',
106108
bitcoindConf.user,
107109
bitcoindConf.pass?'Yes(hidden)':'No',
108110
bitcoindConf.protocol,
@@ -139,4 +141,5 @@ module.exports = {
139141
segmentio: process.env.INSIGHT_SEGMENTIO_KEY
140142
},
141143
safeConfirmations: safeConfirmations, // PLEASE NOTE THAT *FULL RESYNC* IS NEEDED TO CHANGE safeConfirmations
144+
ignoreCache: ignoreCache,
142145
};

lib/TransactionDb.js

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -201,15 +201,13 @@ TransactionDb.prototype._fillOutpoints = function(txInfo, cb) {
201201
i.value = ret.valueSat / util.COIN;
202202
valueIn += i.valueSat;
203203

204-
console.log('[TransactionDb.js.204:ret:]',ret); //TODO
205204
if (ret.multipleSpentAttempt || !ret.spentTxId ||
206205
(ret.spentTxId && ret.spentTxId !== txInfo.txid)
207206
) {
208207
if (ret.multipleSpentAttempts) {
209208
ret.multipleSpentAttempts.forEach(function(mul) {
210209
if (mul.spentTxId !== txInfo.txid) {
211210

212-
console.log('[TransactionDb.js.210]'); //TODO
213211
i.doubleSpentTxID = ret.spentTxId;
214212
i.doubleSpentIndex = ret.spentIndex;
215213
}
@@ -218,7 +216,6 @@ console.log('[TransactionDb.js.210]'); //TODO
218216
i.dbError = 'Input spent not registered';
219217
} else {
220218

221-
console.log('[TransactionDb.js.219]'); //TODO
222219
i.doubleSpentTxID = ret.spentTxId;
223220
i.doubleSpentIndex = ret.spentIndex;
224221
}
@@ -409,7 +406,7 @@ TransactionDb.prototype.cacheScriptPubKey = function(txouts,cb) {
409406

410407

411408

412-
TransactionDb.prototype._parseAddrData = function(data) {
409+
TransactionDb.prototype._parseAddrData = function(data, ignoreCache) {
413410
var k = data.key.split('-');
414411
var v = data.value.split(':');
415412
// console.log('[TransactionDb.js.375]',data.key,data.value); //TODO
@@ -425,7 +422,7 @@ TransactionDb.prototype._parseAddrData = function(data) {
425422
// v[1]== isConfirmedCached
426423
// v[2]=== '1' -> is SpendCached -> [4]=spendTxId [5]=spentIndex [6]=spendTs
427424
// v[3]!== '1' -> is ScriptPubkey -> [[3] = scriptPubkey
428-
if (v[1]){
425+
if (v[1] && !ignoreCache){
429426
item.isConfirmed = 1;
430427
item.isConfirmedCached = 1;
431428
// console.log('[TransactionDb.js.356] CACHE HIT CONF:', item.key); //TODO
@@ -448,18 +445,19 @@ TransactionDb.prototype._parseAddrData = function(data) {
448445
return item;
449446
};
450447

451-
TransactionDb.prototype.fromAddr = function(addr, cb, txLimit) {
448+
TransactionDb.prototype.fromAddr = function(addr, opts, cb) {
449+
opts = opts || {};
452450
var self = this;
453451
var k = ADDR_PREFIX + addr + '-';
454452
var ret = [];
455453

456454
db.createReadStream({
457455
start: k,
458456
end: k + '~',
459-
limit: txLimit>0 ? txLimit: -1, // -1 means not limit
457+
limit: opts.txLimit>0 ? opts.txLimit: -1, // -1 means not limit
460458
})
461459
.on('data', function(data) {
462-
ret.push(self._parseAddrData(data));
460+
ret.push(self._parseAddrData(data, opts.ignoreCache));
463461
})
464462
.on('error', cb)
465463
.on('end', function() {

test/integration/addrCache.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,17 @@ describe('Address cache ', function() {
9393
return done();
9494
},{txLimit:0});
9595
});
96+
it('cache case 2 w ignore cache', function(done) {
97+
var a = new Address('mt2AzeCorSf7yFckj19HFiXJgh9aNyc4h3', txDb);
98+
a.update(function(err) {
99+
if (err) done(err);
100+
a.balance.should.equal(0, 'balance');
101+
a.totalReceived.should.equal(1376000, 'totalReceived');
102+
a.txApperances.should.equal(8003, 'txApperances');
103+
return done();
104+
},{txLimit:0, ignoreCache:1});
105+
});
106+
96107
});
97108

98109

0 commit comments

Comments
 (0)