UNPKG

ledger-bitcoin-babylon

Version:

Ledger Hardware Wallet Babylon Application Client

193 lines 18.1 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createTaprootBip322Signature = exports.createSegwitBip322Signature = exports.bip0322Hash = void 0; const ecc = __importStar(require("@bitcoinerlab/secp256k1")); const bitcoinjs_lib_1 = require("bitcoinjs-lib"); const bip32_1 = require("bip32"); const varuint_bitcoin_1 = require("varuint-bitcoin"); const __1 = require("../.."); const _1 = require("./"); const types_1 = require("./types"); const bip32 = (0, bip32_1.BIP32Factory)(ecc); const encodeVarString = (b) => Buffer.concat([(0, varuint_bitcoin_1.encode)(b.byteLength), b]); const DUMMY_INPUT_HASH = Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex'); const DUMMY_INPUT_INDEX = 0xffffffff; const DUMMY_INPUT_SEQUENCE = 0; function bip0322Hash(message) { const { sha256 } = bitcoinjs_lib_1.crypto; const tag = 'BIP0322-signed-message'; const tagHash = sha256(Buffer.from(tag)); const result = sha256(Buffer.concat([tagHash, tagHash, Buffer.from(message)])); return result.toString('hex'); } exports.bip0322Hash = bip0322Hash; const createMessageSignature = async (app, accountPolicy, message, witnessScript, inputArgs, isSegwit) => { const scriptSig = Buffer.concat([ Buffer.from('0020', 'hex'), Buffer.from(bip0322Hash(message), 'hex'), ]); const txToSpend = new bitcoinjs_lib_1.Transaction(); txToSpend.version = 0; txToSpend.addInput(DUMMY_INPUT_HASH, DUMMY_INPUT_INDEX, DUMMY_INPUT_SEQUENCE, scriptSig); txToSpend.addOutput(witnessScript, 0); const psbtToSign = new bitcoinjs_lib_1.Psbt(); psbtToSign.setVersion(0); psbtToSign.addInput(Object.assign({ hash: txToSpend.getHash(), index: 0, sequence: 0, witnessUtxo: { script: witnessScript, value: 0, } }, inputArgs)); psbtToSign.addOutput({ script: Buffer.from('6a', 'hex'), value: 0 }); const signatures = await app.signPsbt(psbtToSign.toBase64(), accountPolicy, null); for (const signature of signatures) { if (isSegwit) { psbtToSign.updateInput(signature[0], { partialSig: [signature[1]], }); } else { psbtToSign.updateInput(signature[0], { tapKeySig: signature[1].signature, }); } } psbtToSign.finalizeAllInputs(); const txToSign = psbtToSign.extractTransaction(); const len = (0, varuint_bitcoin_1.encode)(txToSign.ins[0].witness.length); const result = Buffer.concat([ len, ...txToSign.ins[0].witness.map((w) => encodeVarString(w)), ]); const signature = result.toString('base64'); return { signature, protocol: types_1.MessageSigningProtocols.BIP322, }; }; function getPublicKeyFromXpubAtIndex(xpub, index, isTestnet) { const btcNetwork = isTestnet ? bitcoinjs_lib_1.networks.testnet : bitcoinjs_lib_1.networks.bitcoin; const { publicKey } = bip32 .fromBase58(xpub, btcNetwork) .derivePath(`0/${index}`); return publicKey; } function getNativeSegwitAccountDataFromXpub(xpub, index, isTestnet = false) { (0, bitcoinjs_lib_1.initEccLib)(ecc); const publicKey = getPublicKeyFromXpubAtIndex(xpub, index, isTestnet); const btcNetwork = isTestnet ? bitcoinjs_lib_1.networks.testnet : bitcoinjs_lib_1.networks.bitcoin; const p2wpkh = bitcoinjs_lib_1.payments.p2wpkh({ pubkey: publicKey, network: btcNetwork }); const address = p2wpkh.address; if (!address) { throw new Error('Address is null'); } if (!p2wpkh.output) { throw new Error('p2wpkh output is null'); } return { publicKey, address, witnessScript: p2wpkh.output, }; } async function createSegwitBip322Signature({ message, app, derivationPath = `m/84'/0'/0'`, isTestnet = false, }) { const masterFingerPrint = await app.getMasterFingerprint(); const extendedPublicKey = await app.getExtendedPubkey(derivationPath); const { publicKey, witnessScript } = getNativeSegwitAccountDataFromXpub(extendedPublicKey, 0, isTestnet); const inputDerivation = { path: `${derivationPath}/0/0`, pubkey: publicKey, masterFingerprint: Buffer.from(masterFingerPrint, 'hex'), }; const accountPolicy = new __1.WalletPolicy('Sign message', 'wpkh(@0/**)', [ `[${derivationPath.replace('m/', `${masterFingerPrint}/`)}]${extendedPublicKey}`, ]); return createMessageSignature(app, accountPolicy, message, witnessScript, { bip32Derivation: [inputDerivation], }, true); } exports.createSegwitBip322Signature = createSegwitBip322Signature; function getTaprootAccountDataFromXpub(xpub, index, isTestnet = false) { (0, bitcoinjs_lib_1.initEccLib)(ecc); const publicKey = getPublicKeyFromXpubAtIndex(xpub, index, isTestnet); const p2tr = bitcoinjs_lib_1.payments.p2tr({ internalPubkey: publicKey.slice(1), network: isTestnet ? bitcoinjs_lib_1.networks.testnet : bitcoinjs_lib_1.networks.bitcoin, }); if (!p2tr.output || !p2tr.address || !p2tr.internalPubkey) { throw new Error('p2tr output, address or internalPubkey is null'); } return { publicKey, address: p2tr.address, internalPubkey: p2tr.internalPubkey, taprootScript: p2tr.output, }; } function _padHexString(hexString) { const len = hexString.length / 2; const lenHex = len.toString(16).padStart(2, '0'); let result = lenHex + hexString; const padNeeded = 64 - result.length; if (padNeeded > 0) { result += 'fc'.repeat(padNeeded / 2); } return result; } function _formatMessage(data) { let hexString = ''; for (let i = 0; i < data.length; i += 2) { const firstByte = data[i].toString(16).padStart(2, '0'); const secondByte = i + 1 < data.length ? data[i + 1].toString(16).padStart(2, '0') : ''; hexString += firstByte + secondByte; } return _padHexString(hexString); } async function createTaprootBip322Signature({ message, app, derivationPath = `m/86'/0'/0'`, isTestnet = false, }) { const masterFingerPrint = await app.getMasterFingerprint(); const extendedPublicKey = await app.getExtendedPubkey(derivationPath); const { internalPubkey, taprootScript } = getTaprootAccountDataFromXpub(extendedPublicKey, 0, isTestnet); // Need to update input derivation path so the ledger can recognize the inputs to sign const inputDerivation = { path: `${derivationPath}/0/0`, pubkey: internalPubkey, masterFingerprint: Buffer.from(masterFingerPrint, 'hex'), leafHashes: [], }; const address = (0, _1.validadteAddress)(message); if (!address) { throw new Error('The message should be a valid bbn address.'); } const accountPolicy = new __1.WalletPolicy('Sign message', 'tr(@0/**,and_v(pk_k(@1/**),pk_k(@2/**)))', [ `[${derivationPath.replace('m/', `${masterFingerPrint}/`)}]${extendedPublicKey}`, `[${derivationPath.replace('m/', `${types_1.MagicCode.BIP322_MESSAGE_FP}/`)}]${(0, _1.formatKey)(_formatMessage(address), isTestnet)}`, `[${derivationPath.replace('m/', `${types_1.MagicCode.BIP322_TAP_PUBKEY_FP}/`)}]${(0, _1.formatKey)(taprootScript.slice(2), isTestnet)}`, ]); return createMessageSignature(app, accountPolicy, message, taprootScript, { tapBip32Derivation: [inputDerivation], tapInternalKey: internalPubkey, }, false); } exports.createTaprootBip322Signature = createTaprootBip322Signature; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmlwMzIyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9iYWJ5bG9uL2JpcDMyMi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLDZEQUErQztBQUMvQyxpREFPdUI7QUFDdkIsaUNBQXFDO0FBQ3JDLHFEQUF5QztBQUV6Qyw2QkFBZ0Q7QUFDaEQseUJBQWlEO0FBQ2pELG1DQU1pQjtBQUVqQixNQUFNLEtBQUssR0FBRyxJQUFBLG9CQUFZLEVBQUMsR0FBRyxDQUFDLENBQUM7QUFDaEMsTUFBTSxlQUFlLEdBQUcsQ0FBQyxDQUFTLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFBLHdCQUFNLEVBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDaEYsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUNsQyxrRUFBa0UsRUFDbEUsS0FBSyxDQUNOLENBQUM7QUFDRixNQUFNLGlCQUFpQixHQUFHLFVBQVUsQ0FBQztBQUNyQyxNQUFNLG9CQUFvQixHQUFHLENBQUMsQ0FBQztBQUcvQixTQUFnQixXQUFXLENBQUMsT0FBZTtJQUN6QyxNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsc0JBQU0sQ0FBQztJQUMxQixNQUFNLEdBQUcsR0FBRyx3QkFBd0IsQ0FBQztJQUNyQyxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3pDLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FDbkIsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQ3hELENBQUM7SUFDRixPQUFPLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFD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