even more size calculation.
This commit is contained in:
parent
6c69914da5
commit
018ce13815
@ -696,12 +696,22 @@ MTX.prototype.isScripted = function isScripted() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
MTX.prototype.maxSize = function maxSize(maxM, maxN, force) {
|
MTX.prototype.maxSize = function maxSize(options, force) {
|
||||||
var i, j, input, total, size, prev, m, n, witness;
|
var i, j, input, total, size, prev, m, n;
|
||||||
|
var witness, hadWitness, redeem, wallet;
|
||||||
|
|
||||||
if (!force && this.isScripted())
|
if (!force && this.isScripted())
|
||||||
return this.getVirtualSize();
|
return this.getVirtualSize();
|
||||||
|
|
||||||
|
if (!options)
|
||||||
|
options = {};
|
||||||
|
|
||||||
|
if (options instanceof bcoin.wallet)
|
||||||
|
options = { wallet: options, m: options.m, n: options.n };
|
||||||
|
|
||||||
|
if (options.wallet)
|
||||||
|
wallet = options.wallet;
|
||||||
|
|
||||||
// Calculate the size, minus the input scripts.
|
// Calculate the size, minus the input scripts.
|
||||||
total = bcoin.protocol.framer.tx.size(this);
|
total = bcoin.protocol.framer.tx.size(this);
|
||||||
|
|
||||||
@ -718,6 +728,8 @@ MTX.prototype.maxSize = function maxSize(maxM, maxN, force) {
|
|||||||
size = 0;
|
size = 0;
|
||||||
witness = false;
|
witness = false;
|
||||||
|
|
||||||
|
// We're out of luck here.
|
||||||
|
// Just assume it's a p2pkh.
|
||||||
if (!input.coin) {
|
if (!input.coin) {
|
||||||
total += 110;
|
total += 110;
|
||||||
continue;
|
continue;
|
||||||
@ -728,24 +740,46 @@ MTX.prototype.maxSize = function maxSize(maxM, maxN, force) {
|
|||||||
|
|
||||||
// If we have access to the redeem script,
|
// If we have access to the redeem script,
|
||||||
// we can use it to calculate size much easier.
|
// we can use it to calculate size much easier.
|
||||||
if (input.script.code.length && prev.isScripthash()) {
|
if (prev.isScripthash()) {
|
||||||
// Need to add the redeem script size
|
// Need to add the redeem script size
|
||||||
// here since it will be ignored by
|
// here since it will be ignored by
|
||||||
// the isMultisig clause.
|
// the isMultisig clause.
|
||||||
// OP_PUSHDATA2 [redeem]
|
// OP_PUSHDATA2 [redeem]
|
||||||
prev = input.script.getRedeem();
|
redeem = wallet
|
||||||
size += 3 + prev.getSize();
|
? wallet.getRedeem(prev.code[1])
|
||||||
|
: input.script.getRedeem();
|
||||||
|
|
||||||
|
if (redeem) {
|
||||||
|
prev = redeem;
|
||||||
|
size += utils.sizePush(prev.getSize());
|
||||||
|
size += prev.getSize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prev.isWitnessProgram()) {
|
if (prev.isWitnessProgram()) {
|
||||||
witness = true;
|
witness = true;
|
||||||
|
|
||||||
// Now calculating vsize. The regular
|
// Now calculating vsize. The regular
|
||||||
// redeem script (if there was one)
|
// redeem script (if there was one)
|
||||||
// is now worth 4 points.
|
// is now worth 4 points.
|
||||||
size *= 4;
|
size *= 4;
|
||||||
if (input.witness.items.length && prev.isWitnessScripthash()) {
|
|
||||||
prev = input.witness.getRedeem();
|
// Add 2 bytes for flag and marker.
|
||||||
size += 3 + prev.getSize();
|
if (!hadWitness)
|
||||||
|
size += 2;
|
||||||
|
|
||||||
|
hadWitness = true;
|
||||||
|
|
||||||
|
if (prev.isWitnessScripthash()) {
|
||||||
|
redeem = wallet
|
||||||
|
? wallet.getRedeem(prev.code[1])
|
||||||
|
: input.witness.getRedeem();
|
||||||
|
|
||||||
|
if (redeem) {
|
||||||
|
prev = redeem;
|
||||||
|
size += utils.sizePush(prev.getSize());
|
||||||
|
size += prev.getSize();
|
||||||
|
}
|
||||||
} else if (prev.isWitnessPubkeyhash()) {
|
} else if (prev.isWitnessPubkeyhash()) {
|
||||||
prev = Script.createPubkeyhash(prev.code[1]);
|
prev = Script.createPubkeyhash(prev.code[1]);
|
||||||
}
|
}
|
||||||
@ -769,7 +803,7 @@ MTX.prototype.maxSize = function maxSize(maxM, maxN, force) {
|
|||||||
size += 1;
|
size += 1;
|
||||||
// OP_PUSHDATA0 [signature] ...
|
// OP_PUSHDATA0 [signature] ...
|
||||||
size += (1 + 73) * m;
|
size += (1 + 73) * m;
|
||||||
} else if (prev.isScripthash()) {
|
} else if (prev.isScripthash() || prev.isWitnessScripthash()) {
|
||||||
// P2SH Multisig
|
// P2SH Multisig
|
||||||
// This technically won't work well for other
|
// This technically won't work well for other
|
||||||
// kinds of P2SH. It will also over-estimate
|
// kinds of P2SH. It will also over-estimate
|
||||||
@ -780,9 +814,9 @@ MTX.prototype.maxSize = function maxSize(maxM, maxN, force) {
|
|||||||
// simply add more of the fee to the change
|
// simply add more of the fee to the change
|
||||||
// output.
|
// output.
|
||||||
// m value
|
// m value
|
||||||
m = maxM || 15;
|
m = options.m || 15;
|
||||||
// n value
|
// n value
|
||||||
n = maxN || 15;
|
n = options.n || 15;
|
||||||
// OP_0
|
// OP_0
|
||||||
size += 1;
|
size += 1;
|
||||||
// OP_PUSHDATA0 [signature] ...
|
// OP_PUSHDATA0 [signature] ...
|
||||||
@ -805,12 +839,15 @@ MTX.prototype.maxSize = function maxSize(maxM, maxN, force) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Byte for varint size of input script.
|
// Byte for varint size of input script or witness.
|
||||||
size += utils.sizeVarint(size);
|
size += utils.sizeVarint(size);
|
||||||
|
|
||||||
// Calculate vsize if we're a witness program.
|
// Calculate vsize if we're a witness program.
|
||||||
if (witness)
|
if (witness) {
|
||||||
|
// Add one byte back for the 0-byte input script.
|
||||||
|
size += 1 * 4;
|
||||||
size = (size + 3) / 4 | 0;
|
size = (size + 3) / 4 | 0;
|
||||||
|
}
|
||||||
|
|
||||||
total += size;
|
total += size;
|
||||||
}
|
}
|
||||||
@ -871,9 +908,6 @@ MTX.prototype.selectCoins = function selectCoins(coins, options) {
|
|||||||
chosen.push(coins[i]);
|
chosen.push(coins[i]);
|
||||||
lastAdded++;
|
lastAdded++;
|
||||||
|
|
||||||
if (options.wallet)
|
|
||||||
options.wallet.scriptInputs(tx, index);
|
|
||||||
|
|
||||||
if (options.selection === 'all')
|
if (options.selection === 'all')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -905,7 +939,7 @@ MTX.prototype.selectCoins = function selectCoins(coins, options) {
|
|||||||
// bytes (10000 satoshi for every 1024 bytes).
|
// bytes (10000 satoshi for every 1024 bytes).
|
||||||
do {
|
do {
|
||||||
// Calculate max possible size after signing.
|
// Calculate max possible size after signing.
|
||||||
size = tx.maxSize(options.m, options.n, true);
|
size = tx.maxSize(options, true);
|
||||||
|
|
||||||
if (tryFree) {
|
if (tryFree) {
|
||||||
if (tx.isFree(network.height + 1, size)) {
|
if (tx.isFree(network.height + 1, size)) {
|
||||||
|
|||||||
@ -1557,6 +1557,19 @@ utils.sizeVarint = function sizeVarint(num) {
|
|||||||
return 9;
|
return 9;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
utils.sizePush = function sizePush(num) {
|
||||||
|
if (num <= 0x4b)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (num <= 0xff)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (num <= 0xffff)
|
||||||
|
return 3;
|
||||||
|
|
||||||
|
return 5;
|
||||||
|
};
|
||||||
|
|
||||||
utils.cmp = function(a, b) {
|
utils.cmp = function(a, b) {
|
||||||
var len, i;
|
var len, i;
|
||||||
|
|
||||||
|
|||||||
@ -59,6 +59,8 @@ function Wallet(options) {
|
|||||||
this.m = options.m || 1;
|
this.m = options.m || 1;
|
||||||
this.n = options.n || 1;
|
this.n = options.n || 1;
|
||||||
|
|
||||||
|
this.cache = new bcoin.lru(20);
|
||||||
|
|
||||||
if (this.n > 1)
|
if (this.n > 1)
|
||||||
this.type = 'multisig';
|
this.type = 'multisig';
|
||||||
|
|
||||||
@ -364,6 +366,9 @@ Wallet.prototype.deriveAddress = function deriveAddress(change, index) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.cache.has(data.path))
|
||||||
|
return this.cache.get(data.path);
|
||||||
|
|
||||||
key = this.accountKey.derive(data.path);
|
key = this.accountKey.derive(data.path);
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
@ -401,6 +406,8 @@ Wallet.prototype.deriveAddress = function deriveAddress(change, index) {
|
|||||||
|
|
||||||
this.emit('add address', address);
|
this.emit('add address', address);
|
||||||
|
|
||||||
|
this.cache.set(data.path, address);
|
||||||
|
|
||||||
return address;
|
return address;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -699,6 +706,32 @@ Wallet.prototype.syncOutputDepth = function syncOutputDepth(tx) {
|
|||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Wallet.prototype.getRedeem = function getRedeem(hash, prefix) {
|
||||||
|
var addr, address;
|
||||||
|
|
||||||
|
if (!prefix) {
|
||||||
|
if (hash.length === 20)
|
||||||
|
prefix = 'scripthash';
|
||||||
|
else if (hash.length === 32)
|
||||||
|
prefix = 'witnessscripthash';
|
||||||
|
else
|
||||||
|
assert(false, 'Unknown hash length.');
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = bcoin.address.compileHash(hash, prefix);
|
||||||
|
address = this.deriveAddress(addr);
|
||||||
|
|
||||||
|
if (!address)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (address.program && hash.length === 20) {
|
||||||
|
if (utils.isEqual(hash, address.programHash))
|
||||||
|
return address.program;
|
||||||
|
}
|
||||||
|
|
||||||
|
return address.script;
|
||||||
|
};
|
||||||
|
|
||||||
Wallet.prototype.scan = function scan(txByAddress, callback) {
|
Wallet.prototype.scan = function scan(txByAddress, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var res = false;
|
var res = false;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user