Socket
Socket
Sign inDemoInstall

bitcoinjs-lib

Package Overview
Dependencies
19
Maintainers
3
Versions
86
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 6.0.2 to 6.1.0-rc.0

src/ecc_lib.d.ts

7

package.json
{
"name": "bitcoinjs-lib",
"version": "6.0.2",
"version": "6.1.0-rc.0",
"description": "Client-side Bitcoin JavaScript library",

@@ -53,3 +53,3 @@ "main": "./src/index.js",

"bech32": "^2.0.0",
"bip174": "^2.0.1",
"bip174": "^2.1.0",
"bs58check": "^2.1.2",

@@ -77,3 +77,2 @@ "create-hash": "^1.1.0",

"bip68": "^1.0.3",
"bn.js": "^4.11.8",
"bs58": "^4.0.0",

@@ -91,3 +90,3 @@ "dhttp": "^3.0.0",

"rimraf": "^2.6.3",
"tiny-secp256k1": "^2.1.2",
"tiny-secp256k1": "^2.2.0",
"ts-node": "^8.3.0",

@@ -94,0 +93,0 @@ "tslint": "^6.1.3",

@@ -68,5 +68,5 @@ # BitcoinJS (bitcoinjs-lib)

Finally, **adhere to best practice**.
We are not an authorative source of best practice, but, at the very least:
We are not an authoritative source of best practice, but, at the very least:
* [Don't re-use addresses](https://en.bitcoin.it/wiki/Address_reuse).
* [Don't reuse addresses](https://en.bitcoin.it/wiki/Address_reuse).
* Don't share BIP32 extended public keys ('xpubs'). [They are a liability](https://bitcoin.stackexchange.com/questions/56916/derivation-of-parent-private-key-from-non-hardened-child), and it only takes 1 misplaced private key (or a buggy implementation!) and you are vulnerable to **catastrophic fund loss**.

@@ -73,0 +73,0 @@ * [Don't use `Math.random`](https://security.stackexchange.com/questions/181580/why-is-math-random-not-designed-to-be-cryptographically-secure) - in any way - don't.

@@ -7,10 +7,9 @@ 'use strict';

const bscript = require('./script');
const types = require('./types');
const types_1 = require('./types');
const bech32_1 = require('bech32');
const bs58check = require('bs58check');
const { typeforce } = types;
const FUTURE_SEGWIT_MAX_SIZE = 40;
const FUTURE_SEGWIT_MIN_SIZE = 2;
const FUTURE_SEGWIT_MAX_VERSION = 16;
const FUTURE_SEGWIT_MIN_VERSION = 1;
const FUTURE_SEGWIT_MIN_VERSION = 2;
const FUTURE_SEGWIT_VERSION_DIFF = 0x50;

@@ -73,3 +72,6 @@ const FUTURE_SEGWIT_VERSION_WARNING =

function toBase58Check(hash, version) {
typeforce(types.tuple(types.Hash160bit, types.UInt8), arguments);
(0, types_1.typeforce)(
(0, types_1.tuple)(types_1.Hash160bit, types_1.UInt8),
arguments,
);
const payload = Buffer.allocUnsafe(21);

@@ -105,2 +107,5 @@ payload.writeUInt8(version, 0);

try {
return payments.p2tr({ output, network }).address;
} catch (e) {}
try {
return _toFutureSegwitAddress(output, network);

@@ -135,2 +140,5 @@ } catch (e) {}

return payments.p2wsh({ hash: decodeBech32.data }).output;
} else if (decodeBech32.version === 1) {
if (decodeBech32.data.length === 32)
return payments.p2tr({ pubkey: decodeBech32.data }).output;
} else if (

@@ -137,0 +145,0 @@ decodeBech32.version >= FUTURE_SEGWIT_MIN_VERSION &&

@@ -15,1 +15,2 @@ import * as address from './address';

export { Input as TxInput, Output as TxOutput } from './transaction';
export { initEccLib } from './ecc_lib';
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
exports.Transaction = exports.opcodes = exports.Psbt = exports.Block = exports.script = exports.payments = exports.networks = exports.crypto = exports.address = void 0;
exports.initEccLib = exports.Transaction = exports.opcodes = exports.Psbt = exports.Block = exports.script = exports.payments = exports.networks = exports.crypto = exports.address = void 0;
const address = require('./address');

@@ -42,1 +42,8 @@ exports.address = address;

});
var ecc_lib_1 = require('./ecc_lib');
Object.defineProperty(exports, 'initEccLib', {
enumerable: true,
get: function() {
return ecc_lib_1.initEccLib;
},
});

@@ -120,2 +120,3 @@ 'use strict';

OP_NOP10: 185,
OP_CHECKSIGADD: 186,
OP_PUBKEYHASH: 253,

@@ -122,0 +123,0 @@ OP_PUBKEY: 254,

/// <reference types="node" />
import { Network } from '../networks';
import { Taptree } from '../types';
import { p2data as embed } from './embed';

@@ -10,2 +11,3 @@ import { p2ms } from './p2ms';

import { p2wsh } from './p2wsh';
import { p2tr } from './p2tr';
export interface Payment {

@@ -21,2 +23,3 @@ name?: string;

signatures?: Buffer[];
internalPubkey?: Buffer;
pubkey?: Buffer;

@@ -27,2 +30,4 @@ signature?: Buffer;

redeem?: Payment;
redeemVersion?: number;
scriptTree?: Taptree;
witness?: Buffer[];

@@ -39,2 +44,2 @@ }

export declare type StackFunction = () => Stack;
export { embed, p2ms, p2pk, p2pkh, p2sh, p2wpkh, p2wsh };
export { embed, p2ms, p2pk, p2pkh, p2sh, p2wpkh, p2wsh, p2tr };
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
exports.p2wsh = exports.p2wpkh = exports.p2sh = exports.p2pkh = exports.p2pk = exports.p2ms = exports.embed = void 0;
exports.p2tr = exports.p2wsh = exports.p2wpkh = exports.p2sh = exports.p2pkh = exports.p2pk = exports.p2ms = exports.embed = void 0;
const embed_1 = require('./embed');

@@ -53,3 +53,10 @@ Object.defineProperty(exports, 'embed', {

});
const p2tr_1 = require('./p2tr');
Object.defineProperty(exports, 'p2tr', {
enumerable: true,
get: function() {
return p2tr_1.p2tr;
},
});
// TODO
// witness commitment

@@ -83,3 +83,6 @@ /// <reference types="node" />

finalizeAllInputs(): this;
finalizeInput(inputIndex: number, finalScriptsFunc?: FinalScriptsFunc): this;
finalizeInput(inputIndex: number, finalScriptsFunc?: FinalScriptsFunc | FinalTaprootScriptsFunc): this;
finalizeTaprootInput(inputIndex: number, tapLeafHashToFinalize?: Buffer, finalScriptsFunc?: FinalTaprootScriptsFunc): this;
private _finalizeInput;
private _finalizeTaprootInput;
getInputType(inputIndex: number): AllScriptType;

@@ -92,2 +95,4 @@ inputHasPubkey(inputIndex: number, pubkey: Buffer): boolean;

validateSignaturesOfInput(inputIndex: number, validator: ValidateSigFunction, pubkey?: Buffer): boolean;
private _validateSignaturesOfInput;
private validateSignaturesOfTaprootInput;
signAllInputsHD(hdKeyPair: HDSigner, sighashTypes?: number[]): this;

@@ -100,3 +105,10 @@ signAllInputsHDAsync(hdKeyPair: HDSigner | HDSignerAsync, sighashTypes?: number[]): Promise<void>;

signInput(inputIndex: number, keyPair: Signer, sighashTypes?: number[]): this;
signTaprootInput(inputIndex: number, keyPair: Signer, tapLeafHashToSign?: Buffer, sighashTypes?: number[]): this;
private _signInput;
private _signTaprootInput;
signInputAsync(inputIndex: number, keyPair: Signer | SignerAsync, sighashTypes?: number[]): Promise<void>;
signTaprootInputAsync(inputIndex: number, keyPair: Signer | SignerAsync, tapLeafHash?: Buffer, sighashTypes?: number[]): Promise<void>;
private _signInputAsync;
private _signTaprootInputAsync;
private checkTaprootHashesForSig;
toBuffer(): Buffer;

@@ -161,2 +173,3 @@ toHex(): string;

sign(hash: Buffer, lowR?: boolean): Buffer;
signSchnorr?(hash: Buffer): Buffer;
getPublicKey?(): Buffer;

@@ -168,2 +181,3 @@ }

sign(hash: Buffer, lowR?: boolean): Promise<Buffer>;
signSchnorr?(hash: Buffer): Promise<Buffer>;
getPublicKey?(): Buffer;

@@ -186,3 +200,8 @@ }

};
declare type FinalTaprootScriptsFunc = (inputIndex: number, // Which input is it?
input: PsbtInput, // The PSBT input contents
tapLeafHashToFinalize?: Buffer) => {
finalScriptWitness: Buffer | undefined;
};
declare type AllScriptType = 'witnesspubkeyhash' | 'pubkeyhash' | 'multisig' | 'pubkey' | 'nonstandard' | 'p2sh-witnesspubkeyhash' | 'p2sh-pubkeyhash' | 'p2sh-multisig' | 'p2sh-pubkey' | 'p2sh-nonstandard' | 'p2wsh-pubkeyhash' | 'p2wsh-multisig' | 'p2wsh-pubkey' | 'p2wsh-nonstandard' | 'p2sh-p2wsh-pubkeyhash' | 'p2sh-p2wsh-multisig' | 'p2sh-p2wsh-pubkey' | 'p2sh-p2wsh-nonstandard';
export {};

@@ -9,7 +9,9 @@ 'use strict';

const bufferutils_1 = require('./bufferutils');
const crypto_1 = require('./crypto');
const networks_1 = require('./networks');
const payments = require('./payments');
const bip341_1 = require('./payments/bip341');
const bscript = require('./script');
const transaction_1 = require('./transaction');
const bip371_1 = require('./psbt/bip371');
const psbtutils_1 = require('./psbt/psbtutils');
/**

@@ -202,2 +204,3 @@ * These are the default arguments for a Psbt instance.

}
(0, bip371_1.checkTaprootInputFields)(inputData, inputData, 'addInput');
checkInputsForPartialSig(this.data.inputs, 'addInput');

@@ -242,2 +245,3 @@ if (inputData.witnessScript) checkInvalidP2WSH(inputData.witnessScript);

}
(0, bip371_1.checkTaprootOutputFields)(outputData, outputData, 'addOutput');
const c = this.__CACHE;

@@ -277,4 +281,29 @@ this.data.addOutput(outputData);

}
finalizeInput(inputIndex, finalScriptsFunc = getFinalScripts) {
finalizeInput(inputIndex, finalScriptsFunc) {
const input = (0, utils_1.checkForInput)(this.data.inputs, inputIndex);
if ((0, bip371_1.isTaprootInput)(input))
return this._finalizeTaprootInput(
inputIndex,
input,
undefined,
finalScriptsFunc,
);
return this._finalizeInput(inputIndex, input, finalScriptsFunc);
}
finalizeTaprootInput(
inputIndex,
tapLeafHashToFinalize,
finalScriptsFunc = bip371_1.tapScriptFinalizer,
) {
const input = (0, utils_1.checkForInput)(this.data.inputs, inputIndex);
if ((0, bip371_1.isTaprootInput)(input))
return this._finalizeTaprootInput(
inputIndex,
input,
tapLeafHashToFinalize,
finalScriptsFunc,
);
throw new Error(`Cannot finalize input #${inputIndex}. Not Taproot.`);
}
_finalizeInput(inputIndex, input, finalScriptsFunc = getFinalScripts) {
const { script, isP2SH, isP2WSH, isSegwit } = getScriptFromInput(

@@ -303,2 +332,33 @@ inputIndex,

}
_finalizeTaprootInput(
inputIndex,
input,
tapLeafHashToFinalize,
finalScriptsFunc = bip371_1.tapScriptFinalizer,
) {
if (!input.witnessUtxo)
throw new Error(
`Cannot finalize input #${inputIndex}. Missing withness utxo.`,
);
// Check key spend first. Increased privacy and reduced block space.
if (input.tapKeySig) {
const payment = payments.p2tr({
output: input.witnessUtxo.script,
signature: input.tapKeySig,
});
const finalScriptWitness = (0, psbtutils_1.witnessStackToScriptWitness)(
payment.witness,
);
this.data.updateInput(inputIndex, { finalScriptWitness });
} else {
const { finalScriptWitness } = finalScriptsFunc(
inputIndex,
input,
tapLeafHashToFinalize,
);
this.data.updateInput(inputIndex, { finalScriptWitness });
}
this.data.clearFinalizedInput(inputIndex);
return this;
}
getInputType(inputIndex) {

@@ -350,2 +410,12 @@ const input = (0, utils_1.checkForInput)(this.data.inputs, inputIndex);

const input = this.data.inputs[inputIndex];
if ((0, bip371_1.isTaprootInput)(input))
return this.validateSignaturesOfTaprootInput(
inputIndex,
validator,
pubkey,
);
return this._validateSignaturesOfInput(inputIndex, validator, pubkey);
}
_validateSignaturesOfInput(inputIndex, validator, pubkey) {
const input = this.data.inputs[inputIndex];
const partialSig = (input || {}).partialSig;

@@ -383,2 +453,50 @@ if (!input || !partialSig || partialSig.length < 1)

}
validateSignaturesOfTaprootInput(inputIndex, validator, pubkey) {
const input = this.data.inputs[inputIndex];
const tapKeySig = (input || {}).tapKeySig;
const tapScriptSig = (input || {}).tapScriptSig;
if (!input && !tapKeySig && !(tapScriptSig && !tapScriptSig.length))
throw new Error('No signatures to validate');
if (typeof validator !== 'function')
throw new Error('Need validator function to validate signatures');
pubkey = pubkey && (0, bip371_1.toXOnly)(pubkey);
const allHashses = pubkey
? getTaprootHashesForSig(
inputIndex,
input,
this.data.inputs,
pubkey,
this.__CACHE,
)
: getAllTaprootHashesForSig(
inputIndex,
input,
this.data.inputs,
this.__CACHE,
);
if (!allHashses.length) throw new Error('No signatures for this pubkey');
const tapKeyHash = allHashses.find(h => !!h.leafHash);
if (tapKeySig && tapKeyHash) {
const isValidTapkeySig = validator(
tapKeyHash.pubkey,
tapKeyHash.hash,
tapKeySig,
);
if (!isValidTapkeySig) return false;
}
if (tapScriptSig) {
for (const tapSig of tapScriptSig) {
const tapSigHash = allHashses.find(h => tapSig.pubkey.equals(h.pubkey));
if (tapSigHash) {
const isValidTapScriptSig = validator(
tapSig.pubkey,
tapSigHash.hash,
tapSig.signature,
);
if (!isValidTapScriptSig) return false;
}
}
}
return true;
}
signAllInputsHD(

@@ -467,6 +585,3 @@ hdKeyPair,

}
signAllInputs(
keyPair,
sighashTypes = [transaction_1.Transaction.SIGHASH_ALL],
) {
signAllInputs(keyPair, sighashTypes) {
if (!keyPair || !keyPair.publicKey)

@@ -491,6 +606,3 @@ throw new Error('Need Signer to sign input');

}
signAllInputsAsync(
keyPair,
sighashTypes = [transaction_1.Transaction.SIGHASH_ALL],
) {
signAllInputsAsync(keyPair, sighashTypes) {
return new Promise((resolve, reject) => {

@@ -524,3 +636,32 @@ if (!keyPair || !keyPair.publicKey)

}
signInput(
signInput(inputIndex, keyPair, sighashTypes) {
if (!keyPair || !keyPair.publicKey)
throw new Error('Need Signer to sign input');
const input = (0, utils_1.checkForInput)(this.data.inputs, inputIndex);
if ((0, bip371_1.isTaprootInput)(input)) {
return this._signTaprootInput(
inputIndex,
input,
keyPair,
undefined,
sighashTypes,
);
}
return this._signInput(inputIndex, keyPair, sighashTypes);
}
signTaprootInput(inputIndex, keyPair, tapLeafHashToSign, sighashTypes) {
if (!keyPair || !keyPair.publicKey)
throw new Error('Need Signer to sign input');
const input = (0, utils_1.checkForInput)(this.data.inputs, inputIndex);
if ((0, bip371_1.isTaprootInput)(input))
return this._signTaprootInput(
inputIndex,
input,
keyPair,
tapLeafHashToSign,
sighashTypes,
);
throw new Error(`Input #${inputIndex} is not of type Taproot.`);
}
_signInput(
inputIndex,

@@ -530,4 +671,2 @@ keyPair,

) {
if (!keyPair || !keyPair.publicKey)
throw new Error('Need Signer to sign input');
const { hash, sighashType } = getHashAndSighashType(

@@ -549,28 +688,178 @@ this.data.inputs,

}
signInputAsync(
_signTaprootInput(
inputIndex,
input,
keyPair,
sighashTypes = [transaction_1.Transaction.SIGHASH_ALL],
tapLeafHashToSign,
allowedSighashTypes = [transaction_1.Transaction.SIGHASH_DEFAULT],
) {
const hashesForSig = this.checkTaprootHashesForSig(
inputIndex,
input,
keyPair,
tapLeafHashToSign,
allowedSighashTypes,
);
const tapKeySig = hashesForSig
.filter(h => !h.leafHash)
.map(h =>
(0, bip371_1.serializeTaprootSignature)(
keyPair.signSchnorr(h.hash),
input.sighashType,
),
)[0];
const tapScriptSig = hashesForSig
.filter(h => !!h.leafHash)
.map(h => ({
pubkey: (0, bip371_1.toXOnly)(keyPair.publicKey),
signature: (0, bip371_1.serializeTaprootSignature)(
keyPair.signSchnorr(h.hash),
input.sighashType,
),
leafHash: h.leafHash,
}));
if (tapKeySig) {
this.data.updateInput(inputIndex, { tapKeySig });
}
if (tapScriptSig.length) {
this.data.updateInput(inputIndex, { tapScriptSig });
}
return this;
}
signInputAsync(inputIndex, keyPair, sighashTypes) {
return Promise.resolve().then(() => {
if (!keyPair || !keyPair.publicKey)
throw new Error('Need Signer to sign input');
const { hash, sighashType } = getHashAndSighashType(
this.data.inputs,
inputIndex,
keyPair.publicKey,
this.__CACHE,
sighashTypes,
);
return Promise.resolve(keyPair.sign(hash)).then(signature => {
const partialSig = [
{
pubkey: keyPair.publicKey,
signature: bscript.signature.encode(signature, sighashType),
const input = (0, utils_1.checkForInput)(this.data.inputs, inputIndex);
if ((0, bip371_1.isTaprootInput)(input))
return this._signTaprootInputAsync(
inputIndex,
input,
keyPair,
undefined,
sighashTypes,
);
return this._signInputAsync(inputIndex, keyPair, sighashTypes);
});
}
signTaprootInputAsync(inputIndex, keyPair, tapLeafHash, sighashTypes) {
return Promise.resolve().then(() => {
if (!keyPair || !keyPair.publicKey)
throw new Error('Need Signer to sign input');
const input = (0, utils_1.checkForInput)(this.data.inputs, inputIndex);
if ((0, bip371_1.isTaprootInput)(input))
return this._signTaprootInputAsync(
inputIndex,
input,
keyPair,
tapLeafHash,
sighashTypes,
);
throw new Error(`Input #${inputIndex} is not of type Taproot.`);
});
}
_signInputAsync(
inputIndex,
keyPair,
sighashTypes = [transaction_1.Transaction.SIGHASH_ALL],
) {
const { hash, sighashType } = getHashAndSighashType(
this.data.inputs,
inputIndex,
keyPair.publicKey,
this.__CACHE,
sighashTypes,
);
return Promise.resolve(keyPair.sign(hash)).then(signature => {
const partialSig = [
{
pubkey: keyPair.publicKey,
signature: bscript.signature.encode(signature, sighashType),
},
];
this.data.updateInput(inputIndex, { partialSig });
});
}
async _signTaprootInputAsync(
inputIndex,
input,
keyPair,
tapLeafHash,
sighashTypes = [transaction_1.Transaction.SIGHASH_DEFAULT],
) {
const hashesForSig = this.checkTaprootHashesForSig(
inputIndex,
input,
keyPair,
tapLeafHash,
sighashTypes,
);
const signaturePromises = [];
const tapKeyHash = hashesForSig.filter(h => !h.leafHash)[0];
if (tapKeyHash) {
const tapKeySigPromise = Promise.resolve(
keyPair.signSchnorr(tapKeyHash.hash),
).then(sig => {
return {
tapKeySig: (0, bip371_1.serializeTaprootSignature)(
sig,
input.sighashType,
),
};
});
signaturePromises.push(tapKeySigPromise);
}
const tapScriptHashes = hashesForSig.filter(h => !!h.leafHash);
if (tapScriptHashes.length) {
const tapScriptSigPromises = tapScriptHashes.map(tsh => {
return Promise.resolve(keyPair.signSchnorr(tsh.hash)).then(
signature => {
const tapScriptSig = [
{
pubkey: (0, bip371_1.toXOnly)(keyPair.publicKey),
signature: (0, bip371_1.serializeTaprootSignature)(
signature,
input.sighashType,
),
leafHash: tsh.leafHash,
},
];
return { tapScriptSig };
},
];
this.data.updateInput(inputIndex, { partialSig });
);
});
signaturePromises.push(...tapScriptSigPromises);
}
return Promise.all(signaturePromises).then(results => {
results.forEach(v => this.data.updateInput(inputIndex, v));
});
}
checkTaprootHashesForSig(
inputIndex,
input,
keyPair,
tapLeafHashToSign,
allowedSighashTypes,
) {
if (typeof keyPair.signSchnorr !== 'function')
throw new Error(
`Need Schnorr Signer to sign taproot input #${inputIndex}.`,
);
const hashesForSig = getTaprootHashesForSig(
inputIndex,
input,
this.data.inputs,
keyPair.publicKey,
this.__CACHE,
tapLeafHashToSign,
allowedSighashTypes,
);
if (!hashesForSig || !hashesForSig.length)
throw new Error(
`Can not sign for input #${inputIndex} with the key ${keyPair.publicKey.toString(
'hex',
)}`,
);
return hashesForSig;
}
toBuffer() {

@@ -594,2 +883,7 @@ checkCache(this.__CACHE);

if (updateData.witnessScript) checkInvalidP2WSH(updateData.witnessScript);
(0, bip371_1.checkTaprootInputFields)(
this.data.inputs[inputIndex],
updateData,
'updateInput',
);
this.data.updateInput(inputIndex, updateData);

@@ -606,2 +900,8 @@ if (updateData.nonWitnessUtxo) {

updateOutput(outputIndex, updateData) {
const outputData = this.data.outputs[outputIndex];
(0, bip371_1.checkTaprootOutputFields)(
outputData,
updateData,
'updateOutput',
);
this.data.updateOutput(outputIndex, updateData);

@@ -720,18 +1020,2 @@ return this;

}
function isPaymentFactory(payment) {
return script => {
try {
payment({ output: script });
return true;
} catch (err) {
return false;
}
};
}
const isP2MS = isPaymentFactory(payments.p2ms);
const isP2PK = isPaymentFactory(payments.p2pk);
const isP2PKH = isPaymentFactory(payments.p2pkh);
const isP2WPKH = isPaymentFactory(payments.p2wpkh);
const isP2WSHScript = isPaymentFactory(payments.p2wsh);
const isP2SHScript = isPaymentFactory(payments.p2sh);
function bip32DerivationIsMine(root) {

@@ -770,33 +1054,7 @@ return d => {

inputs.forEach(input => {
let throws = false;
let pSigs = [];
if ((input.partialSig || []).length === 0) {
if (!input.finalScriptSig && !input.finalScriptWitness) return;
pSigs = getPsigsFromInputFinalScripts(input);
} else {
pSigs = input.partialSig;
}
pSigs.forEach(pSig => {
const { hashType } = bscript.signature.decode(pSig.signature);
const whitelist = [];
const isAnyoneCanPay =
hashType & transaction_1.Transaction.SIGHASH_ANYONECANPAY;
if (isAnyoneCanPay) whitelist.push('addInput');
const hashMod = hashType & 0x1f;
switch (hashMod) {
case transaction_1.Transaction.SIGHASH_ALL:
break;
case transaction_1.Transaction.SIGHASH_SINGLE:
case transaction_1.Transaction.SIGHASH_NONE:
whitelist.push('addOutput');
whitelist.push('setInputSequence');
break;
}
if (whitelist.indexOf(action) === -1) {
throws = true;
}
});
if (throws) {
const throws = (0, bip371_1.isTaprootInput)(input)
? (0, bip371_1.checkTaprootInputForSigs)(input, action)
: (0, psbtutils_1.checkInputForSig)(input, action);
if (throws)
throw new Error('Can not modify transaction, signatures exist.');
}
});

@@ -815,3 +1073,3 @@ }

function checkScriptForPubkey(pubkey, script, action) {
if (!pubkeyInScript(pubkey, script)) {
if (!(0, psbtutils_1.pubkeyInScript)(pubkey, script)) {
throw new Error(

@@ -910,5 +1168,9 @@ `Can not ${action} for this input with the key ${pubkey.toString('hex')}`,

if (p2wsh) {
finalScriptWitness = witnessStackToScriptWitness(p2wsh.witness);
finalScriptWitness = (0, psbtutils_1.witnessStackToScriptWitness)(
p2wsh.witness,
);
} else {
finalScriptWitness = witnessStackToScriptWitness(payment.witness);
finalScriptWitness = (0, psbtutils_1.witnessStackToScriptWitness)(
payment.witness,
);
}

@@ -955,9 +1217,3 @@ if (p2sh) {

input.sighashType || transaction_1.Transaction.SIGHASH_ALL;
if (sighashTypes && sighashTypes.indexOf(sighashType) < 0) {
const str = sighashTypeToString(sighashType);
throw new Error(
`Sighash type is not allowed. Retry the sign method passing the ` +
`sighashTypes array of whitelisted types. Sighash type: ${str}`,
);
}
checkSighashTypeAllowed(sighashType, sighashTypes);
let hash;

@@ -1000,3 +1256,3 @@ let prevout;

);
} else if (isP2WPKH(meaningfulScript)) {
} else if ((0, psbtutils_1.isP2WPKH)(meaningfulScript)) {
// P2WPKH uses the P2PKH template for prevoutScript when signing

@@ -1043,2 +1299,85 @@ const signingScript = payments.p2pkh({ hash: meaningfulScript.slice(2) })

}
function getAllTaprootHashesForSig(inputIndex, input, inputs, cache) {
const allPublicKeys = [];
if (input.tapInternalKey) {
const outputKey = (0, bip371_1.tweakInternalPubKey)(inputIndex, input);
allPublicKeys.push(outputKey);
}
if (input.tapScriptSig) {
const tapScriptPubkeys = input.tapScriptSig.map(tss => tss.pubkey);
allPublicKeys.push(...tapScriptPubkeys);
}
const allHashes = allPublicKeys.map(pubicKey =>
getTaprootHashesForSig(inputIndex, input, inputs, pubicKey, cache),
);
return allHashes.flat();
}
function getTaprootHashesForSig(
inputIndex,
input,
inputs,
pubkey,
cache,
tapLeafHashToSign,
allowedSighashTypes,
) {
const unsignedTx = cache.__TX;
const sighashType =
input.sighashType || transaction_1.Transaction.SIGHASH_DEFAULT;
checkSighashTypeAllowed(sighashType, allowedSighashTypes);
const prevOuts = inputs.map((i, index) =>
getScriptAndAmountFromUtxo(index, i, cache),
);
const signingScripts = prevOuts.map(o => o.script);
const values = prevOuts.map(o => o.value);
const hashes = [];
if (input.tapInternalKey && !tapLeafHashToSign) {
const outputKey = (0, bip371_1.tweakInternalPubKey)(inputIndex, input);
if ((0, bip371_1.toXOnly)(pubkey).equals(outputKey)) {
const tapKeyHash = unsignedTx.hashForWitnessV1(
inputIndex,
signingScripts,
values,
sighashType,
);
hashes.push({ pubkey, hash: tapKeyHash });
}
}
const tapLeafHashes = (input.tapLeafScript || [])
.filter(tapLeaf => (0, psbtutils_1.pubkeyInScript)(pubkey, tapLeaf.script))
.map(tapLeaf => {
const hash = (0, bip341_1.tapleafHash)({
output: tapLeaf.script,
version: tapLeaf.leafVersion,
});
return Object.assign({ hash }, tapLeaf);
})
.filter(
tapLeaf => !tapLeafHashToSign || tapLeafHashToSign.equals(tapLeaf.hash),
)
.map(tapLeaf => {
const tapScriptHash = unsignedTx.hashForWitnessV1(
inputIndex,
signingScripts,
values,
transaction_1.Transaction.SIGHASH_DEFAULT,
tapLeaf.hash,
);
return {
pubkey,
hash: tapScriptHash,
leafHash: tapLeaf.hash,
};
});
return hashes.concat(tapLeafHashes);
}
function checkSighashTypeAllowed(sighashType, sighashTypes) {
if (sighashTypes && sighashTypes.indexOf(sighashType) < 0) {
const str = sighashTypeToString(sighashType);
throw new Error(
`Sighash type is not allowed. Retry the sign method passing the ` +
`sighashTypes array of whitelisted types. Sighash type: ${str}`,
);
}
}
function getPayment(script, scriptType, partialSig) {

@@ -1077,16 +1416,2 @@ let payment;

}
function getPsigsFromInputFinalScripts(input) {
const scriptItems = !input.finalScriptSig
? []
: bscript.decompile(input.finalScriptSig) || [];
const witnessItems = !input.finalScriptWitness
? []
: bscript.decompile(input.finalScriptWitness) || [];
return scriptItems
.concat(witnessItems)
.filter(item => {
return Buffer.isBuffer(item) && bscript.isCanonicalScriptSignature(item);
})
.map(sig => ({ signature: sig }));
}
function getScriptFromInput(inputIndex, input, cache) {

@@ -1119,3 +1444,3 @@ const unsignedTx = cache.__TX;

}
if (input.witnessScript || isP2WPKH(res.script)) {
if (input.witnessScript || (0, psbtutils_1.isP2WPKH)(res.script)) {
res.isSegwit = true;

@@ -1210,24 +1535,2 @@ }

}
function witnessStackToScriptWitness(witness) {
let buffer = Buffer.allocUnsafe(0);
function writeSlice(slice) {
buffer = Buffer.concat([buffer, Buffer.from(slice)]);
}
function writeVarInt(i) {
const currentLen = buffer.length;
const varintLen = varuint.encodingLength(i);
buffer = Buffer.concat([buffer, Buffer.allocUnsafe(varintLen)]);
varuint.encode(i, buffer, currentLen);
}
function writeVarSlice(slice) {
writeVarInt(slice.length);
writeSlice(slice);
}
function writeVector(vector) {
writeVarInt(vector.length);
vector.forEach(writeVarSlice);
}
writeVector(witness);
return buffer;
}
function addNonWitnessTxCache(cache, input, inputIndex) {

@@ -1295,4 +1598,11 @@ cache.__NON_WITNESS_UTXO_BUF_CACHE[inputIndex] = input.nonWitnessUtxo;

function getScriptFromUtxo(inputIndex, input, cache) {
const { script } = getScriptAndAmountFromUtxo(inputIndex, input, cache);
return script;
}
function getScriptAndAmountFromUtxo(inputIndex, input, cache) {
if (input.witnessUtxo !== undefined) {
return input.witnessUtxo.script;
return {
script: input.witnessUtxo.script,
value: input.witnessUtxo.value,
};
} else if (input.nonWitnessUtxo !== undefined) {

@@ -1304,3 +1614,4 @@ const nonWitnessUtxoTx = nonWitnessUtxoTxFromCache(

);
return nonWitnessUtxoTx.outs[cache.__TX.ins[inputIndex].index].script;
const o = nonWitnessUtxoTx.outs[cache.__TX.ins[inputIndex].index];
return { script: o.script, value: o.value };
} else {

@@ -1319,3 +1630,3 @@ throw new Error("Can't find pubkey in input without Utxo data");

);
return pubkeyInScript(pubkey, meaningfulScript);
return (0, psbtutils_1.pubkeyInScript)(pubkey, meaningfulScript);
}

@@ -1331,3 +1642,3 @@ function pubkeyInOutput(pubkey, output, outputIndex, cache) {

);
return pubkeyInScript(pubkey, meaningfulScript);
return (0, psbtutils_1.pubkeyInScript)(pubkey, meaningfulScript);
}

@@ -1380,5 +1691,6 @@ function redeemFromFinalScriptSig(finalScript) {

) {
const isP2SH = isP2SHScript(script);
const isP2SHP2WSH = isP2SH && redeemScript && isP2WSHScript(redeemScript);
const isP2WSH = isP2WSHScript(script);
const isP2SH = (0, psbtutils_1.isP2SHScript)(script);
const isP2SHP2WSH =
isP2SH && redeemScript && (0, psbtutils_1.isP2WSHScript)(redeemScript);
const isP2WSH = (0, psbtutils_1.isP2WSHScript)(script);
if (isP2SH && redeemScript === undefined)

@@ -1418,20 +1730,14 @@ throw new Error('scriptPubkey is P2SH but redeemScript missing');

function checkInvalidP2WSH(script) {
if (isP2WPKH(script) || isP2SHScript(script)) {
if (
(0, psbtutils_1.isP2WPKH)(script) ||
(0, psbtutils_1.isP2SHScript)(script)
) {
throw new Error('P2WPKH or P2SH can not be contained within P2WSH');
}
}
function pubkeyInScript(pubkey, script) {
const pubkeyHash = (0, crypto_1.hash160)(pubkey);
const decompiled = bscript.decompile(script);
if (decompiled === null) throw new Error('Unknown script error');
return decompiled.some(element => {
if (typeof element === 'number') return false;
return element.equals(pubkey) || element.equals(pubkeyHash);
});
}
function classifyScript(script) {
if (isP2WPKH(script)) return 'witnesspubkeyhash';
if (isP2PKH(script)) return 'pubkeyhash';
if (isP2MS(script)) return 'multisig';
if (isP2PK(script)) return 'pubkey';
if ((0, psbtutils_1.isP2WPKH)(script)) return 'witnesspubkeyhash';
if ((0, psbtutils_1.isP2PKH)(script)) return 'pubkeyhash';
if ((0, psbtutils_1.isP2MS)(script)) return 'multisig';
if ((0, psbtutils_1.isP2PK)(script)) return 'pubkey';
return 'nonstandard';

@@ -1438,0 +1744,0 @@ }

@@ -13,2 +13,25 @@ /// <reference types="node" />

export declare const Network: any;
export interface XOnlyPointAddTweakResult {
parity: 1 | 0;
xOnlyPubkey: Uint8Array;
}
export interface Tapleaf {
output: Buffer;
version?: number;
}
export declare const TAPLEAF_VERSION_MASK = 254;
export declare function isTapleaf(o: any): o is Tapleaf;
/**
* Binary tree repsenting script path spends for a Taproot input.
* Each node is either a single Tapleaf, or a pair of Tapleaf | Taptree.
* The tree has no balancing requirements.
*/
export declare type Taptree = [Taptree | Tapleaf, Taptree | Tapleaf] | Tapleaf;
export declare function isTaptree(scriptTree: any): scriptTree is Taptree;
export interface TinySecp256k1Interface {
isXOnlyPoint(p: Uint8Array): boolean;
xOnlyPointAddTweak(p: Uint8Array, tweak: Uint8Array): XOnlyPointAddTweakResult | null;
privateAdd(d: Uint8Array, tweak: Uint8Array): Uint8Array | null;
privateNegate(d: Uint8Array): Uint8Array;
}
export declare const Buffer256bit: any;

@@ -15,0 +38,0 @@ export declare const Hash160bit: any;

'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
exports.oneOf = exports.Null = exports.BufferN = exports.Function = exports.UInt32 = exports.UInt8 = exports.tuple = exports.maybe = exports.Hex = exports.Buffer = exports.String = exports.Boolean = exports.Array = exports.Number = exports.Hash256bit = exports.Hash160bit = exports.Buffer256bit = exports.Network = exports.ECPoint = exports.Satoshi = exports.Signer = exports.BIP32Path = exports.UInt31 = exports.isPoint = exports.typeforce = void 0;
exports.oneOf = exports.Null = exports.BufferN = exports.Function = exports.UInt32 = exports.UInt8 = exports.tuple = exports.maybe = exports.Hex = exports.Buffer = exports.String = exports.Boolean = exports.Array = exports.Number = exports.Hash256bit = exports.Hash160bit = exports.Buffer256bit = exports.isTaptree = exports.isTapleaf = exports.TAPLEAF_VERSION_MASK = exports.Network = exports.ECPoint = exports.Satoshi = exports.Signer = exports.BIP32Path = exports.UInt31 = exports.isPoint = exports.typeforce = void 0;
const buffer_1 = require('buffer');

@@ -71,2 +71,17 @@ exports.typeforce = require('typeforce');

});
exports.TAPLEAF_VERSION_MASK = 0xfe;
function isTapleaf(o) {
if (!o || !('output' in o)) return false;
if (!buffer_1.Buffer.isBuffer(o.output)) return false;
if (o.version !== undefined)
return (o.version & exports.TAPLEAF_VERSION_MASK) === o.version;
return true;
}
exports.isTapleaf = isTapleaf;
function isTaptree(scriptTree) {
if (!(0, exports.Array)(scriptTree)) return isTapleaf(scriptTree);
if (scriptTree.length !== 2) return false;
return scriptTree.every(t => isTaptree(t));
}
exports.isTaptree = isTaptree;
exports.Buffer256bit = exports.typeforce.BufferN(32);

@@ -73,0 +88,0 @@ exports.Hash160bit = exports.typeforce.BufferN(20);

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc