Skip to content

Commit 9256fdd

Browse files
fix(ledger): fix output format mapping on ledger HW devices
1 parent ab26ecf commit 9256fdd

File tree

8 files changed

+28
-37
lines changed

8 files changed

+28
-37
lines changed

packages/hardware-ledger/src/LedgerKeyAgent.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -715,15 +715,18 @@ export class LedgerKeyAgent extends KeyAgentBase {
715715
): Promise<Cardano.Signatures> {
716716
try {
717717
const body = txBody.toCore();
718+
718719
const hash = txBody.hash() as unknown as HexBlob;
719720
const dRepPublicKey = await this.derivePublicKey(util.DREP_KEY_DERIVATION_PATH);
720721
const dRepKeyHashHex = (await Crypto.Ed25519PublicKey.fromHex(dRepPublicKey).hash()).hex();
722+
721723
const ledgerTxData = await toLedgerTx(body, {
722724
accountIndex: this.accountIndex,
723725
chainId: this.chainId,
724726
dRepKeyHashHex,
725727
knownAddresses,
726-
txInKeyPathMap
728+
txInKeyPathMap,
729+
useBabbageOutputs: txBody.hasBabbageOutput()
727730
});
728731

729732
const deviceConnection = await LedgerKeyAgent.checkDeviceConnection(

packages/hardware-ledger/src/transformers/txOut.ts

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -56,39 +56,11 @@ const getScriptHex = (output: Serialization.TransactionOutput): HexBlob | null =
5656
return scriptRef.toCbor();
5757
};
5858

59-
/**
60-
* There are currently two types of outputs supported by the ledger:
61-
*
62-
* legacy_transaction_output =
63-
* [ address
64-
* , amount : value
65-
* , ? datum_hash : $hash32
66-
* ]
67-
*
68-
* and
69-
*
70-
* post_alonzo_transaction_output =
71-
* { 0 : address
72-
* , 1 : value
73-
* , ? 2 : datum_option ; New; datum option
74-
* , ? 3 : script_ref ; New; script reference
75-
* }
76-
*
77-
* Legacy outputs are definite length arrays of three elements, however the new babbage outputs are definite length maps
78-
* of four elements.
79-
*
80-
* @param out The output to be verified.
81-
*/
82-
const isBabbage = (out: Serialization.TransactionOutput): boolean => {
83-
const reader = new Serialization.CborReader(out.toCbor());
84-
return reader.peekState() === Serialization.CborReaderState.StartMap;
85-
};
86-
8759
export const toTxOut: Transform<Cardano.TxOut, Ledger.TxOutput, LedgerTxTransformerContext> = (txOut, context) => {
8860
const output = Serialization.TransactionOutput.fromCore(txOut);
8961
const scriptHex = getScriptHex(output);
9062

91-
return isBabbage(output)
63+
return context?.useBabbageOutputs
9264
? {
9365
amount: txOut.value.coins,
9466
datum: txOut.datumHash ? toDatumHash(txOut.datumHash) : txOut.datum ? toInlineDatum(txOut.datum) : null,

packages/hardware-ledger/src/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,6 @@ export type LedgerTxTransformerContext = {
2121
chainId: Cardano.ChainId;
2222
/** Non-hardened account in cip1852 */
2323
accountIndex: number;
24+
/** Whether to use Babbage output format or not. */
25+
useBabbageOutputs: boolean;
2426
} & SignTransactionContext;

packages/hardware-ledger/test/testData.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,8 @@ export const CONTEXT_WITH_KNOWN_ADDRESSES: LedgerTxTransformerContext = {
357357
type: AddressType.Internal
358358
}
359359
],
360-
txInKeyPathMap: {}
360+
txInKeyPathMap: {},
361+
useBabbageOutputs: true
361362
};
362363

363364
export const CONTEXT_WITHOUT_KNOWN_ADDRESSES: LedgerTxTransformerContext = {
@@ -367,7 +368,8 @@ export const CONTEXT_WITHOUT_KNOWN_ADDRESSES: LedgerTxTransformerContext = {
367368
networkMagic: 999
368369
},
369370
knownAddresses: [],
370-
txInKeyPathMap: {}
371+
txInKeyPathMap: {},
372+
useBabbageOutputs: true
371373
};
372374

373375
export const votes = [

packages/hardware-ledger/test/transformers/certificates.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ const mockContext: LedgerTxTransformerContext = {
8585
txInKeyPathMap: createTxInKeyPathMapMock([
8686
createGroupedAddress(address1, ownRewardAccount, AddressType.External, 0, stakeKeyPath),
8787
createGroupedAddress(address2, ownRewardAccount, AddressType.External, 1, stakeKeyPath)
88-
])
88+
]),
89+
useBabbageOutputs: true
8990
};
9091

9192
const EXAMPLE_URL = 'https://example.com';

packages/hardware-ledger/test/transformers/tx.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ describe('tx', () => {
1515
txInKeyPathMap: {
1616
[TxInId(tx.body.inputs[0])]: paymentKeyPath,
1717
[TxInId(tx.body.collaterals![0])]: paymentKeyPath
18-
}
18+
},
19+
useBabbageOutputs: false
1920
})
2021
).toEqual({
2122
auxiliaryData: {
@@ -267,7 +268,8 @@ describe('tx', () => {
267268

268269
expect(
269270
await toLedgerTx(txBodyWithRegistrationCert, {
270-
...CONTEXT_WITH_KNOWN_ADDRESSES
271+
...CONTEXT_WITH_KNOWN_ADDRESSES,
272+
useBabbageOutputs: false
271273
})
272274
).toEqual({
273275
auxiliaryData: {

packages/hardware-ledger/test/transformers/txOut.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ describe('txOut', () => {
6464

6565
describe('toTxOut', () => {
6666
it('can map a simple txOut to third party address', async () => {
67-
const out = toTxOut(txOut, CONTEXT_WITH_KNOWN_ADDRESSES);
67+
const out = toTxOut(txOut, { ...CONTEXT_WITH_KNOWN_ADDRESSES, useBabbageOutputs: false });
6868

6969
expect(out).toEqual({
7070
amount: 10n,
@@ -114,7 +114,7 @@ describe('txOut', () => {
114114
});
115115

116116
it('can map a simple txOut to owned address', async () => {
117-
const out = toTxOut(txOutToOwnedAddress, CONTEXT_WITH_KNOWN_ADDRESSES);
117+
const out = toTxOut(txOutToOwnedAddress, { ...CONTEXT_WITH_KNOWN_ADDRESSES, useBabbageOutputs: false });
118118

119119
expect(out).toEqual({
120120
amount: 10n,

packages/wallet/test/hardware/ledger/LedgerKeyAgent.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,15 @@ describe('LedgerKeyAgent', () => {
230230
expect(signatures.size).toBe(2);
231231
});
232232

233+
it('successfully signs ADA handle mint transaction', async () => {
234+
const cbor =
235+
'84a500818258207aa1264bcd0c06f34a49ed1dd7307a2bdec5a97bdeb546498759ad5b8ed42fd5010182a200583930195bde3deacb613b7e9eb6280b14db4e353e475e96d19f3f7a5e2d66195bde3deacb613b7e9eb6280b14db4e353e475e96d19f3f7a5e2d66011a00e4e1c0a2005839003d3246dc0c50ab3c74a8ffdd8068313ff99d341c461a8fe31f416d0a8fba06d60d71edc077cc5ebcb8ff82137afbce68df98271909332348011b000000025106a838021a00029309031a04a07bc6081a04a07a40a0f5f6';
236+
const {
237+
witness: { signatures }
238+
} = await wallet.finalizeTx({ tx: cbor as any });
239+
expect(signatures.size).toBe(1);
240+
});
241+
233242
it('throws if signed transaction hash doesnt match hash computed by the wallet', async () => {
234243
const originalHashFn = Serialization.TransactionBody.prototype.hash;
235244
jest

0 commit comments

Comments
 (0)