fix working for spent, also in var names

This commit is contained in:
Matias Alejo Garcia 2014-02-16 13:38:34 -03:00
parent a4626f97eb
commit f69f210abf
5 changed files with 72 additions and 70 deletions

View File

@ -85,18 +85,18 @@ function spec() {
txs.push({txid: txItem.txid, ts: txItem.ts}); txs.push({txid: txItem.txid, ts: txItem.ts});
if (txItem.spendTxId) { if (txItem.spentTxId) {
txs.push({txid: txItem.spendTxId, ts: txItem.spendTs}); txs.push({txid: txItem.spentTxId, ts: txItem.spentTs});
} }
if (txItem.isConfirmed) { if (txItem.isConfirmed) {
self.txApperances += 1; self.txApperances += 1;
self.totalReceivedSat += v; self.totalReceivedSat += v;
if (! txItem.spendTxId ) { if (! txItem.spentTxId ) {
//unspend //unspent
self.balanceSat += v; self.balanceSat += v;
} }
else if(!txItem.spendIsConfirmed) { else if(!txItem.spentIsConfirmed) {
// unspent // unspent
self.balanceSat += v; self.balanceSat += v;
self.unconfirmedBalanceSat -= v; self.unconfirmedBalanceSat -= v;

View File

@ -14,9 +14,9 @@ function spec(b) {
// to show tx outs // to show tx outs
var OUTS_PREFIX = 'txo-'; //txo-<txid>-<n> => [addr, btc_sat] var OUTS_PREFIX = 'txo-'; //txo-<txid>-<n> => [addr, btc_sat]
var SPEND_PREFIX = 'txs-'; //txs-<txid(out)>-<n(out)>-<txid(in)>-<n(in)> = ts var SPENT_PREFIX = 'txs-'; //txs-<txid(out)>-<n(out)>-<txid(in)>-<n(in)> = ts
// to sum up addr balance (only outs, spends are gotten later) // to sum up addr balance (only outs, spents are gotten later)
var ADDR_PREFIX = 'txa-'; //txa-<addr>-<txid>-<n> => + btc_sat:ts var ADDR_PREFIX = 'txa-'; //txa-<addr>-<txid>-<n> => + btc_sat:ts
// TODO: use bitcore networks module // TODO: use bitcore networks module
@ -24,7 +24,7 @@ function spec(b) {
var CONCURRENCY = 10; var CONCURRENCY = 10;
var MAX_OPEN_FILES = 500; var MAX_OPEN_FILES = 500;
var CONFIRMATION_NR_TO_NOT_CHECK = 10; // var CONFIRMATION_NR_TO_NOT_CHECK = 10; //Spend
/** /**
* Module dependencies. * Module dependencies.
*/ */
@ -89,22 +89,22 @@ function spec(b) {
}); });
}; };
TransactionDb.prototype._addSpendInfo = function(r, txid, index, ts) { TransactionDb.prototype._addSpentInfo = function(r, txid, index, ts) {
if (r.spendTxId) { if (r.spentTxId) {
if (!r.multipleSpendAttempts) { if (!r.multipleSpentAttempts) {
r.multipleSpendAttempts = [{ r.multipleSpentAttempts = [{
txid: r.spendTxId, txid: r.spentTxId,
index: r.index, index: r.index,
}]; }];
} }
r.multipleSpendAttempts.push({ r.multipleSpentAttempts.push({
txid: txid, txid: txid,
index: parseInt(index), index: parseInt(index),
}); });
} else { } else {
r.spendTxId = txid; r.spentTxId = txid;
r.spendIndex = parseInt(index); r.spentIndex = parseInt(index);
r.spendTs = parseInt(ts); r.spentTs = parseInt(ts);
} }
}; };
@ -137,7 +137,7 @@ function spec(b) {
}) })
.on('end', function() { .on('end', function() {
var k = SPEND_PREFIX + txid; var k = SPENT_PREFIX + txid;
db.createReadStream({ db.createReadStream({
start: k, start: k,
end: k + '~' end: k + '~'
@ -147,9 +147,9 @@ function spec(b) {
var j = idx[parseInt(k[2])]; var j = idx[parseInt(k[2])];
assert(typeof j !== 'undefined', 'Spent could not be stored: tx ' + txid + assert(typeof j !== 'undefined', 'Spent could not be stored: tx ' + txid +
'spend in TX:' + k[1] + ',' + k[2] + ' j:' + j); 'spent in TX:' + k[1] + ',' + k[2] + ' j:' + j);
self._addSpendInfo(ret[j], k[3], k[4], data.value); self._addSpentInfo(ret[j], k[3], k[4], data.value);
}) })
.on('error', function(err) { .on('error', function(err) {
return cb(err); return cb(err);
@ -161,19 +161,19 @@ function spec(b) {
}; };
TransactionDb.prototype._fillSpend = function(info, cb) { TransactionDb.prototype._fillSpent = function(info, cb) {
var self = this; var self = this;
if (!info) return cb(); if (!info) return cb();
var k = SPEND_PREFIX + info.txid; var k = SPENT_PREFIX + info.txid;
db.createReadStream({ db.createReadStream({
start: k, start: k,
end: k + '~' end: k + '~'
}) })
.on('data', function(data) { .on('data', function(data) {
var k = data.key.split('-'); var k = data.key.split('-');
self._addSpendInfo(info.vout[k[2]], k[3], k[4], data.value); self._addSpentInfo(info.vout[k[2]], k[3], k[4], data.value);
}) })
.on('error', function(err) { .on('error', function(err) {
return cb(err); return cb(err);
@ -202,7 +202,7 @@ function spec(b) {
return c_in(); // error not scalated return c_in(); // error not scalated
} }
info.firstSeenTs = ret.spendTs; info.firstSeenTs = ret.spentTs;
i.unconfirmedInput = i.unconfirmedInput; i.unconfirmedInput = i.unconfirmedInput;
i.addr = ret.addr; i.addr = ret.addr;
i.valueSat = ret.valueSat; i.valueSat = ret.valueSat;
@ -210,32 +210,33 @@ function spec(b) {
valueIn += i.valueSat; valueIn += i.valueSat;
/* /*
* If confirmed by bitcoind, we could not check for double spends * If confirmed by bitcoind, we could not check for double spents
* but we prefer to keep the flag of double spend attempt * but we prefer to keep the flag of double spent attempt
* *
if (info.confirmations if (info.confirmations
&& info.confirmations >= CONFIRMATION_NR_TO_NOT_CHECK) && info.confirmations >= CONFIRMATION_NR_TO_NOT_CHECK)
return c_in(); return c_in();
isspent
*/ */
// Double spend? // Double spent?
if (ret.multipleSpendAttempt || !ret.spendTxId || if (ret.multipleSpentAttempt || !ret.spentTxId ||
(ret.spendTxId && ret.spendTxId !== info.txid) (ret.spentTxId && ret.spentTxId !== info.txid)
) { ) {
if (ret.multipleSpendAttempts) { if (ret.multipleSpentAttempts) {
ret.multipleSpendAttempts.each(function(mul) { ret.multipleSpentAttempts.each(function(mul) {
if (mul.spendTxId !== info.txid) { if (mul.spentTxId !== info.txid) {
i.doubleSpendTxID = ret.spendTxId; i.doubleSpentTxID = ret.spentTxId;
i.doubleSpendIndex = ret.spendIndex; i.doubleSpentIndex = ret.spentIndex;
} }
}); });
} else if (!ret.spendTxId) { } else if (!ret.spentTxId) {
i.dbError = 'Input spend not registered'; i.dbError = 'Input spent not registered';
} else { } else {
i.doubleSpendTxID = ret.spendTxId; i.doubleSpentTxID = ret.spentTxId;
i.doubleSpendIndex = ret.spendIndex; i.doubleSpentIndex = ret.spentIndex;
} }
} else { } else {
i.doubleSpendTxID = null; i.doubleSpentTxID = null;
} }
return c_in(); return c_in();
}); });
@ -258,7 +259,7 @@ function spec(b) {
if (err) return next(err); if (err) return next(err);
self._fillOutpoints(info, function() { self._fillOutpoints(info, function() {
self._fillSpend(info, function() { self._fillSpent(info, function() {
return next(null, info); return next(null, info);
}); });
}); });
@ -272,6 +273,7 @@ function spec(b) {
self._getInfo(txid, function(err, info) { self._getInfo(txid, function(err, info) {
if (err) return cb(err); if (err) return cb(err);
if (!info) return cb(); if (!info) return cb();
//console.log('[TransactionDb.js.278:info:]',info); //TODO
return cb(err, { return cb(err, {
txid: txid, txid: txid,
info: info info: info
@ -299,7 +301,7 @@ function spec(b) {
/* /*
* If this TxID comes from an RPC request * If this TxID comes from an RPC request
* the .confirmations value from bitcoind is available * the .confirmations value from bitcoind is available
* so we could avoid checking if the input were double spended * so we could avoid checking if the input were double spented
* *
* This speed up address calculations by ~30% * This speed up address calculations by ~30%
* *
@ -308,15 +310,15 @@ function spec(b) {
} }
*/ */
// Spend? // spent?
var k = SPEND_PREFIX + txid + '-' + n; var k = SPENT_PREFIX + txid + '-' + n;
db.createReadStream({ db.createReadStream({
start: k, start: k,
end: k + '~' end: k + '~'
}) })
.on('data', function(data) { .on('data', function(data) {
var k = data.key.split('-'); var k = data.key.split('-');
self._addSpendInfo(ret, k[3], k[4], data.value); self._addSpentInfo(ret, k[3], k[4], data.value);
}) })
.on('error', function(error) { .on('error', function(error) {
return cb(error); return cb(error);
@ -334,26 +336,26 @@ function spec(b) {
if (err) return cb(err); if (err) return cb(err);
o.isConfirmed = is; o.isConfirmed = is;
if (!o.spendTxId) return cb(); if (!o.spentTxId) return cb();
if (o.multipleSpendAttempts) { if (o.multipleSpentAttempts) {
async.eachLimit(o.multipleSpendAttempts, CONCURRENCY, async.eachLimit(o.multipleSpentAttempts, CONCURRENCY,
function(oi, e_c) { function(oi, e_c) {
self.isConfirmed(oi.spendTxId, function(err, is) { self.isConfirmed(oi.spentTxId, function(err, is) {
if (err) return; if (err) return;
if (is) { if (is) {
o.spendTxId = oi.spendTxId; o.spentTxId = oi.spentTxId;
o.index = oi.index; o.index = oi.index;
o.spendIsConfirmed = 1; o.spentIsConfirmed = 1;
} }
return e_c(); return e_c();
}); });
}, cb); }, cb);
} else { } else {
self.isConfirmed(o.spendTxId, function(err, is) { self.isConfirmed(o.spentTxId, function(err, is) {
if (err) return cb(err); if (err) return cb(err);
o.spendIsConfirmed = is; o.spentIsConfirmed = is;
return cb(); return cb();
}); });
} }
@ -386,14 +388,14 @@ function spec(b) {
.on('end', function() { .on('end', function() {
async.eachLimit(ret, CONCURRENCY, function(o, e_c) { async.eachLimit(ret, CONCURRENCY, function(o, e_c) {
var k = SPEND_PREFIX + o.txid + '-' + o.index; var k = SPENT_PREFIX + o.txid + '-' + o.index;
db.createReadStream({ db.createReadStream({
start: k, start: k,
end: k + '~' end: k + '~'
}) })
.on('data', function(data) { .on('data', function(data) {
var k = data.key.split('-'); var k = data.key.split('-');
self._addSpendInfo(o, k[3], k[4], data.value); self._addSpentInfo(o, k[3], k[4], data.value);
}) })
.on('error', function(err) { .on('error', function(err) {
return e_c(err); return e_c(err);
@ -430,8 +432,8 @@ function spec(b) {
}, },
function(c) { function(c) {
db.createReadStream({ db.createReadStream({
start: SPEND_PREFIX + txid, start: SPENT_PREFIX + txid,
end: SPEND_PREFIX + txid + '~' end: SPENT_PREFIX + txid + '~'
}) })
.pipe( .pipe(
db.createWriteStream({ db.createWriteStream({
@ -553,7 +555,7 @@ function spec(b) {
async.forEachLimit(tx.vin, CONCURRENCY, async.forEachLimit(tx.vin, CONCURRENCY,
function(i, next_out) { function(i, next_out) {
db.batch() db.batch()
.put(SPEND_PREFIX + i.txid + '-' + i.vout + '-' + tx.txid + '-' + i.n, .put(SPENT_PREFIX + i.txid + '-' + i.vout + '-' + tx.txid + '-' + i.n,
ts || 0) ts || 0)
.write(next_out); .write(next_out);
}, },

View File

@ -52,10 +52,10 @@ function($scope, $rootScope, $routeParams, $location, Global, Transaction, Trans
tmp[addr].addr = addr; tmp[addr].addr = addr;
tmp[addr].items = []; tmp[addr].items = [];
} }
tmp[addr].isSpend = items[i].spendTxId; tmp[addr].isSpent = items[i].spentTxId;
tmp[addr].doubleSpendTxID = tmp[addr].doubleSpendTxID || items[i].doubleSpendTxID; tmp[addr].doubleSpentTxID = tmp[addr].doubleSpentTxID || items[i].doubleSpentTxID;
tmp[addr].doubleSpendIndex = tmp[addr].doubleSpendIndex || items[i].doubleSpendIndex; tmp[addr].doubleSpentIndex = tmp[addr].doubleSpentIndex || items[i].doubleSpentIndex;
tmp[addr].unconfirmedInput += items[i].unconfirmedInput; tmp[addr].unconfirmedInput += items[i].unconfirmedInput;
tmp[addr].dbError = tmp[addr].dbError || items[i].dbError; tmp[addr].dbError = tmp[addr].dbError || items[i].dbError;
tmp[addr].valueSat += items[i].value * COIN; tmp[addr].valueSat += items[i].value * COIN;

View File

@ -36,8 +36,8 @@
</div> </div>
<div data-ng-show="vin.unconfirmedInput" class="text-danger"> <span class="glyphicon glyphicon-warning-sign"></span> (Input unconfirmed)</div> <div data-ng-show="vin.unconfirmedInput" class="text-danger"> <span class="glyphicon glyphicon-warning-sign"></span> (Input unconfirmed)</div>
<div data-ng-show="vin.dbError" class="text-danger"> <span class="glyphicon glyphicon-warning-sign"></span> Incoherence in levelDB detected, please resync</div> <div data-ng-show="vin.dbError" class="text-danger"> <span class="glyphicon glyphicon-warning-sign"></span> Incoherence in levelDB detected, please resync</div>
<div data-ng-show="vin.doubleSpendTxID" class="text-danger"> <span class="glyphicon glyphicon-warning-sign"></span> Double spend attempt detected. From tx: <div data-ng-show="vin.doubleSpentTxID" class="text-danger"> <span class="glyphicon glyphicon-warning-sign"></span> Double spent attempt detected. From tx:
<a href="/tx/{{vin.doubleSpendTxID}}">{{vin.doubleSpendTxID}},{{vin.doubleSpendIndex}}</a> <a href="/tx/{{vin.doubleSpentTxID}}">{{vin.doubleSpentTxID}},{{vin.doubleSpentIndex}}</a>
</div> </div>
</div> </div>
</div> </div>
@ -51,8 +51,8 @@
</div> </div>
<div data-ng-show="vin.unconfirmedInput" class="text-danger"> <span class="glyphicon glyphicon-warning-sign"></span> (Input unconfirmed)</div> <div data-ng-show="vin.unconfirmedInput" class="text-danger"> <span class="glyphicon glyphicon-warning-sign"></span> (Input unconfirmed)</div>
<div data-ng-show="vin.dbError" class="text-danger"> <span class="glyphicon glyphicon-warning-sign"></span> Incoherence in levelDB detected, please resync</div> <div data-ng-show="vin.dbError" class="text-danger"> <span class="glyphicon glyphicon-warning-sign"></span> Incoherence in levelDB detected, please resync</div>
<div data-ng-show="vin.doubleSpendTxID" class="text-danger"> <span class="glyphicon glyphicon-warning-sign"></span> Double spend attempt detected. From tx: <div data-ng-show="vin.doubleSpentTxID" class="text-danger"> <span class="glyphicon glyphicon-warning-sign"></span> Double spent attempt detected. From tx:
<a href="/tx/{{vin.doubleSpendTxID}}">{{vin.doubleSpendTxID}},{{vin.doubleSpendIndex}}</a> <a href="/tx/{{vin.doubleSpentTxID}}">{{vin.doubleSpentTxID}},{{vin.doubleSpentIndex}}</a>
</div> </div>
</div> </div>
@ -83,8 +83,8 @@
<small> <small>
{{$root.currency.getConvertion(vout.value)}} {{$root.currency.getConvertion(vout.value)}}
<span class="text-danger" data-ng-show="vout.isSpend" tooltip="Output is spend" tooltip-placement="left">(S)</span> <span class="text-danger" data-ng-show="vout.isSpent" tooltip="Output is spent" tooltip-placement="left">(S)</span>
<span class="text-success" data-ng-show="!vout.isSpend" tooltip="Output is unspend" tooltip-placement="left">(U)</span> <span class="text-success" data-ng-show="!vout.isSpent" tooltip="Output is unspent" tooltip-placement="left">(U)</span>
</small> </small>
</div> </div>
@ -100,8 +100,8 @@
<div data-ng-repeat="vout in tx.vout" data-ng-show="itemsExpanded"> <div data-ng-repeat="vout in tx.vout" data-ng-show="itemsExpanded">
<div class="col-md-12 transaction-vin-vout"> <div class="col-md-12 transaction-vin-vout">
<div class="text-muted pull-right btc-value"><small>{{$root.currency.getConvertion(vout.value)}} <div class="text-muted pull-right btc-value"><small>{{$root.currency.getConvertion(vout.value)}}
<span class="text-success" data-ng-show="!vout.spendTxId" tooltip="Output is unspend" tooltip-placement="left">(U)</span> <span class="text-success" data-ng-show="!vout.spentTxId" tooltip="Output is unspent" tooltip-placement="left">(U)</span>
<a class="glyphicon glyphicon-chevron-right" data-ng-show="vout.spendTxId" href="/#!/tx/{{vout.spendTxId}}" title="Spent at: {{vout.spendTxId}},{{vout.spendIndex}}"></a>&nbsp;&nbsp; <a class="glyphicon glyphicon-chevron-right" data-ng-show="vout.spentTxId" href="/#!/tx/{{vout.spentTxId}}" title="Spent at: {{vout.spentTxId}},{{vout.spentIndex}}"></a>&nbsp;&nbsp;
</small> </small>

View File

@ -48,8 +48,8 @@ describe('TransactionDb Expenses', function(){
var c=0; var c=0;
txDb.fromTxId( txid, function(err, readItems) { txDb.fromTxId( txid, function(err, readItems) {
s.forEach( function(v) { s.forEach( function(v) {
assert.equal(readItems[c].spendTxId,v.txid); assert.equal(readItems[c].spentTxId,v.txid);
assert.equal(readItems[c].spendIndex,v.n); assert.equal(readItems[c].spentIndex,v.n);
c++; c++;
}); });
done(); done();