PHP WebShell
Текущая директория: /opt/BitGoJS/modules/utxo-core/src/descriptor
Просмотр файла: VirtualSize.ts
import * as utxolib from '@bitgo/utxo-lib';
import { Dimensions, VirtualSizes } from '@bitgo/unspents';
import { Descriptor } from '@bitgo/wasm-miniscript';
import { DescriptorMap } from './DescriptorMap';
import { findDescriptorForInput } from './psbt';
function getScriptPubKeyLength(descType: string): number {
// See https://bitcoinops.org/en/tools/calc-size/
switch (descType) {
case 'Wpkh':
// https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#p2wpkh
return 22;
case 'Sh':
case 'ShWsh':
case 'ShWpkh':
// https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki#specification
return 23;
case 'Pkh':
return 25;
case 'Wsh':
case 'Tr':
// P2WSH: https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#p2wsh
// P2TR: https://github.com/bitcoin/bips/blob/58ffd93812ff25e87d53d1f202fbb389fdfb85bb/bip-0341.mediawiki#script-validation-rules
// > A Taproot output is a native SegWit output (see BIP141) with version number 1, and a 32-byte witness program.
// 32 bytes for the hash, 1 byte for the version, 1 byte for the push opcode
return 34;
case 'Bare':
throw new Error('cannot determine scriptPubKey length for Bare descriptor');
default:
throw new Error('unexpected descriptor type ' + descType);
}
}
function getInputVSizeForDescriptor(descriptor: Descriptor): number {
// FIXME(BTC-1489): this can overestimate the size of the input significantly
const maxWeight = descriptor.maxWeightToSatisfy();
const maxVSize = Math.ceil(maxWeight / 4);
const sizeOpPushdata1 = 1;
const sizeOpPushdata2 = 2;
return (
// inputId
32 +
// vOut
4 +
// nSequence
4 +
// script overhead
(maxVSize < 255 ? sizeOpPushdata1 : sizeOpPushdata2) +
// script
maxVSize
);
}
export function getInputVSizesForDescriptors(descriptors: DescriptorMap): Record<string, number> {
return Object.fromEntries(
Array.from(descriptors.entries()).map(([name, d]) => {
return [name, getInputVSizeForDescriptor(d)];
})
);
}
export function getChangeOutputVSizesForDescriptor(d: Descriptor): {
inputVSize: number;
outputVSize: number;
} {
return {
inputVSize: getInputVSizeForDescriptor(d),
outputVSize: getScriptPubKeyLength(d.descType()),
};
}
type InputWithDescriptorName = { descriptorName: string };
type OutputWithScript = { script: Buffer };
type Tx<TInput> = {
inputs: TInput[];
outputs: OutputWithScript[];
};
export function getVirtualSize(tx: Tx<Descriptor>): number;
export function getVirtualSize(tx: Tx<InputWithDescriptorName>, descriptors: DescriptorMap): number;
export function getVirtualSize(
tx: Tx<Descriptor> | Tx<InputWithDescriptorName>,
descriptorMap?: DescriptorMap
): number {
const lookup = descriptorMap ? getInputVSizesForDescriptors(descriptorMap) : undefined;
const inputVSize = tx.inputs.reduce((sum, input) => {
if (input instanceof Descriptor) {
return sum + getInputVSizeForDescriptor(input);
}
if ('descriptorName' in input) {
if (!lookup) {
throw new Error('missing descriptorMap');
}
const vsize = lookup[input.descriptorName];
if (!vsize) {
throw new Error(`Could not find descriptor ${input.descriptorName}`);
}
return sum + vsize;
}
throw new Error('unexpected input');
}, 0);
const outputVSize = tx.outputs.reduce((sum, o) => {
return sum + Dimensions.getVSizeForOutputWithScriptLength(o.script.length);
}, 0);
// we will just assume that we have at least one segwit input
return inputVSize + outputVSize + VirtualSizes.txSegOverheadVSize;
}
export function getVirtualSizeEstimateForPsbt(psbt: utxolib.Psbt, descriptorMap: DescriptorMap): number {
const inputs = psbt.data.inputs.map((i) => {
const result = findDescriptorForInput(i, descriptorMap);
if (!result) {
throw new Error('Could not find descriptor for input');
}
return result.descriptor;
});
const outputs = psbt.txOutputs.map((o) => ({ script: o.script }));
return getVirtualSize({ inputs, outputs });
}
Выполнить команду
Для локальной разработки. Не используйте в интернете!