diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 1253d5cd..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,44 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](http://keepachangelog.com/) -and this project adheres to [Semantic Versioning](http://semver.org/). - -## [2.0.13](https://github.com/ledgerhq/app-exchange/compare/2.0.12...2.0.13) - 2022-??-?? - -### Changed - -- Application name length is no longer caped to 15B, but synced with BOLOS maximum length - -## [2.0.12](https://github.com/ledgerhq/app-exchange/compare/2.0.11...2.0.12) - 2022-10-19 - -### Added - -- DERIVE_MASTER flag, needed for app-bitcoin-new v2.1+ - -## [2.0.11](https://github.com/ledgerhq/app-exchange/compare/2.0.3...2.0.11) - 2022-05-24 - -TODO - -## [2.0.3](https://github.com/ledgerhq/app-exchange/compare/2.0.2...2.0.3) - 2020-12-10 - -### Added - -- Github Action CI to check code style and compilation -- Project config for vscode -- Changelog file -- Add tests for XRP -- Expect result value from `get_printed_amount` call - -### Changed - -- Update `clang-format` style - -### Removed - -- Remove generated js file folder `test/lib` from versioning - -### Fixed - -- Revamped tests with Zemu diff --git a/protocol.md b/protocol.md index b2f54847..df95cf02 100644 --- a/protocol.md +++ b/protocol.md @@ -1,55 +1,248 @@ # Protocol to speak with EXCHANGE application -Communication is done in request-response maner. -### Request: -| Bytes | Meaning | -| ------------- | ------------- | -| 0xE0 | Universal constant | -| COMMAND | Byte for command, each command is described below | -| 0x00 | not used | -| 0x00 | not used | -| N bytes | command data, depends on specific command| - - - -Posible commands: - -| Name | Value | Description | -| ---- | ----- | ----------- | -| GET_VERSION_COMMAND | 0x02 | Get application version | -| START_NEW_TRANSACTION_COMMAND | 0x03 | Start new EXCHANGE transaction | -| SET_PARTNER_KEY_COMMAND | 0x04 | Set partner public key | -| CHECK_PARTNER_COMMAND | 0x05 | Set partner public key | -| PROCESS_TRANSACTION_RESPONS | 0x06 | Process transaction received from partner| -| CHECK_TRANSACTION_SIGNATURE | 0x07 | Check signature of partner transaction | -| CHECK_PAYOUT_ADDRES | 0x08 | Check that payout address belong to us | -| CHECK_REFUND_ADDRES | 0x09 | Check that refund address belong to us | -### Response: -| Bytes | Meaning | -| ------------- | ------------- | + +Communication is done through a serie of request-response exchanges (APDU / RAPDU). + + +## Request: + +| Bytes | Description | +| ------------- | ----------------------------------------------- | +| 1 byte | CLASS (constant 0xE0) | +| 1 byte | COMMAND to run, each command is described below | +| 1 byte | P1: RATE_TYPE of the transaction | +| 1 byte | P2: mask of TYPE and EXTENSION | +| N bytes | DATA, content depends of the COMMAND | + + +### COMMAND: + +| Name | Value | Description | +| ---------------------------- | ----- | ------------------------------------------------------------------------------------- | +| GET_VERSION | 0x02 | Get application version. This APDU can be sent independantly of the current app state | +| START_NEW_TRANSACTION | 0x03 | Start new EXCHANGE transaction. This APDU resets the app state | +| SET_PARTNER_KEY | 0x04 | Set the credentials of the exchange partner | +| CHECK_PARTNER | 0x05 | Check that the credentials of the exchange partner are signed by the Ledger key | +| PROCESS_TRANSACTION_RESPONSE | 0x06 | Receive the transaction proposal from the exchange partner | +| CHECK_TRANSACTION_SIGNATURE | 0x07 | Check that the transaction proposal is signed by the exchange partner | +| CHECK_ASSET_IN_LEGACY | 0x08 | Format the amounts and fees used. (FUND_LEGACY and SELL_LEGACY flows only) | +| CHECK_ASSET_IN | 0x0B | Format the amounts and fees used. (FUND_NEW and SELL_NEW flows only) | +| CHECK_PAYOUT_ADDRESS | 0x08 | Check that the payout address belongs to us (SWAP based flows only) | +| CHECK_REFUND_ADDRESS | 0x09 | Check that the refund address belongs to us (SWAP based flows only) | +| START_SIGNING_TRANSACTION | 0x0A | Start the library application responsible for the FROM signing | + +The COMMANDS must be sent to the application in the correct order, this order depends of the TYPE chosen for the exchange flow: +- START_NEW_TRANSACTION +- SET_PARTNER_KEY +- CHECK_PARTNER +- PROCESS_TRANSACTION_RESPONSE +- CHECK_TRANSACTION_SIGNATURE + - For SWAP based TYPES: + - CHECK_PAYOUT_ADDRESS + - CHECK_REFUND_ADDRESS + - For FUND_LEGACY and SELL_LEGACY TYPES: + - CHECK_ASSET_IN_LEGACY + - For FUND_NEW and SELL_NEW TYPES: + - CHECK_ASSET_IN +- START_SIGNING_TRANSACTION + +Notes: \ +Commands CHECK_REFUND_ADDRESS, CHECK_ASSET_IN_LEGACY, and CHECK_ASSET_IN prompt an UI review screen. \ +It is always possible to restart the flow by sending a START_NEW_TRANSACTION command, except when an UI review screen is displayed. \ +The command START_SIGNING_TRANSACTION will start the library application, the current application will not be EXCHANGE anymore. + +### RATE_TYPE: + +Different rates possible for the transaction. They are given to the app as P1 of an APDU. + +| Name | Value | Description | +| -------- | ----- | -------------------------------------------- | +| FIXED | 0x00 | The rate in the transaction is a fixed value | +| FLOATING | 0x01 | The rate in the transaction is an estimation | + + +### TYPE: + +Different exchange types are possible for the app. They are given to the app as the lower part of P2 of an APDU. \ +Once an exchange flow is started, the subcommand cannot be changed. + +| Name | Value | Description | +| ----------- | ----- | ----------------------------------------------------------------------------------------------- | +| SWAP_LEGACY | 0x00 | SWAP transaction (crypto against crypto) using legacy signature and encoding, deprecated soon | +| SELL_LEGACY | 0x01 | SELL transaction (crypto against fiat) using legacy signature and encoding, deprecated soon | +| FUND_LEGACY | 0x02 | FUND transaction (crypto to owned account) using legacy signature and encoding, deprecated soon | +| SWAP_NEW | 0x03 | SWAP transaction (crypto against crypto) using unified signature and encoding | +| SELL_NEW | 0x04 | SELL transaction (crypto against fiat) using unified signature and encoding | +| FUND_NEW | 0x05 | FUND transaction (crypto to owned account) using unified signature and encoding | + + +### EXTENSION: + +The maximum data in a single APDU is 255 bytes, in case it is not sufficient for a command, it is possible to send the commad in several parts. \ +It is given to the app as the upper part of P2 of an APDU. \ +It is only possible to use this field for a PROCESS_TRANSACTION_RESPONSE command in a SWAP_NEW, SELL_NEW, or FUND_NEW flow. + +| Name | Value | Description | +| --------- | --------- | ----------------------------------------------------------------- | +| P2_NONE | 0x00 << 4 | This APDU is self sufficient | +| P2_EXTEND | 0x01 << 4 | This APDU is not whole, it extends a previously received one | +| P2_MORE | 0x02 << 4 | This APDU is not whole, the followup part while be received later | + +### DATA: + +For all COMMANDS, the data bytes must be prefixed by a data length header. \ +For PROCESS_TRANSACTION_RESPONSE command of a SWAP_NEW, SELL_NEW, and FUND_NEW, the data length header is coded on 2 bytes. \ +For all other COMMANDS and all other TYPES, the data length header is coded on 1 byte. + +#### GET_VERSION + +No data expected. + +#### START_NEW_TRANSACTION + +No data expected. + +#### SET_PARTNER_KEY + +| Bytes | Description | +| ------- | ---------------------------------- | +| 1 byte | Length of the encoded partner name | +| N bytes | Partner name encoded with utf-8 | +| N bytes | Partner public key | + +#### CHECK_PARTNER + +| Bytes | Description | +| ------ | --------------------------------------------------------------------------------------- | +| N byte | Signature of the partner credentials by the Ledger key, curve secp256k1 hashfunc sha256 | + +#### PROCESS_TRANSACTION_RESPONSE + +| Bytes | Description | +| ------------ | ----------------------------------------------------------------------------------------------- | +| 1 or 2 bytes | Length of the encoded transaction proposal. 1 bytes on Legacy TYPES, 2 bytes on new TYPES | +| N bytes | Transaction proposal. No encoding for SWAP_LEGACY, URLsafe base 64 encoding for all other TYPES | +| 1 byte | Length of the transaction fees | +| N bytes | Transaction fees | + +Please refer to the src/protobuf files for the actual transaction proposal content. + +#### CHECK_TRANSACTION_SIGNATURE + +| Bytes | Description | +| ------ | ---------------------------------------------------------------------------------------------------------- | +| N byte | Signature of the proposed transaction by the partner. | + +For SWAP_LEGACY TYPE, the signature is computed on the sha256 hash of the transaction. \ +For all other TYPES the signature is computed on the sha256 hash of the DOT ('.') prefixed transaction. + +For SWAP_LEGACY and FUND_LEGACY TYPES, the signature is in DER format. \ +For all other TYPES the signature is in (R,S) format. + +For SWAP_LEGACY TYPE, the signature is computed on the secp256k1 curve. \ +For all other TYPES the signature is computed on the secp256r1 curve. + +#### CHECK_ASSET_IN_LEGACY + +This command is used only in the SELL_LEGACY and FUND_LEGACY TYPES. + +| Bytes | Description | +| ------- | ----------------------------------------------------------------------------------------------------------------------- | +| 1 byte | Coin configuration length of the FROM coin. The coin configuration is made of the ticker, appname, and subconfiguration | +| 1 byte | Ticker length | +| N bytes | Ticker name of this the coin configuration. The ticker has to be the same as the FROM ticker | +| 1 byte | Application length | +| N bytes | Name of the application that can handle this currency | +| 1 byte | Sub coin configuration length | +| N bytes | Sub coin configuration, used for tokens to specify an app the subticker and the decimals | +| N bytes | Signature of the coin configuration by the Ledger key, curve secp256k1 hashfunc sha256 | +| 1 byte | Packed derivation path length | +| N bytes | Packed derivation path used for the FROM coin | + +#### CHECK_ASSET_IN + +This command is used only in the SELL_NEW and FUND_NEW TYPES. \ +The data content is the same as CHECK_ASSET_IN_LEGACY, only the command id is different. + +#### CHECK_PAYOUT_ADDRESS + +This command is used only in the SWAP_LEGACY and SWAP_NEW TYPES. + +| Bytes | Description | +| ------- | --------------------------------------------------------------------------------------------------------------------- | +| 1 byte | Coin configuration length of the TO coin. The coin configuration is made of the ticker, appname, and subconfiguration | +| 1 byte | Ticker length | +| N bytes | Ticker name of this the coin configuration. The ticker has to be the same as the TO ticker | +| 1 byte | Application length | +| N bytes | Name of the application that can handle this currency | +| 1 byte | Sub coin configuration length | +| N bytes | Sub coin configuration, used for tokens to specify an app the subticker and the decimals | +| N bytes | Signature of the coin configuration by the Ledger key, curve secp256k1 hashfunc sha256 | +| 1 byte | Packed derivation path length | +| N bytes | Packed derivation path used for the TO coin | + +#### CHECK_REFUND_ADDRESS + +This command is used only in the SWAP_LEGACY and SWAP_NEW TYPES. + +| Bytes | Description | +| ------- | ----------------------------------------------------------------------------------------------------------------------- | +| 1 byte | Coin configuration length of the FROM coin. The coin configuration is made of the ticker, appname, and subconfiguration | +| 1 byte | Ticker length | +| N bytes | Ticker name of this the coin configuration. The ticker has to be the same as the FROM ticker | +| 1 byte | Application length | +| N bytes | Name of the application that can handle this currency | +| 1 byte | Sub coin configuration length | +| N bytes | Sub coin configuration, used for tokens to specify an app the subticker and the decimals | +| N bytes | Signature of the coin configuration by the Ledger key, curve secp256k1 hashfunc sha256 | +| 1 byte | Packed derivation path length | +| N bytes | Packed derivation path used for the FROM coin | + +#### START_SIGNING_TRANSACTION + +No data expected. + + +## Response: + +| Bytes | Description | +| ------------- | --------------------- | | N bytes | Command specific data | -| 2 bytes | Result | - -Result can be one of the following sequences: -| Bytes | Name | Description | -| ------ | ------------------------ | ------------------------------------------------ | -| 0x6A80 | INCORRECT_COMMAND_DATA | Command byte, or specific command data is incorrect | -| 0x6A81 | DESERIALIZATION_FAILED | Can't parse partner transaction | -| 0x6A82 | WRONG_TRANSACTION_ID | Transaction ID is not equal to one generated on the first step| -| 0x6A83 | INVALID_ADDRESS | Refund or payout address doesn't belong to us | -| 0x6A84 | USER_REFUSED | User refused transaction | -| 0x6A85 | INTERNAL_ERROR | Some error inside the device application | -| 0x6E00 | CLASS_NOT_SUPPORTED | | -| 0x6D00 | INVALID_INSTRUCTION | Command byte is not the one from the "Possible commands" table | -| 0x9D1A | SIGN_VERIFICATION_FAIL | Signature is incorrect | -| 0x9000 | SUCCESS | Success | - -## Start new transaction -This should be the first command -On this step device will generate 10 capital latin letters and return it to the the host application. - -No command data expected in this command request. - -In case of success command specific data in response contains 10 bytes - representation of transaction ID. - -## Set partner key -Partner public key and partner name signed by Ledger private key is send in this command. This command is only allowed after successful return from `START_NEW_TRANSACTION_COMMAND` +| 2 bytes | Return code | + +### Returned data + +Only the COMMANDS described below return data. All others only return a code. + +#### GET_VERSION + +In case of success, this command will return the application version in format {MAJOR.MINOR.PATCH}. + +#### START_NEW_TRANSACTION + +In case of success, this command will return a nonce called "device transaction id" used for the initiated flow. \ +For TYPE SWAP_LEGACY, the format of this nonce is a 10 char array. \ +For all other TYPES, the format of this nonce is a 32 bytes array. + +### Return code + +Return code can be one of the following values: + +| Bytes | Name | Description | +| ------ | ------------------------ | ---------------------------------------------------------------------------------------- | +| 0x6A80 | INCORRECT_COMMAND_DATA | Command byte, or specific command data is incorrect | +| 0x6A81 | DESERIALIZATION_FAILED | Can't parse partner transaction proposal | +| 0x6A82 | WRONG_TRANSACTION_ID | Transaction ID is not equal to one generated on the START_NEW_TRANSACTION step | +| 0x6A83 | INVALID_ADDRESS | Refund or payout address doesn't belong to us | +| 0x6A84 | USER_REFUSED | User refused the transaction proposal | +| 0x6A85 | INTERNAL_ERROR | Internal error of the application | +| 0x6A86 | WRONG_P1 | The P1 value is not a valid RATE | +| 0x6A87 | WRONG_P2_SUBCOMMAND | The P2 lower part value is not a valid SUBCOMMAND | +| 0x6A88 | WRONG_P2_EXTENSION | The P2 upper part value is not a valid EXTENSION | +| 0x6A89 | INVALID_P2_EXTENSION | The P2 upper part value is a valid EXTENSION value but is refused in the current context | +| 0x6E00 | CLASS_NOT_SUPPORTED | The CLASS is not 0xE0 | +| 0x6E01 | MALFORMED_APDU | The APDU header is malformed | +| 0x6E02 | INVALID_DATA_LENGTH | The length of the DATA is refused for this COMMAND | +| 0x6D00 | INVALID_INSTRUCTION | COMMAND is not in the "Possible commands" table | +| 0x6D01 | UNEXPECTED_INSTRUCTION | COMMAND is in the "Possible commands" table but is refused in the current context | +| 0x9D1A | SIGN_VERIFICATION_FAIL | The signature sent by this command does not match the data or the associated public key | +| 0x9000 | SUCCESS | Success code |