whole bunch of refactoring.
This commit is contained in:
parent
a2ddb960f5
commit
6005f0f750
@ -52,10 +52,12 @@ function AbstractBlock(data) {
|
||||
this.height = data.height != null ? data.height : -1;
|
||||
|
||||
this.txs = null;
|
||||
this.valid = null;
|
||||
this.mutable = !!data.mutable;
|
||||
|
||||
this._valid = null;
|
||||
this._hash = null;
|
||||
this._size = data._size || 0;
|
||||
this._size = null;
|
||||
this._witnessSize = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -65,10 +67,15 @@ function AbstractBlock(data) {
|
||||
*/
|
||||
|
||||
AbstractBlock.prototype.hash = function hash(enc) {
|
||||
if (!this._hash)
|
||||
this._hash = utils.dsha256(this.abbr());
|
||||
var hash = this._hash;
|
||||
|
||||
return enc === 'hex' ? this._hash.toString('hex') : this._hash;
|
||||
if (!hash) {
|
||||
hash = utils.dsha256(this.abbr());
|
||||
if (!this.mutable)
|
||||
this._hash = hash;
|
||||
}
|
||||
|
||||
return enc === 'hex' ? hash.toString('hex') : hash;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -80,15 +87,6 @@ AbstractBlock.prototype.abbr = function abbr() {
|
||||
return bcoin.protocol.framer.blockHeaders(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the full block size (this may be cached).
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
AbstractBlock.prototype.getSize = function getSize() {
|
||||
return this._size || this.render().length;
|
||||
};
|
||||
|
||||
/**
|
||||
* Verify the block.
|
||||
* @param {Object?} ret - Return object, may be
|
||||
@ -97,9 +95,15 @@ AbstractBlock.prototype.getSize = function getSize() {
|
||||
*/
|
||||
|
||||
AbstractBlock.prototype.verify = function verify(ret) {
|
||||
if (this.valid == null)
|
||||
this.valid = this._verify(ret);
|
||||
return this.valid;
|
||||
var valid = this._valid;
|
||||
|
||||
if (valid == null) {
|
||||
valid = this._verify(ret);
|
||||
if (!this.mutable)
|
||||
this._valid = valid;
|
||||
}
|
||||
|
||||
return valid;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -39,7 +39,7 @@ var BufferReader = require('./reader');
|
||||
*/
|
||||
|
||||
function Block(data) {
|
||||
var self = this;
|
||||
var i, tx;
|
||||
|
||||
if (!(this instanceof Block))
|
||||
return new Block(data);
|
||||
@ -47,19 +47,18 @@ function Block(data) {
|
||||
bcoin.abstractblock.call(this, data);
|
||||
|
||||
this.type = 'block';
|
||||
|
||||
this._witnessSize = data._witnessSize || 0;
|
||||
|
||||
this.txs = data.txs || [];
|
||||
|
||||
this._cbHeight = null;
|
||||
this._commitmentHash = null;
|
||||
|
||||
this.txs = this.txs.map(function(data, i) {
|
||||
if (data instanceof bcoin.tx)
|
||||
return data;
|
||||
for (i = 0; i < this.txs.length; i++) {
|
||||
tx = this.txs[i];
|
||||
|
||||
return bcoin.tx(data, self, i);
|
||||
});
|
||||
if (tx instanceof bcoin.tx)
|
||||
continue;
|
||||
|
||||
this.txs[i] = new bcoin.tx(tx, this, i);
|
||||
}
|
||||
}
|
||||
|
||||
utils.inherits(Block, bcoin.abstractblock);
|
||||
@ -105,79 +104,77 @@ Block.prototype.getRaw = function getRaw() {
|
||||
else
|
||||
raw = bcoin.protocol.framer.block(this);
|
||||
|
||||
this._size = raw.length;
|
||||
this._witnessSize = raw._witnessSize;
|
||||
if (!this.mutable) {
|
||||
this._size = raw.length;
|
||||
this._witnessSize = raw._witnessSize;
|
||||
}
|
||||
|
||||
return raw;
|
||||
};
|
||||
|
||||
Block.prototype._getSize = function _getSize() {
|
||||
var sizes = bcoin.protocol.framer.block.sizes(this);
|
||||
this._size = sizes.size;
|
||||
this._witnessSize = sizes.witnessSize;
|
||||
/**
|
||||
* Calculate real size and size of the witness bytes.
|
||||
* @returns {Object} Contains `size` and `witnessSize`.
|
||||
*/
|
||||
|
||||
Block.prototype.getSizes = function getSizes() {
|
||||
var sizes;
|
||||
|
||||
if (this._size != null) {
|
||||
return {
|
||||
size: this._size,
|
||||
witnessSize: this._witnessSize
|
||||
};
|
||||
}
|
||||
|
||||
sizes = bcoin.protocol.framer.block.sizes(this);
|
||||
|
||||
if (!this.mutable) {
|
||||
this._size = sizes.size;
|
||||
this._witnessSize = sizes.witnessSize;
|
||||
}
|
||||
|
||||
return sizes;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate virtual block size.
|
||||
* @param {Boolean?} force - If true, always recalculate.
|
||||
* @returns {Number} Virtual size.
|
||||
*/
|
||||
|
||||
Block.prototype.getVirtualSize = function getVirtualSize(force) {
|
||||
Block.prototype.getVirtualSize = function getVirtualSize() {
|
||||
var scale = constants.WITNESS_SCALE_FACTOR;
|
||||
return (this.getCost() + scale - 1) / scale | 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate block cost.
|
||||
* @param {Boolean?} force - If true, always recalculate.
|
||||
* @returns {Number} cost
|
||||
*/
|
||||
|
||||
Block.prototype.getCost = function getCost(force) {
|
||||
var size, witnessSize, base;
|
||||
|
||||
size = this.getSize(force);
|
||||
witnessSize = this.getWitnessSize(force);
|
||||
base = size - witnessSize;
|
||||
|
||||
return base * (constants.WITNESS_SCALE_FACTOR - 1) + size;
|
||||
Block.prototype.getCost = function getCost() {
|
||||
var sizes = this.getSizes();
|
||||
var base = sizes.size - sizes.witnessSize;
|
||||
return base * (constants.WITNESS_SCALE_FACTOR - 1) + sizes.size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get real block size.
|
||||
* @param {Boolean?} force - If true, always recalculate.
|
||||
* @returns {Number} size
|
||||
*/
|
||||
|
||||
Block.prototype.getSize = function getSize(force) {
|
||||
if (force || this._size === 0)
|
||||
this._getSize();
|
||||
return this._size;
|
||||
Block.prototype.getSize = function getSize() {
|
||||
return this.getSizes().size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get base block size (without witness).
|
||||
* @param {Boolean?} force - If true, always recalculate.
|
||||
* @returns {Number} size
|
||||
*/
|
||||
|
||||
Block.prototype.getBaseSize = function getBaseSize(force) {
|
||||
if (force || this._size === 0)
|
||||
this._getSize();
|
||||
return this._size - this._witnessSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the total size of the witnesses.
|
||||
* @param {Boolean?} force - If true, always recalculate.
|
||||
* @returns {Number} witness size
|
||||
*/
|
||||
|
||||
Block.prototype.getWitnessSize = function getWitnessSize(force) {
|
||||
if (force || this._size === 0)
|
||||
this._getSize();
|
||||
return this._witnessSize;
|
||||
Block.prototype.getBaseSize = function getBaseSize() {
|
||||
var sizes = this.getSizes();
|
||||
return sizes.size - sizes.witnessSize;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -314,8 +311,10 @@ Block.prototype.__defineGetter__('commitmentHash', function() {
|
||||
}
|
||||
}
|
||||
|
||||
if (commitmentHash)
|
||||
this._commitmentHash = commitmentHash.toString('hex');
|
||||
if (!this.mutable) {
|
||||
if (commitmentHash)
|
||||
this._commitmentHash = commitmentHash.toString('hex');
|
||||
}
|
||||
|
||||
return this._commitmentHash;
|
||||
});
|
||||
@ -420,7 +419,8 @@ Block.prototype.getCoinbaseHeight = function getCoinbaseHeight() {
|
||||
|
||||
height = coinbase.inputs[0].script.getCoinbaseHeight();
|
||||
|
||||
this._cbHeight = height;
|
||||
if (!this.mutable)
|
||||
this._cbHeight = height;
|
||||
|
||||
return height;
|
||||
};
|
||||
|
||||
@ -510,6 +510,7 @@ HDPrivateKey.prototype.derive = function derive(index, hardened) {
|
||||
return child;
|
||||
|
||||
hardened = index >= constants.hd.HARDENED ? true : hardened;
|
||||
|
||||
if (index < constants.hd.HARDENED && hardened)
|
||||
index += constants.hd.HARDENED;
|
||||
|
||||
@ -565,7 +566,7 @@ HDPrivateKey.prototype.derive = function derive(index, hardened) {
|
||||
HDPrivateKey.prototype.deriveAccount44 = function deriveAccount44(accountIndex) {
|
||||
var coinType;
|
||||
|
||||
assert(utils.isNumber(accountIndex), 'accountIndex must be a number.');
|
||||
assert(utils.isNumber(accountIndex), 'Account index must be a number.');
|
||||
|
||||
if (this instanceof HDPublicKey) {
|
||||
assert(this.isAccount44(accountIndex), 'Cannot derive account index.');
|
||||
|
||||
@ -64,9 +64,7 @@ Headers.prototype._verify = function _verify(ret) {
|
||||
*/
|
||||
|
||||
Headers.prototype.getSize = function getSize() {
|
||||
if (this._size == null)
|
||||
this.getRaw();
|
||||
return this._size;
|
||||
return 80;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -75,11 +73,7 @@ Headers.prototype.getSize = function getSize() {
|
||||
*/
|
||||
|
||||
Headers.prototype.getRaw = function getRaw() {
|
||||
if (!this._raw) {
|
||||
this._raw = bcoin.protocol.framer.headers([this]);
|
||||
this._size = this._raw.length;
|
||||
}
|
||||
return this._raw;
|
||||
return this.abbr();
|
||||
};
|
||||
|
||||
/**
|
||||
@ -127,7 +121,7 @@ Headers.parseRaw = function parseRaw(data, enc) {
|
||||
if (enc === 'hex')
|
||||
data = new Buffer(data, 'hex');
|
||||
|
||||
return bcoin.protocol.parser.parseHeaders(data)[0];
|
||||
return bcoin.protocol.parser.parseBlockHeaders(data);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -68,24 +68,6 @@ MerkleBlock.prototype.render = function render() {
|
||||
return this.getRaw();
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialize the merkleblock.
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
MerkleBlock.prototype.renderNormal = function renderNormal() {
|
||||
return this.getRaw();
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialize the merkleblock.
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
MerkleBlock.prototype.renderWitness = function renderWitness() {
|
||||
return this.getRaw();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get merkleblock size.
|
||||
* @returns {Number} Size.
|
||||
@ -152,7 +134,7 @@ MerkleBlock.prototype.verifyPartial = function verifyPartial() {
|
||||
height++;
|
||||
|
||||
function visit(depth) {
|
||||
var flag, left, right;
|
||||
var hash, flag, left, right;
|
||||
|
||||
if (i === flags.length * 8 || j === hashes.length)
|
||||
return null;
|
||||
@ -162,8 +144,9 @@ MerkleBlock.prototype.verifyPartial = function verifyPartial() {
|
||||
|
||||
if (flag === 0 || depth === height) {
|
||||
if (depth === height) {
|
||||
tx.push(hashes[j].toString('hex'));
|
||||
txMap[tx[tx.length - 1]] = true;
|
||||
hash = hashes[j].toString('hex');
|
||||
tx.push(hash);
|
||||
txMap[hash] = true;
|
||||
}
|
||||
return hashes[j++];
|
||||
}
|
||||
|
||||
@ -397,6 +397,7 @@ function MinerBlock(options) {
|
||||
|
||||
// Create our block
|
||||
this.block = new bcoin.block({
|
||||
mutable: true,
|
||||
version: options.version,
|
||||
prevBlock: this.tip.hash,
|
||||
merkleRoot: constants.NULL_HASH,
|
||||
@ -476,7 +477,7 @@ MinerBlock.prototype.addTX = function addTX(tx) {
|
||||
if (tx.mutable)
|
||||
tx = tx.toTX();
|
||||
|
||||
cost = this.block.getCost(true) + tx.getCost();
|
||||
cost = this.block.getCost() + tx.getCost();
|
||||
|
||||
if (cost > constants.block.MAX_COST)
|
||||
return false;
|
||||
|
||||
162
lib/bcoin/mtx.js
162
lib/bcoin/mtx.js
@ -78,8 +78,13 @@ function MTX(options) {
|
||||
this._hash = null;
|
||||
this._whash = null;
|
||||
this._raw = null;
|
||||
this._size = 0;
|
||||
this._witnessSize = 0;
|
||||
this._size = null;
|
||||
this._witnessSize = null;
|
||||
this._outputValue = null;
|
||||
this._inputValue = null;
|
||||
this._hashPrevouts = null;
|
||||
this._hashSequence = null;
|
||||
this._hashOutputs = null;
|
||||
|
||||
if (options.inputs) {
|
||||
for (i = 0; i < options.inputs.length; i++)
|
||||
@ -110,128 +115,6 @@ MTX.prototype.clone = function clone() {
|
||||
return tx;
|
||||
};
|
||||
|
||||
/**
|
||||
* Hash the transaction with the non-witness serialization.
|
||||
* Note that this is not cached.
|
||||
* @param {String?} enc - Can be `'hex'` or `null`.
|
||||
* @returns {Hash|Buffer} hash
|
||||
*/
|
||||
|
||||
MTX.prototype.hash = function hash(enc) {
|
||||
var hash = utils.dsha256(this.renderNormal());
|
||||
return enc === 'hex' ? hash.toString('hex') : hash;
|
||||
};
|
||||
|
||||
/**
|
||||
* Hash the transaction with the witness
|
||||
* serialization, return the wtxid (normal
|
||||
* hash if no witness is present, all zeroes
|
||||
* if coinbase). Note that this is not cached.
|
||||
* @param {String?} enc - Can be `'hex'` or `null`.
|
||||
* @returns {Hash|Buffer} hash
|
||||
*/
|
||||
|
||||
MTX.prototype.witnessHash = function witnessHash(enc) {
|
||||
var hash;
|
||||
|
||||
if (this.isCoinbase()) {
|
||||
return enc === 'hex'
|
||||
? constants.NULL_HASH
|
||||
: utils.slice(constants.ZERO_HASH);
|
||||
}
|
||||
|
||||
if (!this.hasWitness())
|
||||
return this.hash(enc);
|
||||
|
||||
hash = utils.dsha256(this.renderWitness());
|
||||
|
||||
return enc === 'hex' ? hash.toString('hex') : hash;
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialize the transaction. Note
|
||||
* that this is _not_ cached. This will use
|
||||
* the witness serialization if a
|
||||
* witness is present.
|
||||
* @returns {Buffer} Serialized transaction.
|
||||
*/
|
||||
|
||||
MTX.prototype.render = function render() {
|
||||
return this.getRaw();
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialize the transaction without the
|
||||
* witness vector, regardless of whether it
|
||||
* is a witness transaction or not. Note
|
||||
* that this is _not_ cached.
|
||||
* @returns {Buffer} Serialized transaction.
|
||||
*/
|
||||
|
||||
MTX.prototype.renderNormal = function renderNormal() {
|
||||
return bcoin.protocol.framer.tx(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialize the transaction with the
|
||||
* witness vector, regardless of whether it
|
||||
* is a witness transaction or not. Note that
|
||||
* this is _not_ cached.
|
||||
* @returns {Buffer} Serialized transaction.
|
||||
*/
|
||||
|
||||
MTX.prototype.renderWitness = function renderWitness() {
|
||||
return bcoin.protocol.framer.witnessTX(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialize the transaction. Note
|
||||
* that this is cached. This will use
|
||||
* the witness serialization if a
|
||||
* witness is present. Note that this
|
||||
* is _not_ cached.
|
||||
* @returns {Buffer} Serialized transaction.
|
||||
*/
|
||||
|
||||
MTX.prototype.getRaw = function getRaw() {
|
||||
if (this.hasWitness())
|
||||
return bcoin.protocol.framer.witnessTX(this);
|
||||
|
||||
return bcoin.protocol.framer.tx(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the real size of the transaction
|
||||
* with the witness included. Note that this
|
||||
* is _not_ cached.
|
||||
* @returns {Number} size
|
||||
*/
|
||||
|
||||
MTX.prototype.getSize = function getSize() {
|
||||
return bcoin.protocol.framer.tx.witnessSize(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the size of the transaction
|
||||
* with the witness excluded. Note that this
|
||||
* is _not_ cached.
|
||||
* @returns {Number} size
|
||||
*/
|
||||
|
||||
MTX.prototype.getBaseSize = function getBaseSize() {
|
||||
return bcoin.protocol.framer.tx.size(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the virtual size of the transaction.
|
||||
* Note that this is _not_ cached.
|
||||
* @returns {Number} vsize
|
||||
*/
|
||||
|
||||
MTX.prototype.getVirtualSize = function getVirtualSize() {
|
||||
return bcoin.protocol.framer.tx.virtualSize(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add an input to the transaction.
|
||||
* @example
|
||||
@ -246,8 +129,6 @@ MTX.prototype.getVirtualSize = function getVirtualSize() {
|
||||
MTX.prototype.addInput = function addInput(options, index) {
|
||||
var input;
|
||||
|
||||
assert(this.ts === 0, 'Cannot modify a confirmed tx.');
|
||||
|
||||
if (options instanceof bcoin.tx)
|
||||
options = bcoin.coin(options, index);
|
||||
|
||||
@ -282,8 +163,6 @@ MTX.prototype.addInput = function addInput(options, index) {
|
||||
MTX.prototype.scriptInput = function scriptInput(index, addr) {
|
||||
var input, prev, n, i, redeemScript, witnessScript, vector, dummy;
|
||||
|
||||
assert(this.ts === 0, 'Cannot modify a confirmed tx.');
|
||||
|
||||
if (typeof index !== 'number')
|
||||
index = this.inputs.indexOf(index);
|
||||
|
||||
@ -487,8 +366,6 @@ MTX.prototype.signInput = function signInput(index, addr, type) {
|
||||
var input, prev, signature, index, signatures, i;
|
||||
var len, m, n, keys, vector, dummy, version;
|
||||
|
||||
assert(this.ts === 0, 'Cannot modify a confirmed tx.');
|
||||
|
||||
if (typeof index !== 'number')
|
||||
index = this.inputs.indexOf(index);
|
||||
|
||||
@ -790,8 +667,6 @@ MTX.prototype.sign = function sign(index, addr, type) {
|
||||
MTX.prototype.addOutput = function addOutput(address, value) {
|
||||
var options, output;
|
||||
|
||||
assert(this.ts === 0, 'Cannot modify a confirmed tx.');
|
||||
|
||||
if ((address instanceof bcoin.wallet) || (address instanceof bcoin.keyring))
|
||||
address = address.getAddress();
|
||||
|
||||
@ -822,8 +697,6 @@ MTX.prototype.addOutput = function addOutput(address, value) {
|
||||
MTX.prototype.scriptOutput = function scriptOutput(index, options) {
|
||||
var output;
|
||||
|
||||
assert(this.ts === 0, 'Cannot modify a confirmed tx.');
|
||||
|
||||
if (options instanceof bcoin.output)
|
||||
return;
|
||||
|
||||
@ -897,7 +770,7 @@ MTX.prototype.maxSize = function maxSize(options, force) {
|
||||
wallet = options.wallet;
|
||||
|
||||
// Calculate the size, minus the input scripts.
|
||||
total = bcoin.protocol.framer.tx.size(this);
|
||||
total = this.getBaseSize();
|
||||
|
||||
for (i = 0; i < this.inputs.length; i++) {
|
||||
input = this.inputs[i];
|
||||
@ -1157,7 +1030,7 @@ MTX.prototype.selectCoins = function selectCoins(coins, options) {
|
||||
// Calculate max possible size after signing.
|
||||
size = tx.maxSize(options, true);
|
||||
|
||||
if (tryFree && options.height > 0) {
|
||||
if (tryFree && options.height >= 0) {
|
||||
// Note that this will only work
|
||||
// if the mempool's rolling reject
|
||||
// fee is zero (i.e. the mempool is
|
||||
@ -1204,7 +1077,7 @@ MTX.prototype.selectCoins = function selectCoins(coins, options) {
|
||||
|
||||
min = fee + output.getDustThreshold();
|
||||
|
||||
if (output.value < 0)
|
||||
if (output.value < min)
|
||||
throw new Error('Could not subtract fee.');
|
||||
|
||||
output.value -= fee;
|
||||
@ -1241,7 +1114,6 @@ MTX.prototype.selectCoins = function selectCoins(coins, options) {
|
||||
MTX.prototype.fill = function fill(coins, options) {
|
||||
var result, i, change;
|
||||
|
||||
assert(this.ts === 0, 'Cannot modify a confirmed tx.');
|
||||
assert(this.inputs.length === 0, 'TX is already filled.');
|
||||
assert(options, '`options` are required.');
|
||||
assert(options.changeAddress, '`changeAddress` is required.');
|
||||
@ -1282,8 +1154,6 @@ MTX.prototype.fill = function fill(coins, options) {
|
||||
MTX.prototype.sortMembers = function sortMembers() {
|
||||
var changeOutput;
|
||||
|
||||
assert(this.ts === 0, 'Cannot modify a confirmed tx.');
|
||||
|
||||
if (this.changeIndex !== -1) {
|
||||
changeOutput = this.outputs[this.changeIndex];
|
||||
assert(changeOutput);
|
||||
@ -1338,8 +1208,6 @@ MTX.prototype.avoidFeeSniping = function avoidFeeSniping(height) {
|
||||
MTX.prototype.setLocktime = function setLocktime(locktime) {
|
||||
var i, input;
|
||||
|
||||
assert(this.ts === 0, 'Cannot modify a confirmed tx.');
|
||||
|
||||
for (i = 0; i < this.inputs.length; i++) {
|
||||
input = this.inputs[i];
|
||||
if (input.sequence === 0xffffffff)
|
||||
@ -1391,16 +1259,6 @@ MTX.fromExtended = function fromExtended(data, enc) {
|
||||
return new MTX(MTX.parseExtended(data, enc));
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a TX to an MTX.
|
||||
* @param {TX} tx
|
||||
* @returns {MTX}
|
||||
*/
|
||||
|
||||
MTX.fromTX = function fromTX(tx) {
|
||||
return new MTX(tx);
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert the MTX to a TX.
|
||||
* @returns {TX}
|
||||
|
||||
@ -74,14 +74,18 @@ function TX(data, block, index) {
|
||||
this.index = data.index != null ? data.index : -1;
|
||||
this.ps = this.ts === 0 ? (data.ps != null ? data.ps : utils.now()) : 0;
|
||||
this.height = data.height != null ? data.height : -1;
|
||||
this.mutable = false;
|
||||
|
||||
this._hash = null;
|
||||
this._whash = null;
|
||||
this._raw = data._raw || null;
|
||||
this._size = data._size || 0;
|
||||
this._witnessSize = data._witnessSize || 0;
|
||||
this._raw = null;
|
||||
this._size = null;
|
||||
this._witnessSize = null;
|
||||
this._outputValue = null;
|
||||
this._inputValue = null;
|
||||
this._hashPrevouts = null;
|
||||
this._hashSequence = null;
|
||||
this._hashOutputs = null;
|
||||
|
||||
for (i = 0; i < data.inputs.length; i++)
|
||||
this.inputs.push(new bcoin.input(data.inputs[i]));
|
||||
@ -182,11 +186,16 @@ TX.prototype.unsetBlock = function unsetBlock() {
|
||||
* @returns {Hash|Buffer} hash
|
||||
*/
|
||||
|
||||
TX.prototype.hash = function hash(enc) {
|
||||
if (!this._hash)
|
||||
this._hash = utils.dsha256(this.renderNormal());
|
||||
TX.prototype.hash = function _hash(enc) {
|
||||
var hash = this._hash;
|
||||
|
||||
return enc === 'hex' ? this._hash.toString('hex') : this._hash;
|
||||
if (!hash) {
|
||||
hash = utils.dsha256(this.renderNormal());
|
||||
if (!this.mutable)
|
||||
this._hash = hash;
|
||||
}
|
||||
|
||||
return enc === 'hex' ? hash.toString('hex') : hash;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -199,6 +208,8 @@ TX.prototype.hash = function hash(enc) {
|
||||
*/
|
||||
|
||||
TX.prototype.witnessHash = function witnessHash(enc) {
|
||||
var hash = this._whash;
|
||||
|
||||
if (this.isCoinbase()) {
|
||||
return enc === 'hex'
|
||||
? constants.NULL_HASH
|
||||
@ -208,10 +219,13 @@ TX.prototype.witnessHash = function witnessHash(enc) {
|
||||
if (!this.hasWitness())
|
||||
return this.hash(enc);
|
||||
|
||||
if (!this._whash)
|
||||
this._whash = utils.dsha256(this.renderWitness());
|
||||
if (!hash) {
|
||||
hash = utils.dsha256(this.renderWitness());
|
||||
if (!this.mutable)
|
||||
this._whash = hash;
|
||||
}
|
||||
|
||||
return enc === 'hex' ? this._whash.toString('hex') : this._whash;
|
||||
return enc === 'hex' ? hash.toString('hex') : hash;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -276,13 +290,32 @@ TX.prototype.getRaw = function getRaw() {
|
||||
else
|
||||
raw = bcoin.protocol.framer.tx(this);
|
||||
|
||||
this._raw = raw;
|
||||
this._size = raw.length;
|
||||
this._witnessSize = raw._witnessSize;
|
||||
if (!this.mutable) {
|
||||
this._raw = raw;
|
||||
this._size = raw.length;
|
||||
this._witnessSize = raw._witnessSize;
|
||||
}
|
||||
|
||||
return raw;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate real size and size of the witness bytes.
|
||||
* @returns {Object} Contains `size` and `witnessSize`.
|
||||
*/
|
||||
|
||||
TX.prototype.getSizes = function getSizes() {
|
||||
if (this.mutable)
|
||||
return bcoin.protocol.framer.tx.sizes(this);
|
||||
|
||||
this.getRaw();
|
||||
|
||||
return {
|
||||
size: this._size,
|
||||
witnessSize: this._witnessSize
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the virtual size of the transaction.
|
||||
* Note that this is cached.
|
||||
@ -301,15 +334,9 @@ TX.prototype.getVirtualSize = function getVirtualSize() {
|
||||
*/
|
||||
|
||||
TX.prototype.getCost = function getCost() {
|
||||
var size, witnessSize, base;
|
||||
|
||||
this.getRaw();
|
||||
|
||||
size = this._size;
|
||||
witnessSize = this._witnessSize;
|
||||
base = size - witnessSize;
|
||||
|
||||
return base * (constants.WITNESS_SCALE_FACTOR - 1) + size;
|
||||
var sizes = this.getSizes();
|
||||
var base = sizes.size - sizes.witnessSize;
|
||||
return base * (constants.WITNESS_SCALE_FACTOR - 1) + sizes.size;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -319,7 +346,7 @@ TX.prototype.getCost = function getCost() {
|
||||
*/
|
||||
|
||||
TX.prototype.getSize = function getSize() {
|
||||
return this.getRaw().length;
|
||||
return this.getSizes().size;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -330,8 +357,8 @@ TX.prototype.getSize = function getSize() {
|
||||
*/
|
||||
|
||||
TX.prototype.getBaseSize = function getBaseSize() {
|
||||
this.getRaw();
|
||||
return this._size - this._witnessSize;
|
||||
var sizes = this.getSizes();
|
||||
return sizes.size - sizes.witnessSize;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -779,6 +779,7 @@ Wallet.prototype.getTX = function getTX(hash, callback) {
|
||||
|
||||
Wallet.prototype.createTX = function createTX(options, outputs, callback) {
|
||||
var self = this;
|
||||
var height = 0xffffffff;
|
||||
var tx, i;
|
||||
|
||||
if (typeof outputs === 'function') {
|
||||
@ -794,6 +795,9 @@ Wallet.prototype.createTX = function createTX(options, outputs, callback) {
|
||||
if (!Array.isArray(outputs))
|
||||
outputs = [outputs];
|
||||
|
||||
if (options.height >= 0)
|
||||
height = options.height;
|
||||
|
||||
// Create mutable tx
|
||||
tx = bcoin.mtx();
|
||||
|
||||
@ -819,7 +823,13 @@ Wallet.prototype.createTX = function createTX(options, outputs, callback) {
|
||||
// if (options.locktime != null)
|
||||
// tx.setLocktime(options.locktime);
|
||||
// else
|
||||
// tx.avoidFeeSniping();
|
||||
// tx.avoidFeeSniping(options.height);
|
||||
|
||||
if (!tx.isSane())
|
||||
return callback(new Error('CheckTransaction failed.'));
|
||||
|
||||
if (!tx.checkInputs(height))
|
||||
return callback(new Error('CheckInputs failed.'));
|
||||
|
||||
// Sign the transaction
|
||||
if (!self.sign(tx))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user