diff --git a/app/controllers/addresses.js b/app/controllers/addresses.js index 30671ee1..95e49c1d 100644 --- a/app/controllers/addresses.js +++ b/app/controllers/addresses.js @@ -7,7 +7,6 @@ var Address = require('../models/Address'), common = require('./common'); - exports.address = function(req, res, next, addr) { diff --git a/dev-util/level-put.js b/dev-util/level-put.js new file mode 100755 index 00000000..45cdb310 --- /dev/null +++ b/dev-util/level-put.js @@ -0,0 +1,34 @@ +#!/usr/bin/env node +'use strict'; + +var config = require('../config/config'), + levelup = require('levelup'); + + + +var k = process.argv[2]; +var v = process.argv[3]; +var isBlock = process.argv[4] === '1'; + + +var dbPath = config.leveldb + (isBlock ? '/blocks' : '/txs'); +console.log('DB: ',dbPath); //TODO + + + +var db = levelup(dbPath ); + + +if (v) { + db.put(k,v,function(err) { + console.log('[PUT done]',err); //TODO + }); +} +else { + db.del(k,function(err) { + console.log('[DEL done]',err); //TODO + }); +} + + + diff --git a/insight.js b/insight.js index 9689c0f6..fc0969fe 100644 --- a/insight.js +++ b/insight.js @@ -40,9 +40,6 @@ var walk = function(path) { walk(models_path); -var syncOpts = { -}; - /** * p2pSync process */ diff --git a/lib/TransactionDb.js b/lib/TransactionDb.js index 3f043319..5eb1a5bc 100644 --- a/lib/TransactionDb.js +++ b/lib/TransactionDb.js @@ -51,7 +51,6 @@ function spec(b) { }; -// TransactionDb.prototype.fromTxIdOne = function(txid, cb) { TODO TransactionDb.prototype.has = function(txid, cb) { var k = OUTS_PREFIX + txid; @@ -142,18 +141,46 @@ function spec(b) { var valueIn = 0; var incompleteInputs = 0; + async.eachLimit(info.vin, CONCURRENCY, function(i, c_in) { - self.fromTxIdN(i.txid, i.vout, function(err, addr, valueSat) { - - - if (err || !addr || !valueSat ) { + self.fromTxIdN(i.txid, i.vout, function(err, ret) { + //console.log('[TransactionDb.js.154:ret:]',ret); //TODO + if (!ret || !ret.addr || !ret.valueSat ) { console.log('Could not get TXouts in %s,%d from %s ', i.txid, i.vout, info.txid); + if (ret) i.unconfirmedInput = ret.unconfirmedInput; incompleteInputs = 1; return c_in(); // error not scalated } - i.addr = addr; - i.valueSat = valueSat; - i.value = valueSat / util.COIN; + + i.unconfirmedInput = i.unconfirmedInput; + i.addr = ret.addr; + i.valueSat = ret.valueSat; + i.value = ret.valueSat / util.COIN; + + // Double spend? + if ( ret.multipleSpendAttempt || + !ret.spendTxId || + (ret.spendTxId && ret.spendTxId !== info.txid) + ) { + if (ret.multipleSpendAttempts ) { + ret.multipleSpendAttempts.each(function(mul) { + if (mul.spendTxId !== info.txid) { + i.doubleSpendTxID = ret.spendTxId; + i.doubleSpendIndex = ret.spendIndex; + } + }); + } + else if (!ret.spendTxId) { + i.dbError = 'Input spend not registered'; + } + else { + i.doubleSpendTxID = ret.spendTxId; + i.doubleSpendIndex = ret.spendIndex; + } + } + else { + i.doubleSpendTxID = null; + } valueIn += i.valueSat; return c_in(); @@ -195,15 +222,35 @@ function spec(b) { }; TransactionDb.prototype.fromTxIdN = function(txid, n, cb) { - + var self = this; var k = OUTS_PREFIX + txid + '-' + n; db.get(k, function (err,val) { - if (err && err.notFound) { - err = null; + +console.log('[TransactionDb.js.230]'); //TODO + if (!val || (err && err.notFound) ) { + return cb(null, { unconfirmedInput: 1} ); } - var a = val?val.split(':'):[null,null]; - return cb(err, a[0], parseInt(a[1])); + + var a = val.split(':'); + var ret = { + addr: a[0], + valueSat: parseInt(a[1]), + }; + + // Spend? + var k = SPEND_PREFIX + txid + '-' + n; + db.createReadStream({start: k, end: k + '~'}) + .on('data', function (data) { + var k = data.key.split('-'); + self._addSpendInfo(ret, k[4], k[5]); + }) + .on('error', function (error) { + return cb(error); + }) + .on('end', function () { + return cb(null,ret); + }); }); }; @@ -218,27 +265,18 @@ function spec(b) { if (o.multipleSpendAttempts) { - var isConfirmed = 0; - var txid, index; - async.each(o.multipleSpendAttempts, - function (oi) { + async.each(o.multipleSpendAttempts, + function (oi, e_c) { self.isConfirmed(oi.spendTxId, function(err,is) { - if (err) return cb(err); - isConfirmed = 1; - txid = oi.spendTxId; - index = oi.index; - return cb(); + if (err) return; + if (is) { + o.spendTxId = oi.spendTxId; + o.index = oi.index; + o.spendIsConfirmed = 1; + } + return e_c(); }); - }, - function (err) { - // write the spended TXid into main register - if (isConfirmed) { - o.spendTxId = txid; - o.index = index; - o.spendIsConfirmed = 1; - } - return cb(err); - }); + }, cb); } else { self.isConfirmed(o.spendTxId, function(err,is) { @@ -367,7 +405,6 @@ function spec(b) { TransactionDb.prototype.add = function(tx, blockhash, cb) { var self = this; var addrs = []; - var is_new = true; if (tx.hash) self.adaptTxObject(tx); @@ -423,13 +460,8 @@ function spec(b) { }, function (err) { if (err) { - if (err.message.match(/E11000/)) { - is_new = false; - } - else { - console.log('ERR at TX %s: %s', tx.txid, err); - return cb(err); - } + console.log('ERR at TX %s: %s', tx.txid, err); + return cb(err); } return p_c(); }); @@ -439,7 +471,7 @@ function spec(b) { return self.setConfirmation(tx.txid,blockhash, true, p_c); }, ], function(err) { - return cb(err, addrs, is_new); + return cb(err, addrs); }); }; diff --git a/public/src/js/controllers/transactions.js b/public/src/js/controllers/transactions.js index 0107c56f..e754b6fc 100644 --- a/public/src/js/controllers/transactions.js +++ b/public/src/js/controllers/transactions.js @@ -19,12 +19,9 @@ function($scope, $rootScope, $routeParams, $location, Global, Transaction, Trans var tmp = {}; var u = 0; - // TODO multiple output address - // for(var i=0; i < l; i++) { var notAddr = false; - // non standard input if (items[i].scriptSig && !items[i].addr) { items[i].addr = 'Unparsed address [' + u++ + ']'; @@ -56,6 +53,10 @@ function($scope, $rootScope, $routeParams, $location, Global, Transaction, Trans tmp[addr].items = []; } + tmp[addr].doubleSpendTxID = tmp[addr].doubleSpendTxID || items[i].doubleSpendTxID; + tmp[addr].doubleSpendIndex = tmp[addr].doubleSpendIndex || items[i].doubleSpendIndex; + tmp[addr].unconfirmedInput += items[i].unconfirmedInput; + tmp[addr].dbError = tmp[addr].dbError || items[i].dbError; tmp[addr].valueSat += items[i].value * COIN; tmp[addr].value = items[i].value; tmp[addr].items.push(items[i]); diff --git a/public/views/transaction/tx.html b/public/views/transaction/tx.html index 4a648609..4c588a60 100644 --- a/public/views/transaction/tx.html +++ b/public/views/transaction/tx.html @@ -28,6 +28,11 @@ {{vin.addr}} {{vin.addr}} +
(Input unconfirmed)
+
Incoherence in levelDB detected, please resync
+
Double spend attempt detected. From tx: + {{vin.doubleSpendTxID}},{{vin.doubleSpendIndex}} +
@@ -38,6 +43,12 @@ {{vin.addr}} {{vin.addr}}
+
(Input unconfirmed)
+
Incoherence in levelDB detected, please resync
+
Double spend attempt detected. From tx: + {{vin.doubleSpendTxID}},{{vin.doubleSpendIndex}} +
+
@@ -68,6 +79,8 @@ {{vout.addr}} {{address}}
+ +
@@ -108,7 +121,8 @@
- Fees: {{$root.currency.getConvertion(tx.fees)}} + Fees: {{$root.currency.getConvertion(tx.fees)}} + Fees: unknown yet
{{tx.confirmations}} Confirmations