wallet: update rpc calls for getHashes.

This commit is contained in:
Christopher Jeffrey 2017-10-18 09:18:46 -07:00
parent c16e85e485
commit abcf48cbe9
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
7 changed files with 91 additions and 73 deletions

View File

@ -1893,6 +1893,17 @@ Chain.prototype.getTips = function getTips() {
return this.db.getTips(); return this.db.getTips();
}; };
/**
* Get range of hashes.
* @param {Number} [start=-1]
* @param {Number} [end=-1]
* @returns {Promise}
*/
Chain.prototype.getHashes = function getHashes(start = -1, end = -1) {
return this.db.getHashes(start, end);
};
/** /**
* Get a coin (unspents only). * Get a coin (unspents only).
* @private * @private

View File

@ -452,6 +452,14 @@ HTTPServer.prototype.handleAuth = function handleAuth(socket) {
return entry.toRaw(); return entry.toRaw();
}); });
socket.hook('get hashes', (args) => {
const valid = new Validator([args]);
const start = valid.i32(0, -1);
const end = valid.i32(1, -1);
return await this.chain.getHashes(start, end);
});
socket.hook('add filter', (args) => { socket.hook('add filter', (args) => {
const valid = new Validator([args]); const valid = new Validator([args]);
const chunks = valid.array(0); const chunks = valid.array(0);

View File

@ -226,6 +226,19 @@ WalletClient.prototype.getEntry = function getEntry(block) {
}); });
}; };
/**
* Get hashes.
* @param {Number} [start=-1]
* @param {Number} [end=-1]
* @returns {Promise}
*/
WalletClient.prototype.getHashes = function getHashes(start = -1, end = -1) {
return new Promise((resolve, reject) => {
this.socket.emit('get hashes', start, end, wrap(resolve, reject));
});
};
/** /**
* Send a transaction. Do not wait for promise. * Send a transaction. Do not wait for promise.
* @param {TX} tx * @param {TX} tx

View File

@ -178,7 +178,7 @@ NodeClient.prototype.estimateFee = async function estimateFee(blocks) {
*/ */
NodeClient.prototype.getHashes = async function getHashes(start = -1, end = -1) { NodeClient.prototype.getHashes = async function getHashes(start = -1, end = -1) {
return this.node.chain.db.getHashes(start, end); return this.node.chain.getHashes(start, end);
}; };
/** /**

View File

@ -335,12 +335,12 @@ RPC.prototype.getAccountAddress = async function getAccountAddress(args, help) {
if (!name) if (!name)
name = 'default'; name = 'default';
const account = await wallet.getAccount(name); const addr = await wallet.receiveAddress(name);
if (!account) if (!addr)
return ''; return '';
return account.receive.getAddress('string'); return addr.toString(this.network);
}; };
RPC.prototype.getAccount = async function getAccount(args, help) { RPC.prototype.getAccount = async function getAccount(args, help) {

View File

@ -227,9 +227,9 @@ TXDB.prototype.removeCredit = async function removeCredit(b, credit, path) {
*/ */
TXDB.prototype.spendCredit = function spendCredit(b, credit, tx, index) { TXDB.prototype.spendCredit = function spendCredit(b, credit, tx, index) {
const prevout = tx.inputs[index].prevout; const {hash, index} = tx.inputs[index].prevout;
const spender = Outpoint.fromTX(tx, index); const spender = Outpoint.fromTX(tx, index);
b.put(layout.s(prevout.hash, prevout.index), spender.toRaw()); b.put(layout.s(hash, index), spender.toRaw());
b.put(layout.d(spender.hash, spender.index), credit.coin.toRaw()); b.put(layout.d(spender.hash, spender.index), credit.coin.toRaw());
}; };
@ -240,12 +240,37 @@ TXDB.prototype.spendCredit = function spendCredit(b, credit, tx, index) {
*/ */
TXDB.prototype.unspendCredit = function unspendCredit(b, tx, index) { TXDB.prototype.unspendCredit = function unspendCredit(b, tx, index) {
const prevout = tx.inputs[index].prevout; const {hash, index} = tx.inputs[index].prevout;
const spender = Outpoint.fromTX(tx, index); const spender = Outpoint.fromTX(tx, index);
b.del(layout.s(prevout.hash, prevout.index)); b.del(layout.s(hash, index));
b.del(layout.d(spender.hash, spender.index)); b.del(layout.d(spender.hash, spender.index));
}; };
/**
* Write input record.
* @param {TX} tx
* @param {Number} index
*/
TXDB.prototype.writeInput = async function writeInput(tx, index) {
const {hash, index} = tx.inputs[index].prevout;
const spender = Outpoint.fromTX(tx, index);
this.put(layout.s(hash, index), spender.toRaw());
return this.addOutpointMap(b, hash, index);
};
/**
* Remove input record.
* @param {TX} tx
* @param {Number} index
*/
TXDB.prototype.removeInput = async function removeInput(tx, index) {
const {hash, index} = tx.inputs[index].prevout;
this.del(layout.s(hash, index));
return this.removeOutpointMap(b, hash, index);
};
/** /**
* Test a whether a coin has been spent. * Test a whether a coin has been spent.
* @param {Hash} hash * @param {Hash} hash
@ -421,25 +446,6 @@ TXDB.prototype.removeBlock = async function removeBlock(b, hash, height) {
b.put(key, raw); b.put(key, raw);
}; };
/**
* Append to the global block record.
* @param {Hash} hash
* @param {BlockMeta} meta
* @returns {Promise}
*/
TXDB.prototype.addBlockSlow = async function addBlockSlow(b, hash, meta) {
let block = await this.getBlock(meta.height);
if (!block)
block = BlockRecord.fromMeta(meta);
if (!block.add(hash))
return;
b.put(layout.b(meta.height), block.toRaw());
};
/** /**
* Remove from the global block record. * Remove from the global block record.
* @param {Hash} hash * @param {Hash} hash
@ -447,7 +453,7 @@ TXDB.prototype.addBlockSlow = async function addBlockSlow(b, hash, meta) {
* @returns {Promise} * @returns {Promise}
*/ */
TXDB.prototype.removeBlockSlow = async function removeBlockSlow(b, hash, height) { TXDB.prototype.spliceBlock = async function spliceBlock(b, hash, height) {
const block = await this.getBlock(height); const block = await this.getBlock(height);
if (!block) if (!block)
@ -488,7 +494,7 @@ TXDB.prototype.add = async function add(tx, block) {
return null; return null;
// Confirm transaction. // Confirm transaction.
return await this._confirm(existing, block); return await this.confirm(existing, block);
} }
const wtx = TXRecord.fromTX(tx, block); const wtx = TXRecord.fromTX(tx, block);
@ -533,8 +539,13 @@ TXDB.prototype.insert = async function insert(wtx, block) {
const {hash, index} = input.prevout; const {hash, index} = input.prevout;
const credit = await this.getCredit(hash, index); const credit = await this.getCredit(hash, index);
if (!credit) if (!credit) {
// Watch all inputs for incoming txs.
// This allows us to check for double spends.
if (!block)
await this.writeInput(tx, i);
continue; continue;
}
const coin = credit.coin; const coin = credit.coin;
const path = await this.getPath(coin); const path = await this.getPath(coin);
@ -668,28 +679,6 @@ TXDB.prototype.insert = async function insert(wtx, block) {
return details; return details;
}; };
/**
* Attempt to confirm a transaction.
* @private
* @param {TX} tx
* @param {BlockMeta} block
* @returns {Promise}
*/
TXDB.prototype.confirm = async function confirm(hash, block) {
const wtx = await this.getTX(hash);
if (!wtx)
return null;
if (wtx.height !== -1)
throw new Error('TX is already confirmed.');
assert(block);
return this._confirm(wtx, block);
};
/** /**
* Attempt to confirm a transaction. * Attempt to confirm a transaction.
* @private * @private
@ -698,7 +687,7 @@ TXDB.prototype.confirm = async function confirm(hash, block) {
* @returns {Promise} * @returns {Promise}
*/ */
TXDB.prototype._confirm = async function _confirm(wtx, block) { TXDB.prototype.confirm = async function confirm(wtx, block) {
const b = this.bucket(); const b = this.bucket();
const state = this.state.clone(); const state = this.state.clone();
const tx = wtx.tx; const tx = wtx.tx;
@ -724,6 +713,8 @@ TXDB.prototype._confirm = async function _confirm(wtx, block) {
// There may be new credits available // There may be new credits available
// that we haven't seen yet. // that we haven't seen yet.
if (!credit) { if (!credit) {
await this.removeInput(tx, i);
credit = await this.getCredit(hash, index); credit = await this.getCredit(hash, index);
if (!credit) if (!credit)
@ -860,8 +851,11 @@ TXDB.prototype.erase = async function erase(wtx, block) {
for (let i = 0; i < tx.inputs.length; i++) { for (let i = 0; i < tx.inputs.length; i++) {
const credit = credits[i]; const credit = credits[i];
if (!credit) if (!credit) {
if (!block)
await this.removeInput(tx, i);
continue; continue;
}
const coin = credit.coin; const coin = credit.coin;
const path = await this.getPath(coin); const path = await this.getPath(coin);
@ -933,7 +927,7 @@ TXDB.prototype.erase = async function erase(wtx, block) {
// Update block records. // Update block records.
if (block) { if (block) {
await this.removeBlockMap(b, height); await this.removeBlockMap(b, height);
await this.removeBlockSlow(b, hash, height); await this.spliceBlock(b, hash, height);
} }
// Update the transaction counter // Update the transaction counter
@ -1053,8 +1047,10 @@ TXDB.prototype.disconnect = async function disconnect(wtx, block) {
for (let i = 0; i < tx.inputs.length; i++) { for (let i = 0; i < tx.inputs.length; i++) {
const credit = credits[i]; const credit = credits[i];
if (!credit) if (!credit) {
await this.writeInput(tx, i);
continue; continue;
}
const coin = credit.coin; const coin = credit.coin;
@ -1183,10 +1179,10 @@ TXDB.prototype.removeConflicts = async function removeConflicts(tx, conf) {
// Gather all spent records first. // Gather all spent records first.
for (let i = 0; i < tx.inputs.length; i++) { for (let i = 0; i < tx.inputs.length; i++) {
const input = tx.inputs[i]; const input = tx.inputs[i];
const prevout = input.prevout; const {hash, index} = input.prevout;
// Is it already spent? // Is it already spent?
const spent = await this.getSpent(prevout.hash, prevout.index); const spent = await this.getSpent(hash, index);
if (!spent) if (!spent)
continue; continue;
@ -1198,21 +1194,16 @@ TXDB.prototype.removeConflicts = async function removeConflicts(tx, conf) {
const spender = await this.getTX(spent.hash); const spender = await this.getTX(spent.hash);
assert(spender); assert(spender);
const block = spender.getBlock(); if (conf && spender.height !== -1)
if (conf && block)
return false; return false;
spends[i] = spender; spends.push(spender);
} }
// Once we know we're not going to // Once we know we're not going to
// screw things up, remove the double // screw things up, remove the double
// spenders. // spenders.
for (const spender of spends) { for (const spender of spends) {
if (!spender)
continue;
// Remove the double spender. // Remove the double spender.
await this.removeConflict(spender); await this.removeConflict(spender);
} }
@ -2383,12 +2374,7 @@ Credit.prototype.fromRaw = function fromRaw(data) {
const br = new BufferReader(data); const br = new BufferReader(data);
this.coin.fromReader(br); this.coin.fromReader(br);
this.spent = br.readU8() === 1; this.spent = br.readU8() === 1;
this.own = true; this.own = br.readU8() === 1;
// Note: soft-fork
if (br.left() > 0)
this.own = br.readU8() === 1;
return this; return this;
}; };

View File

@ -1559,8 +1559,8 @@ WalletDB.prototype.getPathMap = function getPathMap(hash) {
* @param {Number} wid * @param {Number} wid
*/ */
WalletDB.prototype.addPathMap = function addPathMap(b, hash, wid) { WalletDB.prototype.addPathMap = async function addPathMap(b, hash, wid) {
this.addHash(hash); await this.addHash(hash);
return this.addMap(b, layout.p(hash), wid); return this.addMap(b, layout.p(hash), wid);
}; };