better witnessSize.
This commit is contained in:
parent
8755b16235
commit
d53050993c
@ -42,61 +42,58 @@ function Block(data) {
|
||||
utils.inherits(Block, bcoin.abstractblock);
|
||||
|
||||
Block.prototype.render = function render() {
|
||||
if (this._raw) {
|
||||
if (this._witnessSize === 0)
|
||||
return this._raw;
|
||||
return bcoin.protocol.framer.block(this);
|
||||
}
|
||||
return this.getRaw();
|
||||
};
|
||||
|
||||
if (this.hasWitness())
|
||||
return bcoin.protocol.framer.block(this);
|
||||
Block.prototype.renderNormal = function renderNormal() {
|
||||
if (!this._witnessSize)
|
||||
return this._raw;
|
||||
|
||||
this._raw = bcoin.protocol.framer.block(this);
|
||||
this._size = this._raw.length;
|
||||
this._witnessSize = 0;
|
||||
|
||||
return this._raw;
|
||||
return bcoin.protocol.framer.block(this);
|
||||
};
|
||||
|
||||
Block.prototype.renderWitness = function renderWitness() {
|
||||
this.getRaw();
|
||||
|
||||
if (this._witnessSize)
|
||||
return this._raw;
|
||||
|
||||
return bcoin.protocol.framer.witnessBlock(this);
|
||||
};
|
||||
|
||||
Block.prototype.getRaw = function getRaw() {
|
||||
if (this._raw) {
|
||||
if (this._witnessSize > 0)
|
||||
return this._raw;
|
||||
return bcoin.protocol.framer.witnessBlock(this);
|
||||
assert(this._size > 0);
|
||||
assert(this._witnessSize >= 0);
|
||||
return this._raw;
|
||||
}
|
||||
|
||||
if (!this.hasWitness())
|
||||
return bcoin.protocol.framer.witnessBlock(this);
|
||||
if (this.hasWitness())
|
||||
raw = bcoin.protocol.framer.witnessBlock(this);
|
||||
else
|
||||
raw = bcoin.protocol.framer.block(this);
|
||||
|
||||
this._raw = bcoin.protocol.framer.witnessBlock(this);
|
||||
this._size = this._raw.length;
|
||||
this._witnessSize = this._raw._witnessSize;
|
||||
this._raw = raw;
|
||||
this._size = raw.length;
|
||||
this._witnessSize = raw._witnessSize;
|
||||
|
||||
return this._raw;
|
||||
};
|
||||
|
||||
Block.prototype.getBlockSize = function getBlockSize() {
|
||||
var size = this._size;
|
||||
var witnessSize = this._witnessSize;
|
||||
var raw, base;
|
||||
Block.prototype.getVirtualSize = function getVirtualSize() {
|
||||
var size, witnessSize, base;
|
||||
|
||||
if (!this._size) {
|
||||
raw = this.renderWitness();
|
||||
size = raw.length;
|
||||
witnessSize = raw._witnessSize;
|
||||
}
|
||||
this.getRaw();
|
||||
|
||||
// Virtual size:
|
||||
if (witnessSize > 0) {
|
||||
base = size - witnessSize;
|
||||
return (base * 4 + witnessSize + 3) / 4 | 0;
|
||||
}
|
||||
size = this._size;
|
||||
witnessSize = this._witnessSize;
|
||||
base = size - witnessSize;
|
||||
|
||||
return size;
|
||||
return (base * 4 + witnessSize + 3) / 4 | 0;
|
||||
};
|
||||
|
||||
Block.prototype.getSize = function getSize() {
|
||||
return this._raw.length;
|
||||
return this.getRaw().length;
|
||||
};
|
||||
|
||||
Block.prototype.hasWitness = function hasWitness() {
|
||||
@ -186,7 +183,7 @@ Block.prototype._verify = function _verify() {
|
||||
|
||||
// Size can't be bigger than MAX_BLOCK_SIZE
|
||||
if (this.txs.length > constants.block.maxSize
|
||||
|| this.getBlockSize() > constants.block.maxSize) {
|
||||
|| this.getVirtualSize() > constants.block.maxSize) {
|
||||
utils.debug('Block is too large: %s', this.rhash);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -40,6 +40,7 @@ function MTX(options) {
|
||||
this._raw = null;
|
||||
this._size = 0;
|
||||
this._offset = 0;
|
||||
this._witnessSize = 0;
|
||||
|
||||
this.height = -1;
|
||||
|
||||
@ -78,16 +79,32 @@ MTX.prototype.clone = function clone() {
|
||||
};
|
||||
|
||||
MTX.prototype.hash = function hash(enc) {
|
||||
var hash = utils.dsha256(this.render());
|
||||
var hash = utils.dsha256(this.renderNormal());
|
||||
return enc === 'hex' ? utils.toHex(hash) : hash;
|
||||
};
|
||||
|
||||
MTX.prototype.witnessHash = function hash(enc) {
|
||||
var hash = utils.dsha256(this.renderWitness());
|
||||
MTX.prototype.witnessHash = function witnessHash(enc) {
|
||||
var raw, hash;
|
||||
|
||||
if (this.isCoinbase()) {
|
||||
return enc === 'hex'
|
||||
? utils.toHex(constants.zeroHash)
|
||||
: new Buffer(constants.zeroHash);
|
||||
}
|
||||
|
||||
if (!this.hasWitness())
|
||||
return this.hash(enc);
|
||||
|
||||
hash = utils.dsha256(this.renderWitness());
|
||||
|
||||
return enc === 'hex' ? utils.toHex(hash) : hash;
|
||||
};
|
||||
|
||||
MTX.prototype.render = function render() {
|
||||
return this.getRaw();
|
||||
};
|
||||
|
||||
MTX.prototype.renderNormal = function renderNormal() {
|
||||
return bcoin.protocol.framer.tx(this);
|
||||
};
|
||||
|
||||
@ -95,8 +112,24 @@ MTX.prototype.renderWitness = function renderWitness() {
|
||||
return bcoin.protocol.framer.witnessTX(this);
|
||||
};
|
||||
|
||||
MTX.prototype.getRaw = function getRaw() {
|
||||
if (this.hasWitness())
|
||||
return bcoin.protocol.framer.witnessTX(this);
|
||||
|
||||
return bcoin.protocol.framer.tx(this);
|
||||
};
|
||||
|
||||
MTX.prototype.getSize = function getSize() {
|
||||
return this.render().length;
|
||||
return this.getRaw().length;
|
||||
};
|
||||
|
||||
MTX.prototype.getVirtualSize = function getVirtualSize() {
|
||||
var raw = this.getRaw();
|
||||
var size = raw.length;
|
||||
var witnessSize = raw._witnessSize;
|
||||
var base = size - witnessSize;
|
||||
|
||||
return (base * 4 + witnessSize + 3) / 4 | 0;
|
||||
};
|
||||
|
||||
MTX.prototype.addInput = function addInput(options, index) {
|
||||
@ -648,6 +681,7 @@ MTX.prototype.scriptOutput = function scriptOutput(index, options) {
|
||||
MTX.prototype.maxSize = function maxSize(maxM, maxN) {
|
||||
var copy = this.clone();
|
||||
var i, j, input, total, size, prev, m, n;
|
||||
var witness;
|
||||
|
||||
// Create copy with 0-script inputs
|
||||
for (i = 0; i < copy.inputs.length; i++) {
|
||||
@ -661,6 +695,7 @@ MTX.prototype.maxSize = function maxSize(maxM, maxN) {
|
||||
for (i = 0; i < copy.inputs.length; i++) {
|
||||
input = copy.inputs[i];
|
||||
size = 0;
|
||||
witness = false;
|
||||
|
||||
assert(input.output);
|
||||
|
||||
@ -670,18 +705,22 @@ MTX.prototype.maxSize = function maxSize(maxM, maxN) {
|
||||
// If we have access to the redeem script,
|
||||
// we can use it to calculate size much easier.
|
||||
if (this.inputs[i].script.length && bcoin.script.isScripthash(prev)) {
|
||||
prev = bcoin.script.getRedeem(this.inputs[i].script);
|
||||
// Need to add the redeem script size
|
||||
// here since it will be ignored by
|
||||
// the isMultisig clause.
|
||||
// OP_PUSHDATA2 [redeem]
|
||||
size += 3 + bcoin.script.getSize(prev);
|
||||
prev = this.inputs[i].script[this.inputs[i].script.length - 1];
|
||||
size += utils.sizeIntv(prev.length) + prev.length;
|
||||
prev = bcoin.script.decode(prev);
|
||||
}
|
||||
|
||||
if (this.inputs[i].witness.length) {
|
||||
if (bcoin.script.isWitnessScripthash(prev)) {
|
||||
prev = bcoin.script.getRedeem(this.inputs[i].witness);
|
||||
size += 3 + bcoin.script.getSize(prev);
|
||||
if (bcoin.script.isWitnessProgram(prev)) {
|
||||
witness = true;
|
||||
size *= 4;
|
||||
if (this.inputs[i].witness.length && bcoin.script.isWitnessScripthash(prev)) {
|
||||
prev = this.inputs[i].witness[this.inputs[i].witness.length - 1];
|
||||
size += utils.sizeIntv(prev.length) + prev.length;
|
||||
prev = bcoin.script.decode(prev);
|
||||
} else if (bcoin.script.isWitnessPubkeyhash(prev)) {
|
||||
prev = bcoin.script.createPubkeyhash(prev[1]);
|
||||
}
|
||||
@ -744,6 +783,9 @@ MTX.prototype.maxSize = function maxSize(maxM, maxN) {
|
||||
// Byte for varint size of input script
|
||||
size += utils.sizeIntv(size);
|
||||
|
||||
if (witness)
|
||||
size = (size + 3) / 4 | 0;
|
||||
|
||||
total += size;
|
||||
}
|
||||
|
||||
@ -1027,17 +1069,19 @@ MTX.prototype.setLocktime = function setLocktime(locktime) {
|
||||
};
|
||||
|
||||
MTX.prototype.increaseFee = function increaseFee(unspent, address, fee) {
|
||||
var i, input, result;
|
||||
var i, input;
|
||||
|
||||
this.inputs.length = 0;
|
||||
|
||||
if (this.changeIndex !== -1)
|
||||
if (this.changeIndex !== -1) {
|
||||
this.outputs.splice(this.changeIndex, 1);
|
||||
this.changeIndex = -1;
|
||||
}
|
||||
|
||||
if (!fee)
|
||||
fee = this.getFee().add(new bn(10000));
|
||||
|
||||
result = this.fill(unspent, address, fee);
|
||||
this.fill(unspent, address, fee);
|
||||
|
||||
for (i = 0; i < this.inputs.length; i++) {
|
||||
input = this.inputs[i];
|
||||
|
||||
@ -507,6 +507,7 @@ Framer.witnessTX = function _witnessTX(tx) {
|
||||
+ 2
|
||||
+ utils.sizeIntv(tx.inputs.length) + inputSize
|
||||
+ utils.sizeIntv(tx.outputs.length) + outputSize
|
||||
+ utils.sizeIntv(witnesses.length) + witnessSize
|
||||
+ 4);
|
||||
|
||||
off += utils.write32(p, tx.version, off);
|
||||
@ -609,23 +610,18 @@ Framer.witnessBlock = function _witnessBlock(block) {
|
||||
return Framer._block(block, true);
|
||||
};
|
||||
|
||||
Framer._block = function _block(block, witness) {
|
||||
Framer._block = function _block(block, useWitness) {
|
||||
var off = 0;
|
||||
var txSize = 0;
|
||||
var witnessSize = 0;
|
||||
var txs = [];
|
||||
var hasWitness;
|
||||
var i, tx, p;
|
||||
|
||||
for (i = 0; i < block.txs.length; i++) {
|
||||
if (witness) {
|
||||
hasWitness = block.txs[i].hasWitness
|
||||
? block.txs[i].hasWitness()
|
||||
: block.txs[i]._witness;
|
||||
}
|
||||
tx = hasWitness
|
||||
tx = useWitness && bcoin.tx.prototype.hasWitness.call(block.txs[i])
|
||||
? Framer.witnessTX(block.txs[i])
|
||||
: Framer.tx(block.txs[i]);
|
||||
|
||||
txs.push(tx);
|
||||
txSize += tx.length;
|
||||
witnessSize += tx._witnessSize;
|
||||
|
||||
167
lib/bcoin/tx.js
167
lib/bcoin/tx.js
@ -37,6 +37,7 @@ function TX(data, block, index) {
|
||||
this._raw = data._raw || null;
|
||||
this._size = data._size || 0;
|
||||
this._offset = data._offset || 0;
|
||||
this._witnessSize = data._witnessSize || 0;
|
||||
|
||||
this.height = data.height != null ? data.height : -1;
|
||||
|
||||
@ -72,41 +73,18 @@ TX.prototype.setBlock = function setBlock(block, index) {
|
||||
|
||||
TX.prototype.clone = function clone() {
|
||||
var tx = new TX(this);
|
||||
|
||||
// tx.inputs = tx.inputs.map(function(input) {
|
||||
// var _raw = input.script._raw;
|
||||
// input.script = input.script.slice();
|
||||
// if (_raw)
|
||||
// utils.hidden(input.script, '_raw', _raw);
|
||||
// return input;
|
||||
// });
|
||||
|
||||
// tx.outputs = tx.outputs.map(function(output) {
|
||||
// var _raw = output.script._raw;
|
||||
// output.script = output.script.slice();
|
||||
// if (_raw)
|
||||
// utils.hidden(output.script, '_raw', _raw);
|
||||
// return output;
|
||||
// });
|
||||
|
||||
delete tx._raw;
|
||||
delete tx._size;
|
||||
delete tx._offset;
|
||||
delete tx._hash;
|
||||
delete tx._whash;
|
||||
|
||||
delete tx._witnessSize;
|
||||
return tx;
|
||||
};
|
||||
|
||||
TX.prototype.txid = function txid(enc) {
|
||||
if (this.hasWitness())
|
||||
return this.witnessHash(enc);
|
||||
return this.hash(enc);
|
||||
};
|
||||
|
||||
TX.prototype.hash = function hash(enc) {
|
||||
if (!this._hash)
|
||||
this._hash = utils.dsha256(this.render());
|
||||
this._hash = utils.dsha256(this.renderNormal());
|
||||
|
||||
return enc === 'hex' ? utils.toHex(this._hash) : this._hash;
|
||||
};
|
||||
@ -127,6 +105,61 @@ TX.prototype.witnessHash = function witnessHash(enc) {
|
||||
return enc === 'hex' ? utils.toHex(this._whash) : this._whash;
|
||||
};
|
||||
|
||||
TX.prototype.render = function render() {
|
||||
return this.getRaw();
|
||||
};
|
||||
|
||||
TX.prototype.renderNormal = function renderNormal() {
|
||||
var raw = this.getRaw();
|
||||
if (!bcoin.protocol.parser.isWitnessTX(raw))
|
||||
return raw;
|
||||
return bcoin.protocol.framer.tx(this);
|
||||
};
|
||||
|
||||
TX.prototype.renderWitness = function renderWitness() {
|
||||
var raw = this.getRaw();
|
||||
if (bcoin.protocol.parser.isWitnessTX(raw))
|
||||
return raw;
|
||||
return bcoin.protocol.framer.witnessTX(this);
|
||||
};
|
||||
|
||||
TX.prototype.getRaw = function getRaw() {
|
||||
var raw;
|
||||
|
||||
if (this._raw) {
|
||||
assert(this._size > 0);
|
||||
assert(this._witnessSize >= 0);
|
||||
return this._raw;
|
||||
}
|
||||
|
||||
if (this.hasWitness())
|
||||
raw = bcoin.protocol.framer.witnessTX(this);
|
||||
else
|
||||
raw = bcoin.protocol.framer.tx(this);
|
||||
|
||||
this._raw = raw;
|
||||
this._size = raw.length;
|
||||
this._witnessSize = raw._witnessSize;
|
||||
|
||||
return this._raw;
|
||||
};
|
||||
|
||||
TX.prototype.getVirtualSize = function getVirtualSize() {
|
||||
var size, witnessSize, base;
|
||||
|
||||
this.getRaw();
|
||||
|
||||
size = this._size;
|
||||
witnessSize = this._witnessSize;
|
||||
base = size - witnessSize;
|
||||
|
||||
return (base * 4 + witnessSize + 3) / 4 | 0;
|
||||
};
|
||||
|
||||
TX.prototype.getSize = function getSize() {
|
||||
return this.getRaw().length;
|
||||
};
|
||||
|
||||
TX.prototype.hasWitness = function hasWitness() {
|
||||
var i;
|
||||
|
||||
@ -138,46 +171,6 @@ TX.prototype.hasWitness = function hasWitness() {
|
||||
return false;
|
||||
};
|
||||
|
||||
TX.prototype.render = function render() {
|
||||
if (this._raw) {
|
||||
if (!bcoin.protocol.parser.isWitnessTX(this._raw))
|
||||
return this._raw;
|
||||
return bcoin.protocol.framer.tx(this);
|
||||
}
|
||||
|
||||
if (this.hasWitness())
|
||||
return bcoin.protocol.framer.tx(this);
|
||||
|
||||
this._raw = bcoin.protocol.framer.tx(this);
|
||||
this._size = this._raw.length;
|
||||
|
||||
return this._raw;
|
||||
};
|
||||
|
||||
TX.prototype.renderWitness = function renderWitness() {
|
||||
if (this._raw) {
|
||||
if (bcoin.protocol.parser.isWitnessTX(this._raw))
|
||||
return this._raw;
|
||||
// We probably shouldn't even render it
|
||||
// as a witness tx if it doesn't have a witness.
|
||||
return bcoin.protocol.framer.witnessTX(this);
|
||||
}
|
||||
|
||||
// We probably shouldn't even render it
|
||||
// as a witness tx if it doesn't have a witness.
|
||||
if (!this.hasWitness())
|
||||
return bcoin.protocol.framer.witnessTX(this);
|
||||
|
||||
this._raw = bcoin.protocol.framer.witnessTX(this);
|
||||
this._size = this._raw.length;
|
||||
|
||||
return this._raw;
|
||||
};
|
||||
|
||||
TX.prototype.getSize = function getSize() {
|
||||
return this._raw.length;
|
||||
};
|
||||
|
||||
TX.prototype._inputIndex = function _inputIndex(hash, index) {
|
||||
var i, ex;
|
||||
|
||||
@ -212,9 +205,31 @@ TX.prototype.signatureHash = function signatureHash(index, s, type, version) {
|
||||
};
|
||||
|
||||
TX.prototype.signatureHashV0 = function signatureHashV0(index, s, type) {
|
||||
var copy = this.clone();
|
||||
var i, msg, hash;
|
||||
|
||||
var copy = {
|
||||
version: this.version,
|
||||
inputs: [],
|
||||
outputs: [],
|
||||
locktime: this.locktime
|
||||
};
|
||||
|
||||
for (i = 0; i < this.inputs.length; i++) {
|
||||
copy.inputs.push({
|
||||
prevout: this.inputs[i].prevout,
|
||||
script: this.inputs[i].script.slice(),
|
||||
witness: this.inputs[i].witness.slice(),
|
||||
sequence: this.inputs[i].sequence
|
||||
});
|
||||
}
|
||||
|
||||
for (i = 0; i < this.outputs.length; i++) {
|
||||
copy.outputs.push({
|
||||
value: this.outputs[i].value,
|
||||
script: this.outputs[i].script.slice()
|
||||
});
|
||||
}
|
||||
|
||||
if (typeof index !== 'number')
|
||||
index = this.inputs.indexOf(index);
|
||||
|
||||
@ -379,26 +394,6 @@ TX.prototype.signatureHashV1 = function signatureHashV1(index, s, type) {
|
||||
return hash;
|
||||
};
|
||||
|
||||
TX.prototype.normalizedHash = function normalizedHash(enc, force) {
|
||||
var copy = this.clone();
|
||||
var i;
|
||||
|
||||
if (this.isCoinbase())
|
||||
return this.hash(enc);
|
||||
|
||||
if (!this._nhash || force) {
|
||||
for (i = 0; i < copy.inputs.length; i++)
|
||||
copy.inputs[i].script = [];
|
||||
|
||||
copy = bcoin.protocol.framer.tx(copy);
|
||||
this._nhash = utils.dsha256(copy);
|
||||
}
|
||||
|
||||
return enc === 'hex'
|
||||
? utils.toHex(this._nhash)
|
||||
: this._nhash.slice();
|
||||
};
|
||||
|
||||
TX.prototype.verify = function verify(index, force, flags) {
|
||||
// Valid if included in block
|
||||
if (!force && this.ts !== 0)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user