rpc/mempool: implement prioritisetransaction.

This commit is contained in:
Christopher Jeffrey 2017-03-13 23:58:08 -07:00
parent 6f27b3fa3d
commit 68bba8621e
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
5 changed files with 119 additions and 11 deletions

View File

@ -708,6 +708,9 @@ RPC.prototype.getRawMempool = co(function* getRawMempool(args, help) {
if (help || args.length > 1)
throw new RPCError('getrawmempool ( verbose )');
if (!this.mempool)
throw new RPCError('No mempool available.');
if (verbose) {
hashes = this.mempool.getSnapshot();
@ -748,8 +751,11 @@ RPC.prototype.getTXOut = co(function* getTXOut(args, help) {
if (!hash || index == null)
throw new RPCError('Invalid outpoint.');
if (mempool)
if (mempool) {
if (!this.mempool)
throw new RPCError('No mempool available.');
coin = this.mempool.getCoin(hash, index);
}
if (!coin)
coin = yield this.chain.db.getCoin(hash, index);
@ -1352,7 +1358,7 @@ RPC.prototype.prioritiseTransaction = co(function* prioritiseTransaction(args, h
var valid = new Validator([args]);
var hash = valid.hash(0);
var pri = valid.num(1);
var fee = valid.num(2);
var fee = valid.i64(2);
var entry;
if (help || args.length !== 3) {
@ -1374,6 +1380,8 @@ RPC.prototype.prioritiseTransaction = co(function* prioritiseTransaction(args, h
if (!entry)
throw new RPCError('Transaction not in mempool.');
this.mempool.prioritise(entry, pri, fee);
return true;
});
@ -1673,6 +1681,9 @@ RPC.prototype.signRawTransaction = co(function* signRawTransaction(args, help) {
if (!data)
throw new RPCError('Invalid hex string.');
if (!this.mempool)
throw new RPCError('No mempool available.');
tx = MTX.fromRaw(data);
tx.view = yield this.mempool.getSpentView(tx);

View File

@ -1953,6 +1953,29 @@ Mempool.prototype.getSize = function getSize() {
return this.size;
};
/**
* Prioritise transaction.
* @param {MempoolEntry} entry
* @param {Number} pri
* @param {Amount} fee
*/
Mempool.prototype.prioritise = function _prioritise(entry, pri, fee) {
if (-fee > entry.deltaFee)
fee = -entry.deltaFee;
if (-pri < entry.priority)
pri = -entry.priority;
this.updateAncestors(entry, preprioritise);
entry.priority += pri;
entry.deltaFee += fee;
entry.descFee += fee;
this.updateAncestors(entry, prioritise);
};
/**
* MempoolOptions
* @alias module:mempool.MempoolOptions
@ -2571,7 +2594,7 @@ function nop(parent, child) {
}
function addFee(parent, child) {
parent.descFee += child.fee;
parent.descFee += child.deltaFee;
parent.descSize += child.size;
}
@ -2580,10 +2603,18 @@ function removeFee(parent, child) {
parent.descSize -= child.descSize;
}
function preprioritise(parent, child) {
parent.descFee -= child.deltaFee;
}
function prioritise(parent, child) {
parent.descFee += child.deltaFee;
}
function cmpRate(a, b) {
var xf = a.fee;
var xf = a.deltaFee;
var xs = a.size;
var yf = b.fee;
var yf = b.deltaFee;
var ys = b.size;
var x, y;
@ -2609,7 +2640,7 @@ function cmpRate(a, b) {
}
function useDesc(a) {
var x = a.fee * a.descSize;
var x = a.deltaFee * a.descSize;
var y = a.descFee * a.size;
return y > x;
}

View File

@ -40,6 +40,7 @@ function MempoolEntry(options) {
this.sigops = 0;
this.priority = 0;
this.fee = 0;
this.deltaFee = 0;
this.ts = 0;
this.value = 0;
this.dependencies = false;
@ -63,6 +64,7 @@ MempoolEntry.prototype.fromOptions = function fromOptions(options) {
this.sigops = options.sigops;
this.priority = options.priority;
this.fee = options.fee;
this.deltaFee = options.deltaFee;
this.ts = options.ts;
this.value = options.value;
this.dependencies = options.dependencies;
@ -112,6 +114,7 @@ MempoolEntry.prototype.fromTX = function fromTX(tx, view, height) {
this.sigops = sigops;
this.priority = priority;
this.fee = fee;
this.deltaFee = fee;
this.ts = util.now();
this.value = value;
this.dependencies = dependencies;
@ -160,9 +163,9 @@ MempoolEntry.prototype.txid = function txid() {
*/
MempoolEntry.prototype.getPriority = function getPriority(height) {
var heightDelta = height - this.height;
var deltaPriority = (heightDelta * this.value) / this.size;
var result = this.priority + Math.floor(deltaPriority);
var height = height - this.height;
var priority = (height * this.value) / this.size;
var result = this.priority + Math.floor(priority);
if (result < 0)
result = 0;
return result;
@ -177,6 +180,15 @@ MempoolEntry.prototype.getFee = function getFee() {
return this.fee;
};
/**
* Get delta fee.
* @returns {Amount}
*/
MempoolEntry.prototype.getDeltaFee = function getDeltaFee() {
return this.deltaFee;
};
/**
* Calculate fee rate.
* @returns {Rate}
@ -186,6 +198,15 @@ MempoolEntry.prototype.getRate = function getRate() {
return policy.getRate(this.size, this.fee);
};
/**
* Calculate delta fee rate.
* @returns {Rate}
*/
MempoolEntry.prototype.getDeltaRate = function getDeltaRate() {
return policy.getRate(this.size, this.deltaFee);
};
/**
* Calculate fee cumulative descendant rate.
* @returns {Rate}
@ -322,6 +343,7 @@ MempoolEntry.prototype.fromRaw = function fromRaw(data) {
this.sigops = br.readU32();
this.priority = br.readDouble();
this.fee = br.readU64();
this.deltaFee = this.fee;
this.ts = br.readU32();
this.value = br.readU64();
this.dependencies = br.readU8() === 1;

View File

@ -649,9 +649,9 @@ BlockEntry.fromTX = function fromTX(tx, view, attempt) {
BlockEntry.fromEntry = function fromEntry(entry, attempt) {
var item = new BlockEntry(entry.tx);
item.fee = entry.getFee();
item.rate = entry.getRate();
item.rate = entry.getDeltaRate();
item.priority = entry.getPriority(attempt.height);
item.free = item.fee < policy.getMinFee(entry.size);
item.free = entry.getDeltaFee() < policy.getMinFee(entry.size);
item.sigops = entry.sigops;
item.descRate = entry.getDescRate();
return item;

View File

@ -197,6 +197,50 @@ Validator.prototype.u64 = function u64(key, fallback) {
return value;
};
/**
* Get a value (as an int32).
* @param {String} key
* @param {Object?} fallback
* @returns {Number|null}
*/
Validator.prototype.i32 = function i32(key, fallback) {
var value = this.num(key);
if (fallback === undefined)
fallback = null;
if (value === null)
return fallback;
if (value % 1 !== 0 || Math.abs(value) > 0x7fffffff)
throw new Error(fmt(key) + ' must be an int32.');
return value;
};
/**
* Get a value (as an int64).
* @param {String} key
* @param {Object?} fallback
* @returns {Number|null}
*/
Validator.prototype.i64 = function i64(key, fallback) {
var value = this.num(key);
if (fallback === undefined)
fallback = null;
if (value === null)
return fallback;
if (value % 1 !== 0 || Math.abs(value) > 0x1fffffffffffff)
throw new Error(fmt(key) + ' must be an int64.');
return value;
};
/**
* Get a value (as a satoshi number or btc string).
* @param {String} key