drop old scanning. always rescan blockchain on boot.
This commit is contained in:
parent
1c9c06b4f9
commit
e51736728e
@ -1168,6 +1168,9 @@ ChainDB.prototype.scan = function scan(start, hashes, iter, callback) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
if (!block)
|
||||
return next();
|
||||
|
||||
self.logger.info('Scanning block %s.', utils.revHex(hash));
|
||||
|
||||
utils.forEachSerial(block.txs, function(tx, next) {
|
||||
@ -1177,7 +1180,7 @@ ChainDB.prototype.scan = function scan(start, hashes, iter, callback) {
|
||||
for (i = 0; i < hashes.length; i++) {
|
||||
hash = hashes[i];
|
||||
if (hashMap[hash])
|
||||
return iter(tx, next);
|
||||
return iter(tx, block.toHeaders(), next);
|
||||
}
|
||||
|
||||
next();
|
||||
|
||||
@ -258,26 +258,27 @@ Fullnode.prototype._open = function open(callback) {
|
||||
this.mempool.open.bind(this.mempool),
|
||||
this.miner.open.bind(this.miner),
|
||||
this.pool.open.bind(this.pool),
|
||||
this.walletdb.open.bind(this.walletdb),
|
||||
function(next) {
|
||||
self.walletdb.open(function(err) {
|
||||
self.createWallet(options, function(err, wallet) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
self.createWallet(options, function(err, wallet) {
|
||||
if (err)
|
||||
return next(err);
|
||||
// Set the miner payout address if the
|
||||
// programmer didn't pass one in.
|
||||
if (!self.miner.address)
|
||||
self.miner.address = wallet.getAddress();
|
||||
|
||||
// Set the miner payout address if the
|
||||
// programmer didn't pass one in.
|
||||
if (!self.miner.address)
|
||||
self.miner.address = wallet.getAddress();
|
||||
self.wallet = wallet;
|
||||
|
||||
self.wallet = wallet;
|
||||
|
||||
next();
|
||||
});
|
||||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
// Always rescan to make sure we didn't miss anything:
|
||||
// there is no atomicity between the chaindb and walletdb.
|
||||
self.walletdb.rescan(self.chain.db, next);
|
||||
},
|
||||
function(next) {
|
||||
var i;
|
||||
self.walletdb.getUnconfirmed(function(err, txs) {
|
||||
|
||||
@ -309,6 +309,17 @@ TXDB.prototype.writeGenesis = function writeGenesis(callback) {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the best block hash.
|
||||
* @param {Function} callback
|
||||
*/
|
||||
|
||||
TXDB.prototype.getTip = function getTip(callback) {
|
||||
this.db.fetch('R', function(data) {
|
||||
return data.toString('hex');
|
||||
}, callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a block's transactions and write the new best hash.
|
||||
* @param {Block} block
|
||||
|
||||
@ -1112,71 +1112,6 @@ Wallet.prototype.getRedeem = function getRedeem(hash, callback) {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Scan for active accounts and addresses. Used for importing a wallet.
|
||||
* @param {Function} scanner - Must be a function which accepts
|
||||
* a {@link Base58Address} as well as a callback and returns
|
||||
* transactions by address.
|
||||
* @param {Function} callback - Return [Error, Number] (total number
|
||||
* of addresses allocated).
|
||||
*/
|
||||
|
||||
Wallet.prototype.scan = function scan(maxGap, scanner, callback) {
|
||||
var self = this;
|
||||
var total = 0;
|
||||
var index = 0;
|
||||
var unlock;
|
||||
|
||||
if (typeof maxGap === 'function') {
|
||||
callback = scanner;
|
||||
scanner = maxGap;
|
||||
maxGap = null;
|
||||
}
|
||||
|
||||
unlock = this.writeLock.lock(scan, [maxGap, scanner, callback]);
|
||||
|
||||
if (!unlock)
|
||||
return;
|
||||
|
||||
callback = utils.wrap(callback, unlock);
|
||||
|
||||
if (!this.initialized)
|
||||
return callback(new Error('Wallet is not initialized.'));
|
||||
|
||||
self.start();
|
||||
|
||||
function done(err, total) {
|
||||
if (err) {
|
||||
self.drop();
|
||||
return callback(err);
|
||||
}
|
||||
self.commit(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
return callback(null, total);
|
||||
});
|
||||
}
|
||||
|
||||
(function next() {
|
||||
self.getAccount(index++, function(err, account) {
|
||||
if (err)
|
||||
return done(err);
|
||||
|
||||
if (!account)
|
||||
return done(null, total);
|
||||
|
||||
account.scan(maxGap, scanner, function(err, result) {
|
||||
if (err)
|
||||
return done(err);
|
||||
|
||||
total += result;
|
||||
|
||||
next();
|
||||
});
|
||||
}, true);
|
||||
})();
|
||||
};
|
||||
|
||||
/**
|
||||
* Build input scripts templates for a transaction (does not
|
||||
* sign, only creates signature slots). Only builds scripts
|
||||
@ -1908,13 +1843,6 @@ Account.fromOptions = function fromOptions(db, options) {
|
||||
|
||||
Account.MAX_LOOKAHEAD = 5;
|
||||
|
||||
/*
|
||||
* Default address gap for scanning.
|
||||
* @const {Number}
|
||||
*/
|
||||
|
||||
Account.MAX_GAP = 20;
|
||||
|
||||
/**
|
||||
* Attempt to intialize the account (generating
|
||||
* the first addresses along with the lookahead
|
||||
@ -2285,102 +2213,6 @@ Account.prototype.setDepth = function setDepth(receiveDepth, changeDepth, callba
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Scan for addresses.
|
||||
* @param {Function} scanner - Must be a callback which accepts
|
||||
* a callback and returns transactions by address.
|
||||
* @param {Function} callback - Return [Error, Number] (total number
|
||||
* of addresses allocated).
|
||||
*/
|
||||
|
||||
Account.prototype.scan = function scan(maxGap, scanner, callback) {
|
||||
var self = this;
|
||||
var total = 0;
|
||||
|
||||
if (typeof maxGap === 'function') {
|
||||
callback = scanner;
|
||||
scanner = maxGap;
|
||||
maxGap = null;
|
||||
}
|
||||
|
||||
if (maxGap == null)
|
||||
maxGap = Account.MAX_GAP;
|
||||
|
||||
if (!this.initialized)
|
||||
return callback(new Error('Account is not initialized.'));
|
||||
|
||||
function addTX(txs, calback) {
|
||||
if (!Array.isArray(txs) || txs.length === 0)
|
||||
return callback(null, false);
|
||||
|
||||
utils.forEachSerial(txs, function(tx, next) {
|
||||
self.db.addTX(tx, next);
|
||||
}, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
return callback(null, true);
|
||||
});
|
||||
}
|
||||
|
||||
(function chainCheck(change) {
|
||||
var depth = change ? self.changeDepth : self.receiveDepth;
|
||||
var index = 0;
|
||||
var gap = 0;
|
||||
|
||||
function createAddress(callback) {
|
||||
if (index === depth)
|
||||
return self.createAddress(change, callback);
|
||||
return callback(null, self.deriveAddress(change, index++));
|
||||
}
|
||||
|
||||
(function next() {
|
||||
createAddress(function(err, address) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
scanner(address.getAddress(), function(err, txs) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
addTX(txs, function(err, result) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
// Special case for maxGap=0
|
||||
if (maxGap === 0 && index === depth) {
|
||||
if (!change)
|
||||
return chainCheck(true);
|
||||
self.save();
|
||||
return callback(null, total);
|
||||
}
|
||||
|
||||
if (result) {
|
||||
total++;
|
||||
gap = 0;
|
||||
return next();
|
||||
}
|
||||
|
||||
if (++gap < Account.MAX_GAP)
|
||||
return next();
|
||||
|
||||
if (!change) {
|
||||
self.receiveDepth = Math.max(depth, self.receiveDepth - gap);
|
||||
self.receiveAddress = self.deriveReceive(self.receiveDepth - 1);
|
||||
return chainCheck(true);
|
||||
}
|
||||
|
||||
self.changeDepth = Math.max(depth, self.changeDepth - gap);
|
||||
self.changeAddress = self.deriveChange(self.changeDepth - 1);
|
||||
|
||||
return callback(null, total);
|
||||
});
|
||||
});
|
||||
});
|
||||
})();
|
||||
})(false);
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert the account to a more inspection-friendly object.
|
||||
* @returns {Object}
|
||||
|
||||
@ -1048,6 +1048,38 @@ WalletDB.prototype.getAddresses = function getAddresses(id, callback) {
|
||||
}, callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Rescan the blockchain.
|
||||
* @param {ChainDB} chaindb
|
||||
* @param {Function} callback
|
||||
*/
|
||||
|
||||
WalletDB.prototype.rescan = function rescan(chaindb, callback) {
|
||||
var self = this;
|
||||
this.tx.getTip(function(err, hash) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!hash)
|
||||
return callback(new Error('Best hash not found.'));
|
||||
|
||||
self.getAddresses(function(err, hashes) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
self.logger.info('Scanning for %d addresses.', hashes.length);
|
||||
|
||||
chaindb.scan(hash, hashes, function(tx, block, next) {
|
||||
self.tx.add(tx, function(err) {
|
||||
if (err)
|
||||
return next(err);
|
||||
self.db.put('R', block.hash(), next);
|
||||
});
|
||||
}, callback);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the corresponding path for an address hash.
|
||||
* @param {WalletID} id
|
||||
|
||||
Loading…
Reference in New Issue
Block a user