UNPKG

@ledgerhq/hw-app-btc

Version:
103 lines 4.54 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getTrustedInput = exports.getTrustedInputRaw = void 0; const invariant_1 = __importDefault(require("invariant")); const constants_1 = require("./constants"); const varint_1 = require("./varint"); async function getTrustedInputRaw(transport, transactionData, indexLookup) { let data; let firstRound = false; if (typeof indexLookup === "number") { firstRound = true; const prefix = Buffer.alloc(4); prefix.writeUInt32BE(indexLookup, 0); data = Buffer.concat([prefix, transactionData], transactionData.length + 4); } else { data = transactionData; } const trustedInput = await transport.send(0xe0, 0x42, firstRound ? 0x00 : 0x80, 0x00, data); const res = trustedInput.slice(0, trustedInput.length - 2).toString("hex"); return res; } exports.getTrustedInputRaw = getTrustedInputRaw; async function getTrustedInput(transport, indexLookup, transaction, additionals = []) { const { inputs, outputs, locktime, nExpiryHeight, extraData } = transaction; if (!outputs || !locktime) { throw new Error("getTrustedInput: locktime & outputs is expected"); } const isDecred = additionals.includes("decred"); const processScriptBlocks = async (script, sequence) => { const seq = sequence || Buffer.alloc(0); const scriptBlocks = []; let offset = 0; while (offset !== script.length) { const blockSize = script.length - offset > constants_1.MAX_SCRIPT_BLOCK ? constants_1.MAX_SCRIPT_BLOCK : script.length - offset; if (offset + blockSize !== script.length) { scriptBlocks.push(script.slice(offset, offset + blockSize)); } else { scriptBlocks.push(Buffer.concat([script.slice(offset, offset + blockSize), seq])); } offset += blockSize; } // Handle case when no script length: we still want to pass the sequence // relatable: https://github.com/LedgerHQ/ledger-live-desktop/issues/1386 if (script.length === 0) { scriptBlocks.push(seq); } let res; for (const scriptBlock of scriptBlocks) { res = await getTrustedInputRaw(transport, scriptBlock); } return res; }; const processWholeScriptBlock = block => getTrustedInputRaw(transport, block); await getTrustedInputRaw(transport, Buffer.concat([ transaction.version, transaction.timestamp || Buffer.alloc(0), transaction.nVersionGroupId || Buffer.alloc(0), (0, varint_1.createVarint)(inputs.length), ]), indexLookup); for (const input of inputs) { const treeField = isDecred ? input.tree || Buffer.from([0x00]) : Buffer.alloc(0); const data = Buffer.concat([input.prevout, treeField, (0, varint_1.createVarint)(input.script.length)]); await getTrustedInputRaw(transport, data); // iteration (eachSeries) ended // TODO notify progress // deferred.notify("input"); await (isDecred ? processWholeScriptBlock(Buffer.concat([input.script, input.sequence])) : processScriptBlocks(input.script, input.sequence)); } await getTrustedInputRaw(transport, (0, varint_1.createVarint)(outputs.length)); for (const output of outputs) { const data = Buffer.concat([ output.amount, isDecred ? Buffer.from([0x00, 0x00]) : Buffer.alloc(0), //Version script (0, varint_1.createVarint)(output.script.length), output.script, ]); await getTrustedInputRaw(transport, data); } const endData = []; if (nExpiryHeight && nExpiryHeight.length > 0) { endData.push(nExpiryHeight); } if (extraData && extraData.length > 0) { endData.push(extraData); } let extraPart; if (endData.length) { const data = Buffer.concat(endData); extraPart = isDecred ? data : Buffer.concat([(0, varint_1.createVarint)(data.length), data]); } const res = await processScriptBlocks(Buffer.concat([locktime, extraPart || Buffer.alloc(0)])); (0, invariant_1.default)(res, "missing result in processScriptBlocks"); return res; } exports.getTrustedInput = getTrustedInput; //# sourceMappingURL=getTrustedInput.js.map