@ledgerhq/hw-app-btc 6.20.0 → 6.25.1-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/lib/newops/clientCommands.js +4 -4
- package/lib/newops/clientCommands.js.map +1 -1
- package/lib-es/Btc.js.flow +280 -0
- package/lib-es/bip32.js.flow +13 -0
- package/lib-es/compressPublicKey.js.flow +8 -0
- package/lib-es/constants.js.flow +13 -0
- package/lib-es/createTransaction.js.flow +419 -0
- package/lib-es/debug.js.flow +41 -0
- package/lib-es/finalizeInput.js.flow +38 -0
- package/lib-es/getAppAndVersion.js.flow +19 -0
- package/lib-es/getTrustedInput.js.flow +163 -0
- package/lib-es/getTrustedInputBIP143.js.flow +37 -0
- package/lib-es/getWalletPublicKey.js.flow +51 -0
- package/lib-es/hashPublicKey.js.flow +8 -0
- package/lib-es/newops/clientCommands.js +4 -4
- package/lib-es/newops/clientCommands.js.map +1 -1
- package/lib-es/serializeTransaction.js.flow +77 -0
- package/lib-es/shouldUseTrustedInputForSegwit.js.flow +15 -0
- package/lib-es/signMessage.js.flow +67 -0
- package/lib-es/signP2SHTransaction.js.flow +170 -0
- package/lib-es/signTransaction.js.flow +40 -0
- package/lib-es/splitTransaction.js.flow +145 -0
- package/lib-es/startUntrustedHashTransactionInput.js.flow +136 -0
- package/lib-es/types.js.flow +31 -0
- package/lib-es/varint.js.flow +43 -0
- package/package.json +3 -3
- package/src/newops/clientCommands.ts +4 -4
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
//@flow
|
|
2
|
+
|
|
3
|
+
import Transport from "@ledgerhq/hw-transport";
|
|
4
|
+
import shajs from "sha.js";
|
|
5
|
+
import type { Transaction } from "./types";
|
|
6
|
+
import { serializeTransaction } from "./serializeTransaction";
|
|
7
|
+
|
|
8
|
+
export function getTrustedInputBIP143(
|
|
9
|
+
transport: Transport<*>,
|
|
10
|
+
indexLookup: number,
|
|
11
|
+
transaction: Transaction,
|
|
12
|
+
additionals: Array<string> = []
|
|
13
|
+
) {
|
|
14
|
+
if (!transaction) {
|
|
15
|
+
throw new Error("getTrustedInputBIP143: missing tx");
|
|
16
|
+
}
|
|
17
|
+
const isDecred = additionals.includes("decred");
|
|
18
|
+
if (isDecred) {
|
|
19
|
+
throw new Error("Decred does not implement BIP143");
|
|
20
|
+
}
|
|
21
|
+
let hash = shajs("sha256")
|
|
22
|
+
.update(
|
|
23
|
+
shajs("sha256").update(serializeTransaction(transaction, true)).digest()
|
|
24
|
+
)
|
|
25
|
+
.digest();
|
|
26
|
+
const data = Buffer.alloc(4);
|
|
27
|
+
data.writeUInt32LE(indexLookup, 0);
|
|
28
|
+
const { outputs, locktime } = transaction;
|
|
29
|
+
if (!outputs || !locktime) {
|
|
30
|
+
throw new Error("getTrustedInputBIP143: locktime & outputs is expected");
|
|
31
|
+
}
|
|
32
|
+
if (!outputs[indexLookup]) {
|
|
33
|
+
throw new Error("getTrustedInputBIP143: wrong index");
|
|
34
|
+
}
|
|
35
|
+
hash = Buffer.concat([hash, data, outputs[indexLookup].amount]);
|
|
36
|
+
return hash.toString("hex");
|
|
37
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import type Transport from "@ledgerhq/hw-transport";
|
|
3
|
+
import { bip32asBuffer } from "./bip32";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* address format is one of legacy | p2sh | bech32 | cashaddr
|
|
7
|
+
*/
|
|
8
|
+
export type AddressFormat = "legacy" | "p2sh" | "bech32" | "cashaddr";
|
|
9
|
+
|
|
10
|
+
const addressFormatMap = {
|
|
11
|
+
legacy: 0,
|
|
12
|
+
p2sh: 1,
|
|
13
|
+
bech32: 2,
|
|
14
|
+
cashaddr: 3,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export async function getWalletPublicKey(
|
|
18
|
+
transport: Transport<*>,
|
|
19
|
+
options: { path: string, verify?: boolean, format?: AddressFormat }
|
|
20
|
+
): Promise<{
|
|
21
|
+
publicKey: string,
|
|
22
|
+
bitcoinAddress: string,
|
|
23
|
+
chainCode: string,
|
|
24
|
+
}> {
|
|
25
|
+
const { path, verify, format } = {
|
|
26
|
+
verify: false,
|
|
27
|
+
format: "legacy",
|
|
28
|
+
...options,
|
|
29
|
+
};
|
|
30
|
+
if (!(format in addressFormatMap)) {
|
|
31
|
+
throw new Error("btc.getWalletPublicKey invalid format=" + format);
|
|
32
|
+
}
|
|
33
|
+
const buffer = bip32asBuffer(path);
|
|
34
|
+
var p1 = verify ? 1 : 0;
|
|
35
|
+
var p2 = addressFormatMap[format];
|
|
36
|
+
const response = await transport.send(0xe0, 0x40, p1, p2, buffer);
|
|
37
|
+
|
|
38
|
+
const publicKeyLength = response[0];
|
|
39
|
+
const addressLength = response[1 + publicKeyLength];
|
|
40
|
+
const publicKey = response.slice(1, 1 + publicKeyLength).toString("hex");
|
|
41
|
+
const bitcoinAddress = response
|
|
42
|
+
.slice(1 + publicKeyLength + 1, 1 + publicKeyLength + 1 + addressLength)
|
|
43
|
+
.toString("ascii");
|
|
44
|
+
const chainCode = response
|
|
45
|
+
.slice(
|
|
46
|
+
1 + publicKeyLength + 1 + addressLength,
|
|
47
|
+
1 + publicKeyLength + 1 + addressLength + 32
|
|
48
|
+
)
|
|
49
|
+
.toString("hex");
|
|
50
|
+
return { publicKey, bitcoinAddress, chainCode };
|
|
51
|
+
}
|
|
@@ -93,7 +93,7 @@ var GetPreimageCommand = /** @class */ (function (_super) {
|
|
|
93
93
|
return _this;
|
|
94
94
|
}
|
|
95
95
|
GetPreimageCommand.prototype.execute = function (request) {
|
|
96
|
-
var req = request.subarray(1);
|
|
96
|
+
var req = Buffer.from(request.subarray(1));
|
|
97
97
|
// we expect no more data to read
|
|
98
98
|
if (req.length != 1 + 32) {
|
|
99
99
|
throw new Error("Invalid request, unexpected trailing data");
|
|
@@ -122,7 +122,7 @@ var GetPreimageCommand = /** @class */ (function (_super) {
|
|
|
122
122
|
return Buffer.concat([
|
|
123
123
|
preimage_len_varint,
|
|
124
124
|
Buffer.from([payload_size]),
|
|
125
|
-
known_preimage.subarray(0, payload_size),
|
|
125
|
+
Buffer.from(known_preimage.subarray(0, payload_size)),
|
|
126
126
|
]);
|
|
127
127
|
}
|
|
128
128
|
throw Error("Requested unknown preimage for: ".concat(req_hash_hex));
|
|
@@ -141,7 +141,7 @@ var GetMerkleLeafProofCommand = /** @class */ (function (_super) {
|
|
|
141
141
|
}
|
|
142
142
|
GetMerkleLeafProofCommand.prototype.execute = function (request) {
|
|
143
143
|
var _a;
|
|
144
|
-
var req = request.subarray(1);
|
|
144
|
+
var req = Buffer.from(request.subarray(1));
|
|
145
145
|
if (req.length < 32 + 1 + 1) {
|
|
146
146
|
throw new Error("Invalid request, expected at least 34 bytes");
|
|
147
147
|
}
|
|
@@ -192,7 +192,7 @@ var GetMerkleLeafIndexCommand = /** @class */ (function (_super) {
|
|
|
192
192
|
return _this;
|
|
193
193
|
}
|
|
194
194
|
GetMerkleLeafIndexCommand.prototype.execute = function (request) {
|
|
195
|
-
var req = request.subarray(1);
|
|
195
|
+
var req = Buffer.from(request.subarray(1));
|
|
196
196
|
if (req.length != 32 + 32) {
|
|
197
197
|
throw new Error("Invalid request, unexpected trailing data");
|
|
198
198
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clientCommands.js","sourceRoot":"","sources":["../../src/newops/clientCommands.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAG5C,IAAK,iBAMJ;AAND,WAAK,iBAAiB;IACpB,4DAAY,CAAA;IACZ,0EAAmB,CAAA;IACnB,4FAA4B,CAAA;IAC5B,4FAA4B,CAAA;IAC5B,qFAAwB,CAAA;AAC1B,CAAC,EANI,iBAAiB,KAAjB,iBAAiB,QAMrB;AAED;IAAA;IAGA,CAAC;IAAD,oBAAC;AAAD,CAAC,AAHD,IAGC;AAED;IAAkC,gCAAa;IAK7C,sBAAY,OAAiB,EAAU,gBAA4B;QAAnE,YACE,iBAAO,SAER;QAHsC,sBAAgB,GAAhB,gBAAgB,CAAY;QAFnE,UAAI,GAAG,iBAAiB,CAAC,KAAK,CAAC;QAI7B,KAAI,CAAC,OAAO,GAAG,OAAO,CAAC;;IACzB,CAAC;IAED,8BAAO,GAAP,UAAQ,OAAe;QACrB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACpD,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACxB,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzB,CAAC;IACH,mBAAC;AAAD,CAAC,AAfD,CAAkC,aAAa,GAe9C;;AAED;IAAwC,sCAAa;IAMnD,4BAAY,eAAoC,EAAE,KAAe;QAAjE,YACE,iBAAO,SAGR;QAND,UAAI,GAAG,iBAAiB,CAAC,YAAY,CAAC;QAIpC,KAAI,CAAC,eAAe,GAAG,eAAe,CAAC;QACvC,KAAI,CAAC,KAAK,GAAG,KAAK,CAAC;;IACrB,CAAC;IAED,oCAAO,GAAP,UAAQ,OAAe;QACrB,IAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"clientCommands.js","sourceRoot":"","sources":["../../src/newops/clientCommands.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import type { Transaction } from "./types";
|
|
3
|
+
import { createVarint } from "./varint";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
@example
|
|
7
|
+
const tx1 = btc.splitTransaction("01000000014ea60aeac5252c14291d428915bd7ccd1bfc4af009f4d4dc57ae597ed0420b71010000008a47304402201f36a12c240dbf9e566bc04321050b1984cd6eaf6caee8f02bb0bfec08e3354b022012ee2aeadcbbfd1e92959f57c15c1c6debb757b798451b104665aa3010569b49014104090b15bde569386734abf2a2b99f9ca6a50656627e77de663ca7325702769986cf26cc9dd7fdea0af432c8e2becc867c932e1b9dd742f2a108997c2252e2bdebffffffff0281b72e00000000001976a91472a5d75c8d2d0565b656a5232703b167d50d5a2b88aca0860100000000001976a9144533f5fb9b4817f713c48f0bfe96b9f50c476c9b88ac00000000");
|
|
8
|
+
const outputScript = btc.serializeTransactionOutputs(tx1).toString('hex');
|
|
9
|
+
*/
|
|
10
|
+
export function serializeTransactionOutputs({ outputs }: Transaction): Buffer {
|
|
11
|
+
let outputBuffer = Buffer.alloc(0);
|
|
12
|
+
if (typeof outputs !== "undefined") {
|
|
13
|
+
outputBuffer = Buffer.concat([outputBuffer, createVarint(outputs.length)]);
|
|
14
|
+
outputs.forEach((output) => {
|
|
15
|
+
outputBuffer = Buffer.concat([
|
|
16
|
+
outputBuffer,
|
|
17
|
+
output.amount,
|
|
18
|
+
createVarint(output.script.length),
|
|
19
|
+
output.script,
|
|
20
|
+
]);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
return outputBuffer;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function serializeTransaction(
|
|
27
|
+
transaction: Transaction,
|
|
28
|
+
skipWitness: boolean,
|
|
29
|
+
timestamp?: Buffer,
|
|
30
|
+
additionals: string[] = []
|
|
31
|
+
) {
|
|
32
|
+
const isDecred = additionals.includes("decred");
|
|
33
|
+
const isBech32 = additionals.includes("bech32");
|
|
34
|
+
let inputBuffer = Buffer.alloc(0);
|
|
35
|
+
let useWitness = typeof transaction["witness"] != "undefined" && !skipWitness;
|
|
36
|
+
transaction.inputs.forEach((input) => {
|
|
37
|
+
inputBuffer =
|
|
38
|
+
isDecred || isBech32
|
|
39
|
+
? Buffer.concat([
|
|
40
|
+
inputBuffer,
|
|
41
|
+
input.prevout,
|
|
42
|
+
Buffer.from([0x00]), //tree
|
|
43
|
+
input.sequence,
|
|
44
|
+
])
|
|
45
|
+
: Buffer.concat([
|
|
46
|
+
inputBuffer,
|
|
47
|
+
input.prevout,
|
|
48
|
+
createVarint(input.script.length),
|
|
49
|
+
input.script,
|
|
50
|
+
input.sequence,
|
|
51
|
+
]);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
let outputBuffer = serializeTransactionOutputs(transaction);
|
|
55
|
+
if (
|
|
56
|
+
typeof transaction.outputs !== "undefined" &&
|
|
57
|
+
typeof transaction.locktime !== "undefined"
|
|
58
|
+
) {
|
|
59
|
+
outputBuffer = Buffer.concat([
|
|
60
|
+
outputBuffer,
|
|
61
|
+
(useWitness && transaction.witness) || Buffer.alloc(0),
|
|
62
|
+
transaction.locktime,
|
|
63
|
+
transaction.nExpiryHeight || Buffer.alloc(0),
|
|
64
|
+
transaction.extraData || Buffer.alloc(0),
|
|
65
|
+
]);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return Buffer.concat([
|
|
69
|
+
transaction.version,
|
|
70
|
+
timestamp ? timestamp : Buffer.alloc(0),
|
|
71
|
+
transaction.nVersionGroupId || Buffer.alloc(0),
|
|
72
|
+
useWitness ? Buffer.from("0001", "hex") : Buffer.alloc(0),
|
|
73
|
+
createVarint(transaction.inputs.length),
|
|
74
|
+
inputBuffer,
|
|
75
|
+
outputBuffer,
|
|
76
|
+
]);
|
|
77
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import semver from "semver";
|
|
4
|
+
|
|
5
|
+
export function shouldUseTrustedInputForSegwit({
|
|
6
|
+
version,
|
|
7
|
+
name,
|
|
8
|
+
}: {
|
|
9
|
+
version: string,
|
|
10
|
+
name: string,
|
|
11
|
+
}) {
|
|
12
|
+
if (name === "Decred") return false;
|
|
13
|
+
if (name === "Exchange") return true;
|
|
14
|
+
return semver.gte(version, "1.4.0");
|
|
15
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import type Transport from "@ledgerhq/hw-transport";
|
|
3
|
+
import bippath from "bip32-path";
|
|
4
|
+
import { MAX_SCRIPT_BLOCK } from "./constants";
|
|
5
|
+
|
|
6
|
+
export async function signMessage(
|
|
7
|
+
transport: Transport<*>,
|
|
8
|
+
{ path, messageHex }: { path: string, messageHex: string }
|
|
9
|
+
): Promise<{
|
|
10
|
+
v: number,
|
|
11
|
+
r: string,
|
|
12
|
+
s: string,
|
|
13
|
+
}> {
|
|
14
|
+
const paths = bippath.fromString(path).toPathArray();
|
|
15
|
+
const message = Buffer.from(messageHex, "hex");
|
|
16
|
+
|
|
17
|
+
let offset = 0;
|
|
18
|
+
while (offset !== message.length) {
|
|
19
|
+
let maxChunkSize =
|
|
20
|
+
offset === 0
|
|
21
|
+
? MAX_SCRIPT_BLOCK - 1 - paths.length * 4 - 4
|
|
22
|
+
: MAX_SCRIPT_BLOCK;
|
|
23
|
+
let chunkSize =
|
|
24
|
+
offset + maxChunkSize > message.length
|
|
25
|
+
? message.length - offset
|
|
26
|
+
: maxChunkSize;
|
|
27
|
+
const buffer = Buffer.alloc(
|
|
28
|
+
offset === 0 ? 1 + paths.length * 4 + 2 + chunkSize : chunkSize
|
|
29
|
+
);
|
|
30
|
+
if (offset === 0) {
|
|
31
|
+
buffer[0] = paths.length;
|
|
32
|
+
paths.forEach((element, index) => {
|
|
33
|
+
buffer.writeUInt32BE(element, 1 + 4 * index);
|
|
34
|
+
});
|
|
35
|
+
buffer.writeUInt16BE(message.length, 1 + 4 * paths.length);
|
|
36
|
+
message.copy(
|
|
37
|
+
buffer,
|
|
38
|
+
1 + 4 * paths.length + 2,
|
|
39
|
+
offset,
|
|
40
|
+
offset + chunkSize
|
|
41
|
+
);
|
|
42
|
+
} else {
|
|
43
|
+
message.copy(buffer, 0, offset, offset + chunkSize);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
await transport.send(0xe0, 0x4e, 0x00, offset === 0 ? 0x01 : 0x80, buffer);
|
|
47
|
+
|
|
48
|
+
offset += chunkSize;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const res = await transport.send(0xe0, 0x4e, 0x80, 0x00, Buffer.from([0x00]));
|
|
52
|
+
|
|
53
|
+
const v = res[0] - 0x30;
|
|
54
|
+
let r = res.slice(4, 4 + res[3]);
|
|
55
|
+
if (r[0] === 0) {
|
|
56
|
+
r = r.slice(1);
|
|
57
|
+
}
|
|
58
|
+
r = r.toString("hex");
|
|
59
|
+
offset = 4 + res[3] + 2;
|
|
60
|
+
let s = res.slice(offset, offset + res[offset - 1]);
|
|
61
|
+
if (s[0] === 0) {
|
|
62
|
+
s = s.slice(1);
|
|
63
|
+
}
|
|
64
|
+
s = s.toString("hex");
|
|
65
|
+
|
|
66
|
+
return { v, r, s };
|
|
67
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
//@flow
|
|
2
|
+
import type Transport from "@ledgerhq/hw-transport";
|
|
3
|
+
import { getTrustedInput } from "./getTrustedInput";
|
|
4
|
+
import { startUntrustedHashTransactionInput } from "./startUntrustedHashTransactionInput";
|
|
5
|
+
import { getTrustedInputBIP143 } from "./getTrustedInputBIP143";
|
|
6
|
+
import { signTransaction } from "./signTransaction";
|
|
7
|
+
import { hashOutputFull } from "./finalizeInput";
|
|
8
|
+
import type { TransactionOutput, Transaction } from "./types";
|
|
9
|
+
import {
|
|
10
|
+
DEFAULT_LOCKTIME,
|
|
11
|
+
DEFAULT_VERSION,
|
|
12
|
+
DEFAULT_SEQUENCE,
|
|
13
|
+
SIGHASH_ALL,
|
|
14
|
+
} from "./constants";
|
|
15
|
+
|
|
16
|
+
const defaultArg = {
|
|
17
|
+
lockTime: DEFAULT_LOCKTIME,
|
|
18
|
+
sigHashType: SIGHASH_ALL,
|
|
19
|
+
segwit: false,
|
|
20
|
+
transactionVersion: DEFAULT_VERSION,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
*
|
|
25
|
+
*/
|
|
26
|
+
export type SignP2SHTransactionArg = {
|
|
27
|
+
inputs: Array<[Transaction, number, ?string, ?number]>,
|
|
28
|
+
associatedKeysets: string[],
|
|
29
|
+
outputScriptHex: string,
|
|
30
|
+
lockTime?: number,
|
|
31
|
+
sigHashType?: number,
|
|
32
|
+
segwit?: boolean,
|
|
33
|
+
transactionVersion?: number,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export async function signP2SHTransaction(
|
|
37
|
+
transport: Transport<*>,
|
|
38
|
+
arg: SignP2SHTransactionArg
|
|
39
|
+
) {
|
|
40
|
+
const {
|
|
41
|
+
inputs,
|
|
42
|
+
associatedKeysets,
|
|
43
|
+
outputScriptHex,
|
|
44
|
+
lockTime,
|
|
45
|
+
sigHashType,
|
|
46
|
+
segwit,
|
|
47
|
+
transactionVersion,
|
|
48
|
+
} = { ...defaultArg, ...arg };
|
|
49
|
+
// Inputs are provided as arrays of [transaction, output_index, redeem script, optional sequence]
|
|
50
|
+
// associatedKeysets are provided as arrays of [path]
|
|
51
|
+
const nullScript = Buffer.alloc(0);
|
|
52
|
+
const nullPrevout = Buffer.alloc(0);
|
|
53
|
+
const defaultVersion = Buffer.alloc(4);
|
|
54
|
+
defaultVersion.writeUInt32LE(transactionVersion, 0);
|
|
55
|
+
const trustedInputs = [];
|
|
56
|
+
const regularOutputs: Array<TransactionOutput> = [];
|
|
57
|
+
const signatures = [];
|
|
58
|
+
let firstRun = true;
|
|
59
|
+
const resuming = false;
|
|
60
|
+
let targetTransaction: Transaction = {
|
|
61
|
+
inputs: [],
|
|
62
|
+
version: defaultVersion,
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const getTrustedInputCall = segwit ? getTrustedInputBIP143 : getTrustedInput;
|
|
66
|
+
const outputScript = Buffer.from(outputScriptHex, "hex");
|
|
67
|
+
|
|
68
|
+
for (let input of inputs) {
|
|
69
|
+
if (!resuming) {
|
|
70
|
+
const trustedInput = await getTrustedInputCall(
|
|
71
|
+
transport,
|
|
72
|
+
input[1],
|
|
73
|
+
input[0]
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
let sequence = Buffer.alloc(4);
|
|
77
|
+
sequence.writeUInt32LE(
|
|
78
|
+
input.length >= 4 && typeof input[3] === "number"
|
|
79
|
+
? input[3]
|
|
80
|
+
: DEFAULT_SEQUENCE,
|
|
81
|
+
0
|
|
82
|
+
);
|
|
83
|
+
trustedInputs.push({
|
|
84
|
+
trustedInput: false,
|
|
85
|
+
value: segwit
|
|
86
|
+
? Buffer.from(trustedInput, "hex")
|
|
87
|
+
: Buffer.from(trustedInput, "hex").slice(4, 4 + 0x24),
|
|
88
|
+
sequence,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const { outputs } = input[0];
|
|
93
|
+
const index = input[1];
|
|
94
|
+
if (outputs && index <= outputs.length - 1) {
|
|
95
|
+
regularOutputs.push(outputs[index]);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Pre-build the target transaction
|
|
100
|
+
for (let i = 0; i < inputs.length; i++) {
|
|
101
|
+
let sequence = Buffer.alloc(4);
|
|
102
|
+
sequence.writeUInt32LE(
|
|
103
|
+
inputs[i].length >= 4 && typeof inputs[i][3] === "number"
|
|
104
|
+
? inputs[i][3]
|
|
105
|
+
: DEFAULT_SEQUENCE,
|
|
106
|
+
0
|
|
107
|
+
);
|
|
108
|
+
targetTransaction.inputs.push({
|
|
109
|
+
script: nullScript,
|
|
110
|
+
prevout: nullPrevout,
|
|
111
|
+
sequence,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (segwit) {
|
|
116
|
+
await startUntrustedHashTransactionInput(
|
|
117
|
+
transport,
|
|
118
|
+
true,
|
|
119
|
+
targetTransaction,
|
|
120
|
+
trustedInputs,
|
|
121
|
+
true
|
|
122
|
+
);
|
|
123
|
+
await hashOutputFull(transport, outputScript);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
for (let i = 0; i < inputs.length; i++) {
|
|
127
|
+
const input = inputs[i];
|
|
128
|
+
let script =
|
|
129
|
+
inputs[i].length >= 3 && typeof input[2] === "string"
|
|
130
|
+
? Buffer.from(input[2], "hex")
|
|
131
|
+
: regularOutputs[i].script;
|
|
132
|
+
let pseudoTX = Object.assign({}, targetTransaction);
|
|
133
|
+
let pseudoTrustedInputs = segwit ? [trustedInputs[i]] : trustedInputs;
|
|
134
|
+
if (segwit) {
|
|
135
|
+
pseudoTX.inputs = [{ ...pseudoTX.inputs[i], script }];
|
|
136
|
+
} else {
|
|
137
|
+
pseudoTX.inputs[i].script = script;
|
|
138
|
+
}
|
|
139
|
+
await startUntrustedHashTransactionInput(
|
|
140
|
+
transport,
|
|
141
|
+
!segwit && firstRun,
|
|
142
|
+
pseudoTX,
|
|
143
|
+
pseudoTrustedInputs,
|
|
144
|
+
segwit
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
if (!segwit) {
|
|
148
|
+
await hashOutputFull(transport, outputScript);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const signature = await signTransaction(
|
|
152
|
+
transport,
|
|
153
|
+
associatedKeysets[i],
|
|
154
|
+
lockTime,
|
|
155
|
+
sigHashType
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
signatures.push(
|
|
159
|
+
segwit
|
|
160
|
+
? signature.toString("hex")
|
|
161
|
+
: signature.slice(0, signature.length - 1).toString("hex")
|
|
162
|
+
);
|
|
163
|
+
targetTransaction.inputs[i].script = nullScript;
|
|
164
|
+
if (firstRun) {
|
|
165
|
+
firstRun = false;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return signatures;
|
|
170
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import type Transport from "@ledgerhq/hw-transport";
|
|
3
|
+
import { bip32asBuffer } from "./bip32";
|
|
4
|
+
|
|
5
|
+
export function signTransaction(
|
|
6
|
+
transport: Transport<*>,
|
|
7
|
+
path: string,
|
|
8
|
+
lockTime: number,
|
|
9
|
+
sigHashType: number,
|
|
10
|
+
expiryHeight?: Buffer,
|
|
11
|
+
additionals: Array<string> = []
|
|
12
|
+
): Promise<Buffer> {
|
|
13
|
+
const isDecred = additionals.includes("decred");
|
|
14
|
+
const pathsBuffer = bip32asBuffer(path);
|
|
15
|
+
const lockTimeBuffer = Buffer.alloc(4);
|
|
16
|
+
lockTimeBuffer.writeUInt32BE(lockTime, 0);
|
|
17
|
+
let buffer = isDecred
|
|
18
|
+
? Buffer.concat([
|
|
19
|
+
pathsBuffer,
|
|
20
|
+
lockTimeBuffer,
|
|
21
|
+
expiryHeight || Buffer.from([0x00, 0x00, 0x00, 0x00]),
|
|
22
|
+
Buffer.from([sigHashType]),
|
|
23
|
+
])
|
|
24
|
+
: Buffer.concat([
|
|
25
|
+
pathsBuffer,
|
|
26
|
+
Buffer.from([0x00]),
|
|
27
|
+
lockTimeBuffer,
|
|
28
|
+
Buffer.from([sigHashType]),
|
|
29
|
+
]);
|
|
30
|
+
if (expiryHeight && !isDecred) {
|
|
31
|
+
buffer = Buffer.concat([buffer, expiryHeight]);
|
|
32
|
+
}
|
|
33
|
+
return transport.send(0xe0, 0x48, 0x00, 0x00, buffer).then((result) => {
|
|
34
|
+
if (result.length > 0) {
|
|
35
|
+
result[0] = 0x30;
|
|
36
|
+
return result.slice(0, result.length - 2);
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
});
|
|
40
|
+
}
|