UNPKG

@trezor/utxo-lib

Version:
126 lines (125 loc) 4.17 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TxWeightCalculator = void 0; const coinselectUtils_1 = require("./coinselect/coinselectUtils"); const _TXSIZE_HEADER = 4; const _TXSIZE_FOOTER = 4; const _TXSIZE_SEGWIT_OVERHEAD = 2; const _TXSIZE_INPUT = 40; const _TXSIZE_OUTPUT = 8; const _TXSIZE_PUBKEY = 33; const _TXSIZE_DER_SIGNATURE = 72; const _TXSIZE_SCHNORR_SIGNATURE = 64; const _TXSIZE_MULTISIGSCRIPT = 3; const _TXSIZE_WITNESSPKHASH = 22; const _TXSIZE_WITNESSSCRIPT = 34; const SCRIPT_TYPES = { p2pkh: 'SPENDADDRESS', p2sh: 'SPENDP2SHWITNESS', p2tr: 'SPENDTAPROOT', p2wpkh: 'SPENDWITNESS' }; const SEGWIT_INPUT_SCRIPT_TYPES = ['SPENDP2SHWITNESS', 'SPENDWITNESS', 'SPENDTAPROOT']; const NONSEGWIT_INPUT_SCRIPT_TYPES = ['SPENDADDRESS', 'SPENDMULTISIG']; function getVarIntSize(length) { if (length < 253) return 1; if (length < 65536) return 3; return 5; } function getOpPushSize(length) { if (length < 76) return 1; if (length < 256) return 2; if (length < 65536) return 3; return 5; } class TxWeightCalculator { inputs_count = 0; outputs_count = 0; counter = 4 * (_TXSIZE_HEADER + _TXSIZE_FOOTER); segwit_inputs_count = 0; inputs = []; addInputByKey(type) { this.addInput({ script_type: SCRIPT_TYPES[type] }); } addInput(input) { this.inputs_count += 1; let input_script_size = 0; if (input.multisig) { if (input.script_type === 'SPENDTAPROOT') { throw new Error('Multisig not supported for Taproot yet'); } const n = input.multisig.nodes ? input.multisig.nodes.length : input.multisig.pubkeys.length; let multisig_script_size = _TXSIZE_MULTISIGSCRIPT + n * (1 + _TXSIZE_PUBKEY); if (SEGWIT_INPUT_SCRIPT_TYPES.includes(input.script_type)) { multisig_script_size += getVarIntSize(multisig_script_size); } else { multisig_script_size += getOpPushSize(multisig_script_size); input_script_size = 1 + input.multisig.m * (1 + _TXSIZE_DER_SIGNATURE) + multisig_script_size; } } else if (input.script_type === 'SPENDTAPROOT') { input_script_size = 1 + _TXSIZE_SCHNORR_SIGNATURE; } else { input_script_size = 1 + _TXSIZE_DER_SIGNATURE + 1 + _TXSIZE_PUBKEY; } this.counter += 4 * _TXSIZE_INPUT; if (NONSEGWIT_INPUT_SCRIPT_TYPES.includes(input.script_type)) { input_script_size += getVarIntSize(input_script_size); this.counter += 4 * input_script_size; } else if (SEGWIT_INPUT_SCRIPT_TYPES.includes(input.script_type)) { this.segwit_inputs_count += 1; if (input.script_type === 'SPENDP2SHWITNESS') { if (input.multisig) { this.counter += 4 * (2 + _TXSIZE_WITNESSSCRIPT); } else { this.counter += 4 * (2 + _TXSIZE_WITNESSPKHASH); } } else { this.counter += 4; } this.counter += 1 + input_script_size; } else if (input.script_type === 'EXTERNAL') { const witness_size = 0; const script_sig_size = 0; if (input.ownership_proof) {} else {} if (witness_size > 1) { this.segwit_inputs_count += 1; } this.counter += 4 * (getVarIntSize(script_sig_size) + script_sig_size); this.counter += witness_size; } else { throw new Error('unknown input script_type'); } this.inputs.push({ length: input_script_size }); } addOutputByKey(key) { this.addOutput({ length: coinselectUtils_1.OUTPUT_SCRIPT_LENGTH[key] }); } addOutput(script) { this.outputs_count += 1; const script_size = getVarIntSize(script.length) + script.length; this.counter += 4 * (_TXSIZE_OUTPUT + script_size); } getTotal() { let total = this.counter; total += 4 * getVarIntSize(this.inputs_count); total += 4 * getVarIntSize(this.outputs_count); if (this.segwit_inputs_count) { total += _TXSIZE_SEGWIT_OVERHEAD; total += this.inputs_count - this.segwit_inputs_count; } return total; } getVirtualBytes() { return Math.ceil(this.getTotal() / 4); } } exports.TxWeightCalculator = TxWeightCalculator; //# sourceMappingURL=txWeightCalculator.js.map