From 50f5f1b72f53a92563f1ffe580128491e87f14f7 Mon Sep 17 00:00:00 2001 From: Emmanuel Date: Tue, 19 Nov 2024 12:10:15 -0300 Subject: [PATCH] feat: add error description for DKG app (#22) * chore: bump ledger-js version * feat: add error description for DKG app * feat: use custom error descriptions --- package.json | 2 +- src/consts.ts | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/index.ts | 39 ++++++++++++++++--------------- 3 files changed, 85 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index f2cc33a..057b550 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "url": "https://github.com/zondax/ledger-ironfish-js/issues" }, "dependencies": { - "@zondax/ledger-js": "^1.0.1" + "@zondax/ledger-js": "^1.2.0" }, "devDependencies": { "@trivago/prettier-plugin-sort-imports": "^4.3.0", diff --git a/src/consts.ts b/src/consts.ts index 4e9f853..d0c2cc5 100644 --- a/src/consts.ts +++ b/src/consts.ts @@ -16,3 +16,67 @@ export const REDJUBJUB_SIGNATURE_LEN = 64 export const ED25519_SIGNATURE_LEN = 64 export const IDENTITY_LEN = VERSION + KEY_LENGTH + KEY_LENGTH + ED25519_SIGNATURE_LEN export const TX_HASH_LEN = 32 + +export enum LedgerAppError { + AddrDisplayFail = 0xb002, + TxWrongLength = 0xb004, + TxParsingFail = 0xb005, + TxSignFail = 0xb008, + KeyDeriveFail = 0xb009, + VersionParsingFail = 0xb00a, + DkgRound2Fail = 0xb00b, + DkgRound3Fail = 0xb00c, + InvalidKeyType = 0xb00d, + InvalidIdentity = 0xb00e, + InvalidPayload = 0xb00f, + BufferOutOfBounds = 0xb010, + InvalidSigningPackage = 0xb011, + InvalidRandomizer = 0xb012, + InvalidSigningNonces = 0xb013, + InvalidIdentityIndex = 0xb014, + InvalidKeyPackage = 0xb015, + InvalidPublicPackage = 0xb016, + InvalidGroupSecretKey = 0xb017, + InvalidScalar = 0xb018, + DecryptionFail = 0xb019, + EncryptionFail = 0xb020, + InvalidNVMWrite = 0xb021, + InvalidDkgStatus = 0xb022, + InvalidDkgKeysVersion = 0xb023, + TooManyParticipants = 0xb024, + InvalidTxHash = 0xb025, + InvalidToken = 0xb026, + ErrExpertModeMustBeEnabled = 0xb027, +} + +export const ERROR_DESCRIPTION_OVERRIDE: Readonly> = { + [LedgerAppError.AddrDisplayFail]: 'Invalid address', + [LedgerAppError.TxWrongLength]: 'Tx too long', + [LedgerAppError.TxParsingFail]: 'Tx parsing failed', + [LedgerAppError.TxSignFail]: 'Tx signing failed', + [LedgerAppError.KeyDeriveFail]: 'Invalid signing key', + [LedgerAppError.VersionParsingFail]: 'Invalid tx version', + [LedgerAppError.DkgRound2Fail]: 'Round 2 has failed', + [LedgerAppError.DkgRound3Fail]: 'Round 3 has failed', + [LedgerAppError.InvalidKeyType]: 'Invalid key type', + [LedgerAppError.InvalidIdentity]: 'Invalid identity', + [LedgerAppError.InvalidPayload]: 'Invalid payload', + [LedgerAppError.BufferOutOfBounds]: 'Buffer out of bounds', + [LedgerAppError.InvalidSigningPackage]: 'Invalid signing package', + [LedgerAppError.InvalidRandomizer]: 'Invalid tx randomizer', + [LedgerAppError.InvalidSigningNonces]: 'Invalid signing nonces', + [LedgerAppError.InvalidIdentityIndex]: 'Invalid identity index', + [LedgerAppError.InvalidKeyPackage]: 'Invalid key package', + [LedgerAppError.InvalidPublicPackage]: 'Invalid public package', + [LedgerAppError.InvalidGroupSecretKey]: 'Invalid group secret key', + [LedgerAppError.InvalidScalar]: 'Invalid scalar', + [LedgerAppError.DecryptionFail]: 'Keys decryption failed', + [LedgerAppError.EncryptionFail]: 'Keys encryption failed', + [LedgerAppError.InvalidNVMWrite]: 'Invalid flash write', + [LedgerAppError.InvalidDkgStatus]: 'Invalid dkg process status', + [LedgerAppError.InvalidDkgKeysVersion]: 'Invalid keys version', + [LedgerAppError.TooManyParticipants]: 'Too many participants for DKG', + [LedgerAppError.InvalidTxHash]: 'Invalid tx hash', + [LedgerAppError.InvalidToken]: 'Invalid asset', + [LedgerAppError.ErrExpertModeMustBeEnabled]: 'Expert mode is required', +} diff --git a/src/index.ts b/src/index.ts index eb458e4..9d17431 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,7 +17,7 @@ import GenericApp, { ConstructorParams, LedgerError, Transport, processErrorResponse, processResponse } from '@zondax/ledger-js' import { ResponsePayload } from '@zondax/ledger-js/dist/payload' -import { P2_VALUES } from './consts' +import { ERROR_DESCRIPTION_OVERRIDE, P2_VALUES } from './consts' import { deserializeDkgRound1, deserializeDkgRound2, deserializeGetIdentities, deserializeReviewTx } from './deserialize' import { processGetIdentityResponse, processGetKeysResponse } from './helper' import { serializeDkgGetCommitments, serializeDkgRound1, serializeDkgRound2, serializeDkgRound3Min, serializeDkgSign } from './serialize' @@ -78,6 +78,7 @@ export default class IronfishApp extends GenericApp { }, acceptedPathLengths: [3], chunkSize: 250, + customAppErrorDescription: ERROR_DESCRIPTION_OVERRIDE, } super(transport, params) } @@ -87,7 +88,7 @@ export default class IronfishApp extends GenericApp { const p1 = showInDevice ? this.P1_VALUES.SHOW_ADDRESS_IN_DEVICE : this.P1_VALUES.ONLY_RETRIEVE const response = await this.transport.send(this.CLA, this.INS.GET_KEYS, p1, keyType, serializedPath, [LedgerError.NoErrors]) - const payload = processResponse(response) + const payload = processResponse(response, this.CUSTOM_APP_ERROR_DESCRIPTION) return processGetKeysResponse(payload, keyType) } @@ -103,7 +104,7 @@ export default class IronfishApp extends GenericApp { signature: result.readBytes(result.length()), } } catch (e) { - throw processErrorResponse(e) + throw processErrorResponse(e, this.CUSTOM_APP_ERROR_DESCRIPTION) } } @@ -113,7 +114,7 @@ export default class IronfishApp extends GenericApp { const p1 = showInDevice ? 1 : 0 const response = await this.transport.send(this.CLA, this.INS.DKG_IDENTITY, p1, 0, req, [LedgerError.NoErrors]) - const data = processResponse(response) + const data = processResponse(response, this.CUSTOM_APP_ERROR_DESCRIPTION) return processGetIdentityResponse(data) } @@ -130,7 +131,7 @@ export default class IronfishApp extends GenericApp { let result = await this.getResult(rawResponse) return deserializeDkgRound1(result) } catch (e) { - throw processErrorResponse(e) + throw processErrorResponse(e, this.CUSTOM_APP_ERROR_DESCRIPTION) } } @@ -147,7 +148,7 @@ export default class IronfishApp extends GenericApp { let result = await this.getResult(rawResponse) return deserializeDkgRound2(result) } catch (e) { - throw processErrorResponse(e) + throw processErrorResponse(e, this.CUSTOM_APP_ERROR_DESCRIPTION) } } @@ -167,7 +168,7 @@ export default class IronfishApp extends GenericApp { await this.sendGenericChunk(this.INS.DKG_ROUND_3_MIN, P2_VALUES.DEFAULT, 1 + i, chunks.length, chunks[i]) } } catch (e) { - throw processErrorResponse(e) + throw processErrorResponse(e, this.CUSTOM_APP_ERROR_DESCRIPTION) } } @@ -186,7 +187,7 @@ export default class IronfishApp extends GenericApp { commitments: result, } } catch (e) { - throw processErrorResponse(e) + throw processErrorResponse(e, this.CUSTOM_APP_ERROR_DESCRIPTION) } } @@ -205,14 +206,14 @@ export default class IronfishApp extends GenericApp { signature: result, } } catch (e) { - throw processErrorResponse(e) + throw processErrorResponse(e, this.CUSTOM_APP_ERROR_DESCRIPTION) } } async dkgGetPublicPackage(): Promise { try { let response = await this.transport.send(this.CLA, this.INS.DKG_GET_PUBLIC_PACKAGE, 0, 0, Buffer.alloc(0), [LedgerError.NoErrors]) - let data = processResponse(response) + let data = processResponse(response, this.CUSTOM_APP_ERROR_DESCRIPTION) let result = await this.getResult(data) @@ -220,14 +221,14 @@ export default class IronfishApp extends GenericApp { publicPackage: result, } } catch (e) { - throw processErrorResponse(e) + throw processErrorResponse(e, this.CUSTOM_APP_ERROR_DESCRIPTION) } } async dkgBackupKeys(): Promise { try { let response = await this.transport.send(this.CLA, this.INS.DKG_BACKUP_KEYS, 0, 0, Buffer.alloc(0), [LedgerError.NoErrors]) - let data = processResponse(response) + let data = processResponse(response, this.CUSTOM_APP_ERROR_DESCRIPTION) let result = await this.getResult(data) @@ -235,26 +236,26 @@ export default class IronfishApp extends GenericApp { encryptedKeys: result, } } catch (e) { - throw processErrorResponse(e) + throw processErrorResponse(e, this.CUSTOM_APP_ERROR_DESCRIPTION) } } async dkgGetIdentities(): Promise { try { let response = await this.transport.send(this.CLA, this.INS.DKG_IDENTITIES, 0, 0, Buffer.alloc(0), [LedgerError.NoErrors]) - let data = processResponse(response) + let data = processResponse(response, this.CUSTOM_APP_ERROR_DESCRIPTION) let result = await this.getResult(data) return deserializeGetIdentities(result) } catch (e) { - throw processErrorResponse(e) + throw processErrorResponse(e, this.CUSTOM_APP_ERROR_DESCRIPTION) } } async dkgRetrieveKeys(keyType: IronfishKeys, showInDevice?: boolean): Promise { const p1 = showInDevice ? 1 : 0 const response = await this.transport.send(this.CLA, this.INS.DKG_GET_KEYS, p1, keyType, Buffer.alloc(0), [LedgerError.NoErrors]) - const data = processResponse(response) + const data = processResponse(response, this.CUSTOM_APP_ERROR_DESCRIPTION) return processGetKeysResponse(data, keyType) } @@ -266,7 +267,7 @@ export default class IronfishApp extends GenericApp { await this.sendGenericChunk(this.INS.DKG_RESTORE_KEYS, P2_VALUES.DEFAULT, 1 + i, chunks.length, chunks[i]) } } catch (e) { - throw processErrorResponse(e) + throw processErrorResponse(e, this.CUSTOM_APP_ERROR_DESCRIPTION) } } @@ -283,7 +284,7 @@ export default class IronfishApp extends GenericApp { let result = await this.getResult(rawResponse) return deserializeReviewTx(result) } catch (e) { - throw processErrorResponse(e) + throw processErrorResponse(e, this.CUSTOM_APP_ERROR_DESCRIPTION) } } @@ -293,7 +294,7 @@ export default class IronfishApp extends GenericApp { let chunks = rawResponse.readBytes(1).readUint8() for (let i = 0; i < chunks; i++) { let result = await this.transport.send(this.CLA, this.INS.GET_RESULT, i, 0, Buffer.alloc(0)) - let response = processResponse(result) + let response = processResponse(result, this.CUSTOM_APP_ERROR_DESCRIPTION) data = Buffer.concat([data, response.getCompleteBuffer()]) }