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)
|
if (err)
|
||||||
return next(err);
|
return next(err);
|
||||||
|
|
||||||
|
if (!block)
|
||||||
|
return next();
|
||||||
|
|
||||||
self.logger.info('Scanning block %s.', utils.revHex(hash));
|
self.logger.info('Scanning block %s.', utils.revHex(hash));
|
||||||
|
|
||||||
utils.forEachSerial(block.txs, function(tx, next) {
|
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++) {
|
for (i = 0; i < hashes.length; i++) {
|
||||||
hash = hashes[i];
|
hash = hashes[i];
|
||||||
if (hashMap[hash])
|
if (hashMap[hash])
|
||||||
return iter(tx, next);
|
return iter(tx, block.toHeaders(), next);
|
||||||
}
|
}
|
||||||
|
|
||||||
next();
|
next();
|
||||||
|
|||||||
@ -258,26 +258,27 @@ Fullnode.prototype._open = function open(callback) {
|
|||||||
this.mempool.open.bind(this.mempool),
|
this.mempool.open.bind(this.mempool),
|
||||||
this.miner.open.bind(this.miner),
|
this.miner.open.bind(this.miner),
|
||||||
this.pool.open.bind(this.pool),
|
this.pool.open.bind(this.pool),
|
||||||
|
this.walletdb.open.bind(this.walletdb),
|
||||||
function(next) {
|
function(next) {
|
||||||
self.walletdb.open(function(err) {
|
self.createWallet(options, function(err, wallet) {
|
||||||
if (err)
|
if (err)
|
||||||
return next(err);
|
return next(err);
|
||||||
|
|
||||||
self.createWallet(options, function(err, wallet) {
|
// Set the miner payout address if the
|
||||||
if (err)
|
// programmer didn't pass one in.
|
||||||
return next(err);
|
if (!self.miner.address)
|
||||||
|
self.miner.address = wallet.getAddress();
|
||||||
|
|
||||||
// Set the miner payout address if the
|
self.wallet = wallet;
|
||||||
// programmer didn't pass one in.
|
|
||||||
if (!self.miner.address)
|
|
||||||
self.miner.address = wallet.getAddress();
|
|
||||||
|
|
||||||
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) {
|
function(next) {
|
||||||
var i;
|
var i;
|
||||||
self.walletdb.getUnconfirmed(function(err, txs) {
|
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.
|
* Add a block's transactions and write the new best hash.
|
||||||
* @param {Block} block
|
* @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
|
* Build input scripts templates for a transaction (does not
|
||||||
* sign, only creates signature slots). Only builds scripts
|
* sign, only creates signature slots). Only builds scripts
|
||||||
@ -1908,13 +1843,6 @@ Account.fromOptions = function fromOptions(db, options) {
|
|||||||
|
|
||||||
Account.MAX_LOOKAHEAD = 5;
|
Account.MAX_LOOKAHEAD = 5;
|
||||||
|
|
||||||
/*
|
|
||||||
* Default address gap for scanning.
|
|
||||||
* @const {Number}
|
|
||||||
*/
|
|
||||||
|
|
||||||
Account.MAX_GAP = 20;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to intialize the account (generating
|
* Attempt to intialize the account (generating
|
||||||
* the first addresses along with the lookahead
|
* 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.
|
* Convert the account to a more inspection-friendly object.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
|
|||||||
@ -1048,6 +1048,38 @@ WalletDB.prototype.getAddresses = function getAddresses(id, callback) {
|
|||||||
}, 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.
|
* Get the corresponding path for an address hash.
|
||||||
* @param {WalletID} id
|
* @param {WalletID} id
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user