@ledgerhq/hw-app-btc
Advanced tools
Comparing version 8.0.2 to 8.1.0-nightly.0
# @ledgerhq/hw-app-btc | ||
## 8.1.0-nightly.0 | ||
### Minor Changes | ||
- [#836](https://github.com/LedgerHQ/ledger-live/pull/836) [`68a0b01efc`](https://github.com/LedgerHQ/ledger-live/commit/68a0b01efcfd481cb8fe71ec22a2fc7217f25ec9) Thanks [@hzheng-ledger](https://github.com/hzheng-ledger)! - Support zcash v5 format transaction | ||
### Patch Changes | ||
- Updated dependencies []: | ||
- @ledgerhq/hw-transport@6.27.5-nightly.0 | ||
## 8.0.2 | ||
@@ -4,0 +15,0 @@ |
@@ -83,3 +83,3 @@ var __assign = (this && this.__assign) || function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var signTx, inputs, associatedKeysets, changePath, outputScriptHex, lockTime, sigHashType, segwit, initialTimestamp, additionals, expiryHeight, onDeviceStreaming, onDeviceSignatureGranted, onDeviceSignatureRequested, useTrustedInputForSegwit, a, e_1, notify, isDecred, isXST, startTime, sapling, bech32, useBip143, nullScript, nullPrevout, defaultVersion, trustedInputs, regularOutputs, signatures, publicKeys, firstRun, resuming, targetTransaction, getTrustedInputCall, outputScript, inputs_1, inputs_1_1, input, trustedInput, sequence, outputs, index, e_2_1, result_1, i, r, i, i, input, script, pseudoTX, pseudoTrustedInputs, signature, i, signatureSize, keySize, offset, lockTimeBuffer, result, witness, i, tmpScriptData, decredWitness_1; | ||
var signTx, inputs, associatedKeysets, changePath, outputScriptHex, lockTime, sigHashType, segwit, initialTimestamp, additionals, expiryHeight, onDeviceStreaming, onDeviceSignatureGranted, onDeviceSignatureRequested, useTrustedInputForSegwit, a, e_1, notify, isDecred, isZcash, isXST, startTime, sapling, bech32, useBip143, lockTimeBuffer, nullScript, nullPrevout, defaultVersion, trustedInputs, regularOutputs, signatures, publicKeys, firstRun, resuming, targetTransaction, getTrustedInputCall, outputScript, inputs_1, inputs_1_1, input, trustedInput, sequence, outputs, index, e_2_1, result_1, i, r, i, i, input, script, pseudoTX, pseudoTrustedInputs, signature, i, signatureSize, keySize, offset, result, witness, i, tmpScriptData, decredWitness_1; | ||
var e_2, _a; | ||
@@ -125,2 +125,3 @@ return __generator(this, function (_b) { | ||
isDecred = additionals.includes("decred"); | ||
isZcash = additionals.includes("zcash"); | ||
isXST = additionals.includes("stealthcoin"); | ||
@@ -136,2 +137,4 @@ startTime = Date.now(); | ||
(!!expiryHeight && !isDecred); | ||
lockTimeBuffer = Buffer.alloc(4); | ||
lockTimeBuffer.writeUInt32LE(lockTime, 0); | ||
nullScript = Buffer.alloc(0); | ||
@@ -141,3 +144,3 @@ nullPrevout = Buffer.alloc(0); | ||
!!expiryHeight && !isDecred | ||
? defaultVersion.writeUInt32LE(sapling ? 0x80000004 : 0x80000003, 0) | ||
? defaultVersion.writeUInt32LE(isZcash ? 0x80000005 : sapling ? 0x80000004 : 0x80000003, 0) // v5 format for zcash refer to https://zips.z.cash/zip-0225 | ||
: isXST | ||
@@ -192,3 +195,9 @@ ? defaultVersion.writeUInt32LE(2, 0) | ||
if (expiryHeight && !isDecred) { | ||
targetTransaction.nVersionGroupId = Buffer.from(sapling ? [0x85, 0x20, 0x2f, 0x89] : [0x70, 0x82, 0xc4, 0x03]); | ||
targetTransaction.nVersionGroupId = Buffer.from( | ||
// nVersionGroupId is 0x26A7270A for zcash from https://z.cash/upgrade/nu5/ | ||
isZcash | ||
? [0x0a, 0x27, 0xa7, 0x26] | ||
: sapling | ||
? [0x85, 0x20, 0x2f, 0x89] | ||
: [0x70, 0x82, 0xc4, 0x03]); | ||
targetTransaction.nExpiryHeight = expiryHeight; | ||
@@ -220,3 +229,3 @@ // For sapling : valueBalance (8), nShieldedSpend (1), nShieldedOutput (1), nJoinSplit (1) | ||
case 13: | ||
targetTransaction.inputs = inputs.map(function (input) { | ||
targetTransaction.inputs = inputs.map(function (input, idx) { | ||
var sequence = Buffer.alloc(4); | ||
@@ -227,3 +236,3 @@ sequence.writeUInt32LE(input.length >= 4 && typeof input[3] === "number" | ||
return { | ||
script: nullScript, | ||
script: isZcash ? regularOutputs[idx].script : nullScript, | ||
prevout: nullPrevout, | ||
@@ -363,4 +372,3 @@ sequence: sequence | ||
} | ||
lockTimeBuffer = Buffer.alloc(4); | ||
lockTimeBuffer.writeUInt32LE(lockTime, 0); | ||
targetTransaction.locktime = lockTimeBuffer; | ||
result = Buffer.concat([ | ||
@@ -384,13 +392,12 @@ serializeTransaction(targetTransaction, false, targetTransaction.timestamp, additionals), | ||
} | ||
// FIXME: In ZEC or KMD sapling lockTime is serialized before expiryHeight. | ||
// expiryHeight is used only in overwinter/sapling so I moved lockTimeBuffer here | ||
// and it should not break other coins because expiryHeight is false for them. | ||
// Don't know about Decred though. | ||
result = Buffer.concat([result, lockTimeBuffer]); | ||
if (expiryHeight) { | ||
result = Buffer.concat([ | ||
result, | ||
targetTransaction.nExpiryHeight || Buffer.alloc(0), | ||
targetTransaction.extraData || Buffer.alloc(0), | ||
]); | ||
// from to https://zips.z.cash/zip-0225, zcash is different with other coins, the lock_time and nExpiryHeight fields are before the inputs and outputs | ||
if (!isZcash) { | ||
result = Buffer.concat([result, lockTimeBuffer]); | ||
if (expiryHeight) { | ||
result = Buffer.concat([ | ||
result, | ||
targetTransaction.nExpiryHeight || Buffer.alloc(0), | ||
targetTransaction.extraData || Buffer.alloc(0), | ||
]); | ||
} | ||
} | ||
@@ -411,2 +418,5 @@ if (isDecred) { | ||
} | ||
if (isZcash) { | ||
result = Buffer.concat([result, Buffer.from([0x00, 0x00, 0x00])]); | ||
} | ||
return [2 /*return*/, result.toString("hex")]; | ||
@@ -413,0 +423,0 @@ } |
@@ -26,2 +26,3 @@ import { createVarint } from "./varint"; | ||
var isDecred = additionals.includes("decred"); | ||
var isZcash = additionals.includes("zcash"); | ||
var isBech32 = additionals.includes("bech32"); | ||
@@ -58,2 +59,16 @@ var inputBuffer = Buffer.alloc(0); | ||
} | ||
// from to https://zips.z.cash/zip-0225, zcash is different with other coins, the lock_time and nExpiryHeight fields are before the inputs and outputs | ||
if (isZcash) { | ||
return Buffer.concat([ | ||
transaction.version, | ||
transaction.nVersionGroupId || Buffer.alloc(0), | ||
Buffer.from([0xb4, 0xd0, 0xd6, 0xc2]), | ||
transaction.locktime || Buffer.from([0x00, 0x00, 0x00, 0x00]), | ||
transaction.nExpiryHeight || Buffer.from([0x00, 0x00, 0x00, 0x00]), | ||
useWitness ? Buffer.from("0001", "hex") : Buffer.alloc(0), | ||
createVarint(transaction.inputs.length), | ||
inputBuffer, | ||
outputBuffer, | ||
]); | ||
} | ||
return Buffer.concat([ | ||
@@ -60,0 +75,0 @@ transaction.version, |
@@ -17,8 +17,12 @@ import { log } from "@ledgerhq/logs"; | ||
var extraData = Buffer.alloc(0); | ||
var witnessScript, locktime; | ||
var isDecred = additionals.includes("decred"); | ||
var isZencash = additionals.includes("zencash"); | ||
var isZcash = additionals.includes("zcash"); | ||
var transaction = Buffer.from(transactionHex, "hex"); | ||
var version = transaction.slice(offset, offset + 4); | ||
var overwinter = version.equals(Buffer.from([0x03, 0x00, 0x00, 0x80])) || | ||
version.equals(Buffer.from([0x04, 0x00, 0x00, 0x80])); | ||
version.equals(Buffer.from([0x04, 0x00, 0x00, 0x80])) || | ||
version.equals(Buffer.from([0x05, 0x00, 0x00, 0x80])); | ||
var isZcashv5 = isZcash && version.equals(Buffer.from([0x05, 0x00, 0x00, 0x80])); | ||
offset += 4; | ||
@@ -41,2 +45,7 @@ if (!hasTimestamp && | ||
} | ||
if (isZcashv5) { | ||
locktime = transaction.slice(offset + 4, offset + 8); | ||
nExpiryHeight = transaction.slice(offset + 8, offset + 12); | ||
offset += 12; | ||
} | ||
var varint = getVarint(transaction, offset); | ||
@@ -90,3 +99,2 @@ var numberInputs = varint[0]; | ||
} | ||
var witnessScript, locktime; | ||
if (witness) { | ||
@@ -96,7 +104,7 @@ witnessScript = transaction.slice(offset, -4); | ||
} | ||
else { | ||
else if (!isZcashv5) { | ||
locktime = transaction.slice(offset, offset + 4); | ||
} | ||
offset += 4; | ||
if (overwinter || isDecred) { | ||
if ((overwinter || isDecred) && !isZcashv5) { | ||
nExpiryHeight = transaction.slice(offset, offset + 4); | ||
@@ -103,0 +111,0 @@ offset += 4; |
@@ -86,3 +86,3 @@ "use strict"; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var signTx, inputs, associatedKeysets, changePath, outputScriptHex, lockTime, sigHashType, segwit, initialTimestamp, additionals, expiryHeight, onDeviceStreaming, onDeviceSignatureGranted, onDeviceSignatureRequested, useTrustedInputForSegwit, a, e_1, notify, isDecred, isXST, startTime, sapling, bech32, useBip143, nullScript, nullPrevout, defaultVersion, trustedInputs, regularOutputs, signatures, publicKeys, firstRun, resuming, targetTransaction, getTrustedInputCall, outputScript, inputs_1, inputs_1_1, input, trustedInput, sequence, outputs, index, e_2_1, result_1, i, r, i, i, input, script, pseudoTX, pseudoTrustedInputs, signature, i, signatureSize, keySize, offset, lockTimeBuffer, result, witness, i, tmpScriptData, decredWitness_1; | ||
var signTx, inputs, associatedKeysets, changePath, outputScriptHex, lockTime, sigHashType, segwit, initialTimestamp, additionals, expiryHeight, onDeviceStreaming, onDeviceSignatureGranted, onDeviceSignatureRequested, useTrustedInputForSegwit, a, e_1, notify, isDecred, isZcash, isXST, startTime, sapling, bech32, useBip143, lockTimeBuffer, nullScript, nullPrevout, defaultVersion, trustedInputs, regularOutputs, signatures, publicKeys, firstRun, resuming, targetTransaction, getTrustedInputCall, outputScript, inputs_1, inputs_1_1, input, trustedInput, sequence, outputs, index, e_2_1, result_1, i, r, i, i, input, script, pseudoTX, pseudoTrustedInputs, signature, i, signatureSize, keySize, offset, result, witness, i, tmpScriptData, decredWitness_1; | ||
var e_2, _a; | ||
@@ -128,2 +128,3 @@ return __generator(this, function (_b) { | ||
isDecred = additionals.includes("decred"); | ||
isZcash = additionals.includes("zcash"); | ||
isXST = additionals.includes("stealthcoin"); | ||
@@ -139,2 +140,4 @@ startTime = Date.now(); | ||
(!!expiryHeight && !isDecred); | ||
lockTimeBuffer = Buffer.alloc(4); | ||
lockTimeBuffer.writeUInt32LE(lockTime, 0); | ||
nullScript = Buffer.alloc(0); | ||
@@ -144,3 +147,3 @@ nullPrevout = Buffer.alloc(0); | ||
!!expiryHeight && !isDecred | ||
? defaultVersion.writeUInt32LE(sapling ? 0x80000004 : 0x80000003, 0) | ||
? defaultVersion.writeUInt32LE(isZcash ? 0x80000005 : sapling ? 0x80000004 : 0x80000003, 0) // v5 format for zcash refer to https://zips.z.cash/zip-0225 | ||
: isXST | ||
@@ -195,3 +198,9 @@ ? defaultVersion.writeUInt32LE(2, 0) | ||
if (expiryHeight && !isDecred) { | ||
targetTransaction.nVersionGroupId = Buffer.from(sapling ? [0x85, 0x20, 0x2f, 0x89] : [0x70, 0x82, 0xc4, 0x03]); | ||
targetTransaction.nVersionGroupId = Buffer.from( | ||
// nVersionGroupId is 0x26A7270A for zcash from https://z.cash/upgrade/nu5/ | ||
isZcash | ||
? [0x0a, 0x27, 0xa7, 0x26] | ||
: sapling | ||
? [0x85, 0x20, 0x2f, 0x89] | ||
: [0x70, 0x82, 0xc4, 0x03]); | ||
targetTransaction.nExpiryHeight = expiryHeight; | ||
@@ -223,3 +232,3 @@ // For sapling : valueBalance (8), nShieldedSpend (1), nShieldedOutput (1), nJoinSplit (1) | ||
case 13: | ||
targetTransaction.inputs = inputs.map(function (input) { | ||
targetTransaction.inputs = inputs.map(function (input, idx) { | ||
var sequence = Buffer.alloc(4); | ||
@@ -230,3 +239,3 @@ sequence.writeUInt32LE(input.length >= 4 && typeof input[3] === "number" | ||
return { | ||
script: nullScript, | ||
script: isZcash ? regularOutputs[idx].script : nullScript, | ||
prevout: nullPrevout, | ||
@@ -366,4 +375,3 @@ sequence: sequence | ||
} | ||
lockTimeBuffer = Buffer.alloc(4); | ||
lockTimeBuffer.writeUInt32LE(lockTime, 0); | ||
targetTransaction.locktime = lockTimeBuffer; | ||
result = Buffer.concat([ | ||
@@ -387,13 +395,12 @@ (0, serializeTransaction_1.serializeTransaction)(targetTransaction, false, targetTransaction.timestamp, additionals), | ||
} | ||
// FIXME: In ZEC or KMD sapling lockTime is serialized before expiryHeight. | ||
// expiryHeight is used only in overwinter/sapling so I moved lockTimeBuffer here | ||
// and it should not break other coins because expiryHeight is false for them. | ||
// Don't know about Decred though. | ||
result = Buffer.concat([result, lockTimeBuffer]); | ||
if (expiryHeight) { | ||
result = Buffer.concat([ | ||
result, | ||
targetTransaction.nExpiryHeight || Buffer.alloc(0), | ||
targetTransaction.extraData || Buffer.alloc(0), | ||
]); | ||
// from to https://zips.z.cash/zip-0225, zcash is different with other coins, the lock_time and nExpiryHeight fields are before the inputs and outputs | ||
if (!isZcash) { | ||
result = Buffer.concat([result, lockTimeBuffer]); | ||
if (expiryHeight) { | ||
result = Buffer.concat([ | ||
result, | ||
targetTransaction.nExpiryHeight || Buffer.alloc(0), | ||
targetTransaction.extraData || Buffer.alloc(0), | ||
]); | ||
} | ||
} | ||
@@ -414,2 +421,5 @@ if (isDecred) { | ||
} | ||
if (isZcash) { | ||
result = Buffer.concat([result, Buffer.from([0x00, 0x00, 0x00])]); | ||
} | ||
return [2 /*return*/, result.toString("hex")]; | ||
@@ -416,0 +426,0 @@ } |
@@ -30,2 +30,3 @@ "use strict"; | ||
var isDecred = additionals.includes("decred"); | ||
var isZcash = additionals.includes("zcash"); | ||
var isBech32 = additionals.includes("bech32"); | ||
@@ -62,2 +63,16 @@ var inputBuffer = Buffer.alloc(0); | ||
} | ||
// from to https://zips.z.cash/zip-0225, zcash is different with other coins, the lock_time and nExpiryHeight fields are before the inputs and outputs | ||
if (isZcash) { | ||
return Buffer.concat([ | ||
transaction.version, | ||
transaction.nVersionGroupId || Buffer.alloc(0), | ||
Buffer.from([0xb4, 0xd0, 0xd6, 0xc2]), | ||
transaction.locktime || Buffer.from([0x00, 0x00, 0x00, 0x00]), | ||
transaction.nExpiryHeight || Buffer.from([0x00, 0x00, 0x00, 0x00]), | ||
useWitness ? Buffer.from("0001", "hex") : Buffer.alloc(0), | ||
(0, varint_1.createVarint)(transaction.inputs.length), | ||
inputBuffer, | ||
outputBuffer, | ||
]); | ||
} | ||
return Buffer.concat([ | ||
@@ -64,0 +79,0 @@ transaction.version, |
@@ -20,8 +20,12 @@ "use strict"; | ||
var extraData = Buffer.alloc(0); | ||
var witnessScript, locktime; | ||
var isDecred = additionals.includes("decred"); | ||
var isZencash = additionals.includes("zencash"); | ||
var isZcash = additionals.includes("zcash"); | ||
var transaction = Buffer.from(transactionHex, "hex"); | ||
var version = transaction.slice(offset, offset + 4); | ||
var overwinter = version.equals(Buffer.from([0x03, 0x00, 0x00, 0x80])) || | ||
version.equals(Buffer.from([0x04, 0x00, 0x00, 0x80])); | ||
version.equals(Buffer.from([0x04, 0x00, 0x00, 0x80])) || | ||
version.equals(Buffer.from([0x05, 0x00, 0x00, 0x80])); | ||
var isZcashv5 = isZcash && version.equals(Buffer.from([0x05, 0x00, 0x00, 0x80])); | ||
offset += 4; | ||
@@ -44,2 +48,7 @@ if (!hasTimestamp && | ||
} | ||
if (isZcashv5) { | ||
locktime = transaction.slice(offset + 4, offset + 8); | ||
nExpiryHeight = transaction.slice(offset + 8, offset + 12); | ||
offset += 12; | ||
} | ||
var varint = (0, varint_1.getVarint)(transaction, offset); | ||
@@ -93,3 +102,2 @@ var numberInputs = varint[0]; | ||
} | ||
var witnessScript, locktime; | ||
if (witness) { | ||
@@ -99,7 +107,7 @@ witnessScript = transaction.slice(offset, -4); | ||
} | ||
else { | ||
else if (!isZcashv5) { | ||
locktime = transaction.slice(offset, offset + 4); | ||
} | ||
offset += 4; | ||
if (overwinter || isDecred) { | ||
if ((overwinter || isDecred) && !isZcashv5) { | ||
nExpiryHeight = transaction.slice(offset, offset + 4); | ||
@@ -106,0 +114,0 @@ offset += 4; |
{ | ||
"name": "@ledgerhq/hw-app-btc", | ||
"version": "8.0.2", | ||
"version": "8.1.0-nightly.0", | ||
"description": "Ledger Hardware Wallet Bitcoin Application API", | ||
@@ -72,4 +72,4 @@ "keywords": [ | ||
"dependencies": { | ||
"@ledgerhq/hw-transport": "^6.27.4", | ||
"@ledgerhq/logs": "^6.10.0", | ||
"@ledgerhq/hw-transport": "^6.27.5-nightly.0", | ||
"@ledgerhq/logs": "^6.10.1-nightly.0", | ||
"bip32-path": "^0.4.2", | ||
@@ -87,4 +87,4 @@ "bitcoinjs-lib": "^5.2.0", | ||
"devDependencies": { | ||
"@ledgerhq/hw-transport-mocker": "^6.27.4", | ||
"@ledgerhq/hw-transport-node-speculos": "^6.27.4", | ||
"@ledgerhq/hw-transport-mocker": "^6.27.5-nightly.0", | ||
"@ledgerhq/hw-transport-node-speculos": "^6.27.5-nightly.0", | ||
"axios": "^0.25.0" | ||
@@ -91,0 +91,0 @@ }, |
@@ -116,2 +116,3 @@ import { log } from "@ledgerhq/logs"; | ||
const isDecred = additionals.includes("decred"); | ||
const isZcash = additionals.includes("zcash"); | ||
const isXST = additionals.includes("stealthcoin"); | ||
@@ -130,2 +131,4 @@ const startTime = Date.now(); | ||
// associatedKeysets are provided as arrays of [path] | ||
const lockTimeBuffer = Buffer.alloc(4); | ||
lockTimeBuffer.writeUInt32LE(lockTime, 0); | ||
const nullScript = Buffer.alloc(0); | ||
@@ -135,3 +138,6 @@ const nullPrevout = Buffer.alloc(0); | ||
!!expiryHeight && !isDecred | ||
? defaultVersion.writeUInt32LE(sapling ? 0x80000004 : 0x80000003, 0) | ||
? defaultVersion.writeUInt32LE( | ||
isZcash ? 0x80000005 : sapling ? 0x80000004 : 0x80000003, | ||
0 | ||
) // v5 format for zcash refer to https://zips.z.cash/zip-0225 | ||
: isXST | ||
@@ -158,3 +164,2 @@ ? defaultVersion.writeUInt32LE(2, 0) | ||
notify(0, 0); | ||
// first pass on inputs to get trusted inputs | ||
@@ -193,3 +198,8 @@ for (const input of inputs) { | ||
targetTransaction.nVersionGroupId = Buffer.from( | ||
sapling ? [0x85, 0x20, 0x2f, 0x89] : [0x70, 0x82, 0xc4, 0x03] | ||
// nVersionGroupId is 0x26A7270A for zcash from https://z.cash/upgrade/nu5/ | ||
isZcash | ||
? [0x0a, 0x27, 0xa7, 0x26] | ||
: sapling | ||
? [0x85, 0x20, 0x2f, 0x89] | ||
: [0x70, 0x82, 0xc4, 0x03] | ||
); | ||
@@ -209,3 +219,3 @@ targetTransaction.nExpiryHeight = expiryHeight; | ||
targetTransaction.inputs = inputs.map((input) => { | ||
targetTransaction.inputs = inputs.map((input, idx) => { | ||
const sequence = Buffer.alloc(4); | ||
@@ -219,3 +229,3 @@ sequence.writeUInt32LE( | ||
return { | ||
script: nullScript, | ||
script: isZcash ? regularOutputs[idx].script : nullScript, | ||
prevout: nullPrevout, | ||
@@ -376,5 +386,3 @@ sequence, | ||
} | ||
const lockTimeBuffer = Buffer.alloc(4); | ||
lockTimeBuffer.writeUInt32LE(lockTime, 0); | ||
targetTransaction.locktime = lockTimeBuffer; | ||
let result = Buffer.concat([ | ||
@@ -407,16 +415,13 @@ serializeTransaction( | ||
// FIXME: In ZEC or KMD sapling lockTime is serialized before expiryHeight. | ||
// expiryHeight is used only in overwinter/sapling so I moved lockTimeBuffer here | ||
// and it should not break other coins because expiryHeight is false for them. | ||
// Don't know about Decred though. | ||
result = Buffer.concat([result, lockTimeBuffer]); | ||
if (expiryHeight) { | ||
result = Buffer.concat([ | ||
result, | ||
targetTransaction.nExpiryHeight || Buffer.alloc(0), | ||
targetTransaction.extraData || Buffer.alloc(0), | ||
]); | ||
// from to https://zips.z.cash/zip-0225, zcash is different with other coins, the lock_time and nExpiryHeight fields are before the inputs and outputs | ||
if (!isZcash) { | ||
result = Buffer.concat([result, lockTimeBuffer]); | ||
if (expiryHeight) { | ||
result = Buffer.concat([ | ||
result, | ||
targetTransaction.nExpiryHeight || Buffer.alloc(0), | ||
targetTransaction.extraData || Buffer.alloc(0), | ||
]); | ||
} | ||
} | ||
if (isDecred) { | ||
@@ -436,4 +441,6 @@ let decredWitness = Buffer.from([targetTransaction.inputs.length]); | ||
} | ||
if (isZcash) { | ||
result = Buffer.concat([result, Buffer.from([0x00, 0x00, 0x00])]); | ||
} | ||
return result.toString("hex"); | ||
} |
@@ -33,2 +33,3 @@ import type { Transaction } from "./types"; | ||
const isDecred = additionals.includes("decred"); | ||
const isZcash = additionals.includes("zcash"); | ||
const isBech32 = additionals.includes("bech32"); | ||
@@ -69,3 +70,16 @@ let inputBuffer = Buffer.alloc(0); | ||
} | ||
// from to https://zips.z.cash/zip-0225, zcash is different with other coins, the lock_time and nExpiryHeight fields are before the inputs and outputs | ||
if (isZcash) { | ||
return Buffer.concat([ | ||
transaction.version, | ||
transaction.nVersionGroupId || Buffer.alloc(0), | ||
Buffer.from([0xb4, 0xd0, 0xd6, 0xc2]), // Zcash Consensus Branch ID: 0xC2D6D0B4 refer to https://z.cash/upgrade/nu5/ | ||
transaction.locktime || Buffer.from([0x00, 0x00, 0x00, 0x00]), | ||
transaction.nExpiryHeight || Buffer.from([0x00, 0x00, 0x00, 0x00]), | ||
useWitness ? Buffer.from("0001", "hex") : Buffer.alloc(0), | ||
createVarint(transaction.inputs.length), | ||
inputBuffer, | ||
outputBuffer, | ||
]); | ||
} | ||
return Buffer.concat([ | ||
@@ -72,0 +86,0 @@ transaction.version, |
@@ -20,4 +20,6 @@ import { log } from "@ledgerhq/logs"; | ||
let extraData = Buffer.alloc(0); | ||
let witnessScript, locktime; | ||
const isDecred = additionals.includes("decred"); | ||
const isZencash = additionals.includes("zencash"); | ||
const isZcash = additionals.includes("zcash"); | ||
const transaction = Buffer.from(transactionHex, "hex"); | ||
@@ -27,3 +29,6 @@ const version = transaction.slice(offset, offset + 4); | ||
version.equals(Buffer.from([0x03, 0x00, 0x00, 0x80])) || | ||
version.equals(Buffer.from([0x04, 0x00, 0x00, 0x80])); | ||
version.equals(Buffer.from([0x04, 0x00, 0x00, 0x80])) || | ||
version.equals(Buffer.from([0x05, 0x00, 0x00, 0x80])); | ||
const isZcashv5 = | ||
isZcash && version.equals(Buffer.from([0x05, 0x00, 0x00, 0x80])); | ||
offset += 4; | ||
@@ -50,3 +55,7 @@ if ( | ||
} | ||
if (isZcashv5) { | ||
locktime = transaction.slice(offset + 4, offset + 8); | ||
nExpiryHeight = transaction.slice(offset + 8, offset + 12); | ||
offset += 12; | ||
} | ||
let varint = getVarint(transaction, offset); | ||
@@ -83,7 +92,5 @@ const numberInputs = varint[0]; | ||
} | ||
varint = getVarint(transaction, offset); | ||
const numberOutputs = varint[0]; | ||
offset += varint[1]; | ||
for (let i = 0; i < numberOutputs; i++) { | ||
@@ -108,8 +115,6 @@ const amount = transaction.slice(offset, offset + 8); | ||
let witnessScript, locktime; | ||
if (witness) { | ||
witnessScript = transaction.slice(offset, -4); | ||
locktime = transaction.slice(transaction.length - 4); | ||
} else { | ||
} else if (!isZcashv5) { | ||
locktime = transaction.slice(offset, offset + 4); | ||
@@ -120,3 +125,3 @@ } | ||
if (overwinter || isDecred) { | ||
if ((overwinter || isDecred) && !isZcashv5) { | ||
nExpiryHeight = transaction.slice(offset, offset + 4); | ||
@@ -123,0 +128,0 @@ offset += 4; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
1204493
18563
1