Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@ledgerhq/hw-app-btc

Package Overview
Dependencies
Maintainers
7
Versions
437
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ledgerhq/hw-app-btc - npm Package Compare versions

Comparing version 2.1.3 to 2.2.0-beta.9d29a5c6

flow-typed/npm/create-hash_vx.x.x.js

32

flow-typed/npm/@ledgerhq/hw-transport_vx.x.x.js

@@ -1,3 +0,3 @@

// flow-typed signature: 559e6d9e212eae61339873c83e1b86ad
// flow-typed version: <<STUB>>/@ledgerhq/hw-transport_v^2.0.5/flow_v0.63.1
// flow-typed signature: 75d330203ebfe98a2c99295790ffe07c
// flow-typed version: <<STUB>>/@ledgerhq/hw-transport_v^2.1.0/flow_v0.63.1

@@ -25,2 +25,18 @@ /**

*/
declare module '@ledgerhq/hw-transport/flow-typed/npm/events_vx.x.x' {
declare module.exports: any;
}
declare module '@ledgerhq/hw-transport/flow-typed/npm/flow-bin_v0.x.x' {
declare module.exports: any;
}
declare module '@ledgerhq/hw-transport/flow-typed/npm/flow-typed_vx.x.x' {
declare module.exports: any;
}
declare module '@ledgerhq/hw-transport/flow-typed/npm/invariant_v2.x.x' {
declare module.exports: any;
}
declare module '@ledgerhq/hw-transport/src/Transport' {

@@ -31,4 +47,16 @@ declare module.exports: any;

// Filename aliases
declare module '@ledgerhq/hw-transport/flow-typed/npm/events_vx.x.x.js' {
declare module.exports: $Exports<'@ledgerhq/hw-transport/flow-typed/npm/events_vx.x.x'>;
}
declare module '@ledgerhq/hw-transport/flow-typed/npm/flow-bin_v0.x.x.js' {
declare module.exports: $Exports<'@ledgerhq/hw-transport/flow-typed/npm/flow-bin_v0.x.x'>;
}
declare module '@ledgerhq/hw-transport/flow-typed/npm/flow-typed_vx.x.x.js' {
declare module.exports: $Exports<'@ledgerhq/hw-transport/flow-typed/npm/flow-typed_vx.x.x'>;
}
declare module '@ledgerhq/hw-transport/flow-typed/npm/invariant_v2.x.x.js' {
declare module.exports: $Exports<'@ledgerhq/hw-transport/flow-typed/npm/invariant_v2.x.x'>;
}
declare module '@ledgerhq/hw-transport/src/Transport.js' {
declare module.exports: $Exports<'@ledgerhq/hw-transport/src/Transport'>;
}

289

lib/Btc.js

@@ -7,6 +7,10 @@ "use strict";

var _promise = require("babel-runtime/core-js/promise");
var _regenerator = require("babel-runtime/regenerator");
var _promise2 = _interopRequireDefault(_promise);
var _regenerator2 = _interopRequireDefault(_regenerator);
var _asyncToGenerator2 = require("babel-runtime/helpers/asyncToGenerator");
var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck");

@@ -22,6 +26,8 @@

var _createHash = require("create-hash");
var _createHash2 = _interopRequireDefault(_createHash);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var MAX_SCRIPT_BLOCK = 50;
// TODO future refactoring

@@ -31,7 +37,11 @@ // - drop utils.js & refactoring with async/await style

// - there are redundant code across apps (see Eth vs Btc). we might want to factorize it somewhere. also each app apdu call should be abstracted it out as an api
var MAX_SCRIPT_BLOCK = 50;
var DEFAULT_LOCKTIME = 0;
var DEFAULT_SEQUENCE = 0xffffffff;
var SIGHASH_ALL = 1;
var OP_PUSHDATA1 = 0x76;
var OP_HASH160 = 0xa9;
var HASH_SIZE = 0x14;
var OP_EQUALVERIFY = 0x88;
var OP_CHECKSIG = 0xac;
/**

@@ -53,13 +63,30 @@ * Bitcoin API.

/**
* @param path a BIP 32 path
* @example
* btc.getWalletPublicKey("44'/0'/0'/0").then(o => o.bitcoinAddress)
*/
(0, _createClass3.default)(Btc, [{
key: "hashPublicKey",
value: function hashPublicKey(buffer) {
return (0, _createHash2.default)("rmd160").update((0, _createHash2.default)("sha256").update(buffer).digest()).digest();
}
/**
* @param path a BIP 32 path
* @param segwit use segwit
* @example
* btc.getWalletPublicKey("44'/0'/0'/0").then(o => o.bitcoinAddress)
*/
(0, _createClass3.default)(Btc, [{
}, {
key: "getWalletPublicKey",
value: function getWalletPublicKey(path) {
var verify = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var segwit = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
var paths = (0, _utils.splitPath)(path);
var p1 = 0x00;
var p2 = 0x00;
if (verify === true) {
p1 = 0x01;
}
if (segwit == true) {
p2 = 0x01;
}
var buffer = Buffer.alloc(1 + paths.length * 4);

@@ -70,3 +97,3 @@ buffer[0] = paths.length;

});
return this.transport.send(0xe0, 0x40, 0x00, 0x00, buffer).then(function (response) {
return this.transport.send(0xe0, 0x40, p1, p2, buffer).then(function (response) {
var publicKeyLength = response[0];

@@ -162,2 +189,69 @@ var addressLength = response[1 + publicKeyLength];

}, {
key: "getTrustedInputBIP143",
value: function () {
var _ref = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(indexLookup, transaction) {
var sha, hash, data, outputs, locktime;
return _regenerator2.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
if (transaction) {
_context.next = 2;
break;
}
throw new Error("getTrustedInputBIP143: missing tx");
case 2:
sha = (0, _createHash2.default)("sha256");
sha.update(this.serializeTransaction(transaction, true));
hash = sha.digest();
sha = (0, _createHash2.default)("sha256");
sha.update(hash);
hash = sha.digest();
data = Buffer.alloc(4);
data.writeUInt32LE(indexLookup, 0);
outputs = transaction.outputs, locktime = transaction.locktime;
if (!(!outputs || !locktime)) {
_context.next = 13;
break;
}
throw new Error("getTrustedInputBIP143: locktime & outputs is expected");
case 13:
if (outputs[indexLookup]) {
_context.next = 15;
break;
}
throw new Error("getTrustedInputBIP143: wrong index");
case 15:
hash = Buffer.concat([hash, data, outputs[indexLookup].amount]);
_context.next = 18;
return hash.toString("hex");
case 18:
return _context.abrupt("return", _context.sent);
case 19:
case "end":
return _context.stop();
}
}
}, _callee, this);
}));
function getTrustedInputBIP143(_x3, _x4) {
return _ref.apply(this, arguments);
}
return getTrustedInputBIP143;
}()
}, {
key: "getVarint",

@@ -180,3 +274,5 @@ value: function getVarint(data, offset) {

value: function startUntrustedHashTransactionInputRaw(newTransaction, firstRound, transactionData) {
return this.transport.send(0xe0, 0x44, firstRound ? 0x00 : 0x80, newTransaction ? 0x00 : 0x80, transactionData);
var segwit = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
return this.transport.send(0xe0, 0x44, firstRound ? 0x00 : 0x80, newTransaction ? segwit ? 0x02 : 0x00 : 0x80, transactionData);
}

@@ -188,18 +284,20 @@ }, {

var segwit = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
var data = Buffer.concat([transaction.version, this.createVarint(transaction.inputs.length)]);
return this.startUntrustedHashTransactionInputRaw(newTransaction, true, data).then(function () {
return this.startUntrustedHashTransactionInputRaw(newTransaction, true, data, segwit).then(function () {
var i = 0;
return (0, _utils.eachSeries)(transaction.inputs, function (input) {
// TODO : segwit
var prefix = void 0;
if (inputs[i].trustedInput) {
prefix = Buffer.alloc(2);
prefix[0] = 0x01;
prefix[1] = inputs[i].value.length;
if (segwit) {
prefix = Buffer.from([0x02]);
} else {
prefix = Buffer.from([0x01, inputs[i].value.length]);
}
} else {
prefix = Buffer.alloc(1);
prefix[0] = 0x00;
prefix = Buffer.from([0x00]);
}
data = Buffer.concat([prefix, inputs[i].value, _this2.createVarint(input.script.length)]);
return _this2.startUntrustedHashTransactionInputRaw(newTransaction, false, data).then(function () {
return _this2.startUntrustedHashTransactionInputRaw(newTransaction, false, data, segwit).then(function () {
var scriptBlocks = [];

@@ -221,3 +319,3 @@ var offset = 0;

return (0, _utils.eachSeries)(scriptBlocks, function (scriptBlock) {
return _this2.startUntrustedHashTransactionInputRaw(newTransaction, false, scriptBlock);
return _this2.startUntrustedHashTransactionInputRaw(newTransaction, false, scriptBlock, segwit);
}).then(function () {

@@ -356,2 +454,3 @@ i++;

* * sequence is the sequence number to use for this input (when using RBF), or non present
* @param segwit is a boolean indicating wether to use segwit or not
* @param associatedKeysets is an array of BIP 32 paths pointing to the path to the private key used for each UTXO

@@ -375,6 +474,8 @@ * @param changePath is an optional BIP 32 path pointing to the path to the public key used to compute the change address

value: function createPaymentTransactionNew(inputs, associatedKeysets, changePath, outputScriptHex) {
var lockTime = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : DEFAULT_LOCKTIME;
var _this5 = this;
var lockTime = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : DEFAULT_LOCKTIME;
var sigHashType = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : SIGHASH_ALL;
var segwit = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false;

@@ -397,3 +498,3 @@ // Inputs are provided as arrays of [transaction, output_index, optional redeem script, optional sequence]

};
var getTrustedInputCall = segwit ? this.getTrustedInputBIP143.bind(this) : this.getTrustedInput.bind(this);
var outputScript = Buffer.from(outputScriptHex, "hex");

@@ -403,3 +504,3 @@

return (0, _utils.doIf)(!resuming, function () {
return _this5.getTrustedInput(input[1], input[0]).then(function (trustedInput) {
return getTrustedInputCall(input[1], input[0]).then(function (trustedInput) {
trustedInputs.push({

@@ -417,14 +518,14 @@ trustedInput: true,

}
}).then(function () {
for (var i = 0; i < inputs.length; i++) {
var _sequence = Buffer.alloc(4);
_sequence.writeUInt32LE(inputs[i].length >= 4 && typeof inputs[i][3] === "number" ? inputs[i][3] : DEFAULT_SEQUENCE, 0);
targetTransaction.inputs.push({
script: nullScript,
prevout: nullPrevout,
sequence: _sequence
});
}
});
}).then(function () {
for (var i = 0; i < inputs.length; i++) {
var _sequence = Buffer.alloc(4);
_sequence.writeUInt32LE(inputs[i].length >= 4 && typeof inputs[i][3] === "number" ? inputs[i][3] : DEFAULT_SEQUENCE, 0);
targetTransaction.inputs.push({
script: nullScript,
prevout: nullPrevout,
sequence: _sequence
});
}
}).then(function () {
return (0, _utils.doIf)(!resuming, function () {

@@ -443,31 +544,52 @@ return (

}).then(function () {
return (0, _utils.foreach)(inputs, function (input, i) {
targetTransaction.inputs[i].script = inputs[i].length >= 3 && typeof inputs[i][2] === "string" ? Buffer.from(inputs[i][2], "hex") : regularOutputs[i].script;
return _this5.startUntrustedHashTransactionInput(firstRun, targetTransaction, trustedInputs).then(function () {
return _promise2.default.resolve().then(function () {
if (!resuming && typeof changePath !== "undefined") {
return _this5.provideOutputFullChangePath(changePath);
}
}).then(function () {
return _this5.hashOutputFull(outputScript);
}).then(function () {
return _this5.signTransaction(associatedKeysets[i], lockTime, sigHashType).then(function (signature) {
signatures.push(signature);
targetTransaction.inputs[i].script = nullScript;
if (firstRun) {
firstRun = false;
}
return (0, _utils.doIf)(segwit, function () {
return (
// Do the first run with all inputs
_this5.startUntrustedHashTransactionInput(true, targetTransaction, trustedInputs, segwit).then(function () {
return (0, _utils.doIf)(!resuming && typeof changePath != "undefined", function () {
return this.provideOutputFullChangePath(changePath);
}).then(function () {
return _this5.hashOutputFull(outputScript);
});
});
});
})
);
});
}).then(function () {
return (
// Do the second run with the individual transaction
(0, _utils.foreach)(inputs, function (input, i) {
targetTransaction.inputs[i].script = inputs[i].length >= 3 && typeof inputs[i][2] === "string" ? Buffer.from(inputs[i][2], "hex") : !segwit ? regularOutputs[i].script : Buffer.concat([Buffer.from([OP_PUSHDATA1, OP_HASH160, HASH_SIZE]), _this5.hashPublicKey(publicKeys[i]), Buffer.from([OP_EQUALVERIFY, OP_CHECKSIG])]);
return _this5.startUntrustedHashTransactionInput(!segwit && firstRun, targetTransaction, trustedInputs, segwit).then(function () {
return (0, _utils.doIf)(!segwit, function () {
return (0, _utils.doIf)(!resuming && typeof changePath != "undefined", function () {
return this.provideOutputFullChangePath(changePath);
}).then(function () {
return _this5.hashOutputFull(outputScript);
});
});
}).then(function () {
return _this5.signTransaction(associatedKeysets[i], lockTime, sigHashType);
}).then(function (signature) {
signatures.push(signature);
targetTransaction.inputs[i].script = nullScript;
if (firstRun) {
firstRun = false;
}
});
})
);
}).then(function () {
// Populate the final input scripts
for (var i = 0; i < inputs.length; i++) {
var signatureSize = Buffer.alloc(1);
var keySize = Buffer.alloc(1);
signatureSize[0] = signatures[i].length;
keySize[0] = publicKeys[i].length;
targetTransaction.inputs[i].script = Buffer.concat([signatureSize, signatures[i], keySize, publicKeys[i]]);
targetTransaction.inputs[i].prevout = trustedInputs[i].value.slice(4, 4 + 0x24);
for (var _i = 0; _i < inputs.length; _i++) {
if (segwit) {
targetTransaction.inputs[_i].script = Buffer.concat([Buffer.from("160014", "hex"), _this5.hashPublicKey(publicKeys[_i])]);
} else {
var signatureSize = Buffer.alloc(1);
var keySize = Buffer.alloc(1);
signatureSize[0] = signatures[_i].length;
keySize[0] = publicKeys[_i].length;
targetTransaction.inputs[_i].script = Buffer.concat([signatureSize, signatures[_i], keySize, publicKeys[_i]]);
}
targetTransaction.inputs[_i].prevout = trustedInputs[_i].value.slice(4, 4 + 0x24);
}

@@ -478,4 +600,15 @@

var result = Buffer.concat([_this5.serializeTransaction(targetTransaction), outputScript, lockTimeBuffer]);
var result = Buffer.concat([_this5.serializeTransaction(targetTransaction, false), outputScript]);
if (segwit) {
var witness = Buffer.alloc(0);
for (var i = 0; i < inputs.length; i++) {
var tmpScriptData = Buffer.concat([Buffer.from("02", "hex"), Buffer.from([signatures[i].length]), signatures[i], Buffer.from([publicKeys[i].length]), publicKeys[i]]);
witness = Buffer.concat([witness, tmpScriptData]);
}
result = Buffer.concat([result, witness]);
}
result = Buffer.concat([result, lockTimeBuffer]);
return result.toString("hex");

@@ -567,3 +700,3 @@ });

targetTransaction.inputs[i].script = inputs[i].length >= 3 && typeof inputs[i][2] === "string" ? Buffer.from(inputs[i][2], "hex") : regularOutputs[i].script;
return _this6.startUntrustedHashTransactionInput(firstRun, targetTransaction, trustedInputs).then(function () {
return _this6.startUntrustedHashTransactionInput(firstRun, targetTransaction, trustedInputs, false).then(function () {
return _this6.hashOutputFull(outputScript);

@@ -624,5 +757,6 @@ }).then(function () {

key: "splitTransaction",
value: function splitTransaction(transactionHex) {
value: function splitTransaction(transactionHex, isSegwitSupported) {
var inputs = [];
var outputs = [];
var witness = false;
var offset = 0;

@@ -632,2 +766,6 @@ var transaction = Buffer.from(transactionHex, "hex");

offset += 4;
if (isSegwitSupported && transaction[offset] === 0 && transaction[offset + 1] !== 0) {
offset += 2;
witness = true;
}
var varint = this.getVarint(transaction, offset);

@@ -650,3 +788,3 @@ var numberInputs = varint[0];

offset += varint[1];
for (var _i = 0; _i < numberOutputs; _i++) {
for (var _i2 = 0; _i2 < numberOutputs; _i2++) {
var _amount = transaction.slice(offset, offset + 8);

@@ -660,4 +798,10 @@ offset += 8;

}
var locktime = transaction.slice(offset, offset + 4);
return { version: version, inputs: inputs, outputs: outputs, locktime: locktime };
var witnessScript, locktime;
if (witness) {
witnessScript = transaction.slice(offset, -4);
locktime = transaction.slice(transaction.length - 4);
} else {
locktime = transaction.slice(offset, offset + 4);
}
return { version: version, inputs: inputs, outputs: outputs, locktime: locktime, witness: witnessScript };
}

@@ -673,6 +817,6 @@

key: "serializeTransactionOutputs",
value: function serializeTransactionOutputs(_ref) {
value: function serializeTransactionOutputs(_ref2) {
var _this7 = this;
var outputs = _ref.outputs;
var outputs = _ref2.outputs;

@@ -694,6 +838,7 @@ var outputBuffer = Buffer.alloc(0);

key: "serializeTransaction",
value: function serializeTransaction(transaction) {
value: function serializeTransaction(transaction, skipWitness) {
var _this8 = this;
var inputBuffer = Buffer.alloc(0);
var useWitness = typeof transaction["witness"] != "undefined" && !skipWitness;
transaction.inputs.forEach(function (input) {

@@ -705,6 +850,6 @@ inputBuffer = Buffer.concat([inputBuffer, input.prevout, _this8.createVarint(input.script.length), input.script, input.sequence]);

if (typeof transaction.outputs !== "undefined" && typeof transaction.locktime !== "undefined") {
outputBuffer = Buffer.concat([outputBuffer, transaction.locktime]);
outputBuffer = Buffer.concat([outputBuffer, useWitness && transaction.witness || Buffer.alloc(0), transaction.locktime]);
}
return Buffer.concat([transaction.version, this.createVarint(transaction.inputs.length), inputBuffer, outputBuffer]);
return Buffer.concat([transaction.version, useWitness ? Buffer.from("0001", "hex") : Buffer.alloc(0), this.createVarint(transaction.inputs.length), inputBuffer, outputBuffer]);
}

@@ -711,0 +856,0 @@

{
"name": "@ledgerhq/hw-app-btc",
"version": "2.1.3",
"version": "2.2.0-beta.9d29a5c6",
"description": "Ledger Hardware Wallet Bitcoin Application API",

@@ -28,3 +28,4 @@ "keywords": [

"dependencies": {
"@ledgerhq/hw-transport": "^2.1.3"
"@ledgerhq/hw-transport": "^2.2.0-beta.9d29a5c6",
"create-hash": "^1.1.3"
},

@@ -31,0 +32,0 @@ "devDependencies": {

@@ -9,2 +9,3 @@ //@flow

import type Transport from "@ledgerhq/hw-transport";
import createHash from "create-hash";

@@ -15,3 +16,7 @@ const MAX_SCRIPT_BLOCK = 50;

const SIGHASH_ALL = 1;
const OP_PUSHDATA1 = 0x76;
const OP_HASH160 = 0xa9;
const HASH_SIZE = 0x14;
const OP_EQUALVERIFY = 0x88;
const OP_CHECKSIG = 0xac;
/**

@@ -32,4 +37,15 @@ * Bitcoin API.

hashPublicKey(buffer: Buffer) {
return createHash("rmd160")
.update(
createHash("sha256")
.update(buffer)
.digest()
)
.digest();
}
/**
* @param path a BIP 32 path
* @param segwit use segwit
* @example

@@ -39,3 +55,5 @@ * btc.getWalletPublicKey("44'/0'/0'/0").then(o => o.bitcoinAddress)

getWalletPublicKey(
path: string
path: string,
verify?: boolean = false,
segwit?: boolean = false
): Promise<{

@@ -47,2 +65,10 @@ publicKey: string,

const paths = splitPath(path);
var p1 = 0x00;
var p2 = 0x00;
if (verify === true) {
p1 = 0x01;
}
if (segwit == true) {
p2 = 0x01;
}
const buffer = Buffer.alloc(1 + paths.length * 4);

@@ -53,24 +79,17 @@ buffer[0] = paths.length;

});
return this.transport
.send(0xe0, 0x40, 0x00, 0x00, buffer)
.then(response => {
const publicKeyLength = response[0];
const addressLength = response[1 + publicKeyLength];
const publicKey = response
.slice(1, 1 + publicKeyLength)
.toString("hex");
const bitcoinAddress = response
.slice(
1 + publicKeyLength + 1,
1 + publicKeyLength + 1 + addressLength
)
.toString("ascii");
const chainCode = response
.slice(
1 + publicKeyLength + 1 + addressLength,
1 + publicKeyLength + 1 + addressLength + 32
)
.toString("hex");
return { publicKey, bitcoinAddress, chainCode };
});
return this.transport.send(0xe0, 0x40, p1, p2, buffer).then(response => {
const publicKeyLength = response[0];
const addressLength = response[1 + publicKeyLength];
const publicKey = response.slice(1, 1 + publicKeyLength).toString("hex");
const bitcoinAddress = response
.slice(1 + publicKeyLength + 1, 1 + publicKeyLength + 1 + addressLength)
.toString("ascii");
const chainCode = response
.slice(
1 + publicKeyLength + 1 + addressLength,
1 + publicKeyLength + 1 + addressLength + 32
)
.toString("hex");
return { publicKey, bitcoinAddress, chainCode };
});
}

@@ -175,2 +194,25 @@

async getTrustedInputBIP143(indexLookup: number, transaction: Transaction) {
if (!transaction) {
throw new Error("getTrustedInputBIP143: missing tx");
}
let sha = createHash("sha256");
sha.update(this.serializeTransaction(transaction, true));
let hash = sha.digest();
sha = createHash("sha256");
sha.update(hash);
hash = sha.digest();
const data = Buffer.alloc(4);
data.writeUInt32LE(indexLookup, 0);
const { outputs, locktime } = transaction;
if (!outputs || !locktime) {
throw new Error("getTrustedInputBIP143: locktime & outputs is expected");
}
if (!outputs[indexLookup]) {
throw new Error("getTrustedInputBIP143: wrong index");
}
hash = Buffer.concat([hash, data, outputs[indexLookup].amount]);
return await hash.toString("hex");
}
getVarint(data: Buffer, offset: number): [number, number] {

@@ -199,3 +241,4 @@ if (data[offset] < 0xfd) {

firstRound: boolean,
transactionData: Buffer
transactionData: Buffer,
segwit?: boolean = false
) {

@@ -206,3 +249,3 @@ return this.transport.send(

firstRound ? 0x00 : 0x80,
newTransaction ? 0x00 : 0x80,
newTransaction ? (segwit ? 0x02 : 0x00) : 0x80,
transactionData

@@ -215,3 +258,4 @@ );

transaction: Transaction,
inputs: Array<{ trustedInput: boolean, value: Buffer }>
inputs: Array<{ trustedInput: boolean, value: Buffer }>,
segwit?: boolean = false
) {

@@ -225,15 +269,16 @@ let data = Buffer.concat([

true,
data
data,
segwit
).then(() => {
let i = 0;
return eachSeries(transaction.inputs, input => {
// TODO : segwit
let prefix;
if (inputs[i].trustedInput) {
prefix = Buffer.alloc(2);
prefix[0] = 0x01;
prefix[1] = inputs[i].value.length;
if (segwit) {
prefix = Buffer.from([0x02]);
} else {
prefix = Buffer.from([0x01, inputs[i].value.length]);
}
} else {
prefix = Buffer.alloc(1);
prefix[0] = 0x00;
prefix = Buffer.from([0x00]);
}

@@ -248,3 +293,4 @@ data = Buffer.concat([

false,
data
data,
segwit
).then(() => {

@@ -280,3 +326,4 @@ let scriptBlocks = [];

false,
scriptBlock
scriptBlock,
segwit
);

@@ -422,2 +469,3 @@ }).then(() => {

* * sequence is the sequence number to use for this input (when using RBF), or non present
* @param segwit is a boolean indicating wether to use segwit or not
* @param associatedKeysets is an array of BIP 32 paths pointing to the path to the private key used for each UTXO

@@ -443,3 +491,4 @@ * @param changePath is an optional BIP 32 path pointing to the path to the public key used to compute the change address

lockTime?: number = DEFAULT_LOCKTIME,
sigHashType?: number = SIGHASH_ALL
sigHashType?: number = SIGHASH_ALL,
segwit?: boolean = false
) {

@@ -462,8 +511,10 @@ // Inputs are provided as arrays of [transaction, output_index, optional redeem script, optional sequence]

};
const getTrustedInputCall = segwit
? this.getTrustedInputBIP143.bind(this)
: this.getTrustedInput.bind(this);
const outputScript = Buffer.from(outputScriptHex, "hex");
return foreach(inputs, input =>
doIf(!resuming, () =>
this.getTrustedInput(input[1], input[0]).then(trustedInput => {
return foreach(inputs, input => {
return doIf(!resuming, () =>
getTrustedInputCall(input[1], input[0]).then(trustedInput => {
trustedInputs.push({

@@ -474,28 +525,29 @@ trustedInput: true,

})
).then(() => {
const { outputs } = input[0];
const index = input[1];
if (outputs && index <= outputs.length - 1) {
regularOutputs.push(outputs[index]);
}
})
)
.then(() => {
for (let i = 0; i < inputs.length; i++) {
let sequence = Buffer.alloc(4);
sequence.writeUInt32LE(
inputs[i].length >= 4 && typeof inputs[i][3] === "number"
? inputs[i][3]
: DEFAULT_SEQUENCE,
0
);
targetTransaction.inputs.push({
script: nullScript,
prevout: nullPrevout,
sequence
});
}
})
.then(() => {
return doIf(!resuming, () =>
)
.then(() => {
const { outputs } = input[0];
const index = input[1];
if (outputs && index <= outputs.length - 1) {
regularOutputs.push(outputs[index]);
}
})
.then(() => {
for (let i = 0; i < inputs.length; i++) {
let sequence = Buffer.alloc(4);
sequence.writeUInt32LE(
inputs[i].length >= 4 && typeof inputs[i][3] === "number"
? inputs[i][3]
: DEFAULT_SEQUENCE,
0
);
targetTransaction.inputs.push({
script: nullScript,
prevout: nullPrevout,
sequence
});
}
});
})
.then(() =>
doIf(!resuming, () =>
// Collect public keys

@@ -513,5 +565,21 @@ foreach(inputs, (input, i) =>

})
);
})
)
)
.then(() =>
doIf(segwit, () =>
// Do the first run with all inputs
this.startUntrustedHashTransactionInput(
true,
targetTransaction,
trustedInputs,
segwit
).then(() =>
doIf(!resuming && typeof changePath != "undefined", function() {
return this.provideOutputFullChangePath(changePath);
}).then(() => this.hashOutputFull(outputScript))
)
)
)
.then(() =>
// Do the second run with the individual transaction
foreach(inputs, (input, i) => {

@@ -521,29 +589,32 @@ targetTransaction.inputs[i].script =

? Buffer.from(inputs[i][2], "hex")
: regularOutputs[i].script;
: !segwit
? regularOutputs[i].script
: Buffer.concat([
Buffer.from([OP_PUSHDATA1, OP_HASH160, HASH_SIZE]),
this.hashPublicKey(publicKeys[i]),
Buffer.from([OP_EQUALVERIFY, OP_CHECKSIG])
]);
return this.startUntrustedHashTransactionInput(
firstRun,
!segwit && firstRun,
targetTransaction,
trustedInputs
).then(() =>
Promise.resolve()
.then(() => {
if (!resuming && typeof changePath !== "undefined") {
trustedInputs,
segwit
)
.then(() =>
doIf(!segwit, () =>
doIf(!resuming && typeof changePath != "undefined", function() {
return this.provideOutputFullChangePath(changePath);
}
})
.then(() => this.hashOutputFull(outputScript))
.then(() =>
this.signTransaction(
associatedKeysets[i],
lockTime,
sigHashType
).then(signature => {
signatures.push(signature);
targetTransaction.inputs[i].script = nullScript;
if (firstRun) {
firstRun = false;
}
})
}).then(() => this.hashOutputFull(outputScript))
)
);
)
.then(() =>
this.signTransaction(associatedKeysets[i], lockTime, sigHashType)
)
.then(signature => {
signatures.push(signature);
targetTransaction.inputs[i].script = nullScript;
if (firstRun) {
firstRun = false;
}
});
})

@@ -554,12 +625,20 @@ )

for (let i = 0; i < inputs.length; i++) {
const signatureSize = Buffer.alloc(1);
const keySize = Buffer.alloc(1);
signatureSize[0] = signatures[i].length;
keySize[0] = publicKeys[i].length;
targetTransaction.inputs[i].script = Buffer.concat([
signatureSize,
signatures[i],
keySize,
publicKeys[i]
]);
if (segwit) {
targetTransaction.inputs[i].script = Buffer.concat([
Buffer.from("160014", "hex"),
this.hashPublicKey(publicKeys[i])
]);
} else {
const signatureSize = Buffer.alloc(1);
const keySize = Buffer.alloc(1);
signatureSize[0] = signatures[i].length;
keySize[0] = publicKeys[i].length;
targetTransaction.inputs[i].script = Buffer.concat([
signatureSize,
signatures[i],
keySize,
publicKeys[i]
]);
}
targetTransaction.inputs[i].prevout = trustedInputs[i].value.slice(

@@ -574,8 +653,24 @@ 4,

const result = Buffer.concat([
this.serializeTransaction(targetTransaction),
outputScript,
lockTimeBuffer
var result = Buffer.concat([
this.serializeTransaction(targetTransaction, false),
outputScript
]);
if (segwit) {
var witness = Buffer.alloc(0);
for (var i = 0; i < inputs.length; i++) {
var tmpScriptData = Buffer.concat([
Buffer.from("02", "hex"),
Buffer.from([signatures[i].length]),
signatures[i],
Buffer.from([publicKeys[i].length]),
publicKeys[i]
]);
witness = Buffer.concat([witness, tmpScriptData]);
}
result = Buffer.concat([result, witness]);
}
result = Buffer.concat([result, lockTimeBuffer]);
return result.toString("hex");

@@ -672,3 +767,4 @@ });

targetTransaction,
trustedInputs
trustedInputs,
false
)

@@ -730,5 +826,9 @@ .then(() => this.hashOutputFull(outputScript))

*/
splitTransaction(transactionHex: string): Transaction {
splitTransaction(
transactionHex: string,
isSegwitSupported: boolean
): Transaction {
const inputs = [];
const outputs = [];
var witness = false;
let offset = 0;

@@ -738,2 +838,9 @@ const transaction = Buffer.from(transactionHex, "hex");

offset += 4;
if (
isSegwitSupported &&
(transaction[offset] === 0 && transaction[offset + 1] !== 0)
) {
offset += 2;
witness = true;
}
let varint = this.getVarint(transaction, offset);

@@ -765,4 +872,10 @@ const numberInputs = varint[0];

}
let locktime = transaction.slice(offset, offset + 4);
return { version, inputs, outputs, locktime };
var witnessScript, locktime;
if (witness) {
witnessScript = transaction.slice(offset, -4);
locktime = transaction.slice(transaction.length - 4);
} else {
locktime = transaction.slice(offset, offset + 4);
}
return { version, inputs, outputs, locktime, witness: witnessScript };
}

@@ -796,4 +909,6 @@

*/
serializeTransaction(transaction: Transaction) {
serializeTransaction(transaction: Transaction, skipWitness: boolean) {
let inputBuffer = Buffer.alloc(0);
let useWitness =
typeof transaction["witness"] != "undefined" && !skipWitness;
transaction.inputs.forEach(input => {

@@ -814,3 +929,7 @@ inputBuffer = Buffer.concat([

) {
outputBuffer = Buffer.concat([outputBuffer, transaction.locktime]);
outputBuffer = Buffer.concat([
outputBuffer,
(useWitness && transaction.witness) || Buffer.alloc(0),
transaction.locktime
]);
}

@@ -820,2 +939,3 @@

transaction.version,
useWitness ? Buffer.from("0001", "hex") : Buffer.alloc(0),
this.createVarint(transaction.inputs.length),

@@ -871,3 +991,4 @@ inputBuffer,

outputs?: TransactionOutput[],
locktime?: Buffer
locktime?: Buffer,
witness?: Buffer
};

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc