Skip to content

Commit

Permalink
Merge pull request #1 from qtumproject/time/app_qtum_2.1.3
Browse files Browse the repository at this point in the history
Port app-qtum to upstream 2.1.3
  • Loading branch information
qtum-neil authored Sep 21, 2023
2 parents f83a4e7 + 42aa0f1 commit d92f011
Show file tree
Hide file tree
Showing 35 changed files with 1,006 additions and 92 deletions.
36 changes: 18 additions & 18 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ APP_STACK_SIZE = 3072

# Setting to allow building variant applications
VARIANT_PARAM = COIN
VARIANT_VALUES = bitcoin_testnet bitcoin
VARIANT_VALUES = qtum_testnet qtum

# simplify for tests
ifndef COIN
COIN=bitcoin_testnet
COIN=qtum_testnet
endif

########################################
Expand All @@ -55,35 +55,35 @@ HAVE_APPLICATION_FLAG_GLOBAL_PIN = 1
HAVE_APPLICATION_FLAG_BOLOS_SETTINGS = 1
HAVE_APPLICATION_FLAG_LIBRARY = 1

ifeq ($(COIN),bitcoin_testnet)
ifeq ($(COIN),qtum_testnet)

# Bitcoin testnet, no legacy support
# Qtum testnet, no legacy support
DEFINES += BIP32_PUBKEY_VERSION=0x043587CF
DEFINES += BIP44_COIN_TYPE=1
DEFINES += BIP44_COIN_TYPE_2=1
DEFINES += COIN_P2PKH_VERSION=111
DEFINES += COIN_P2SH_VERSION=196
DEFINES += COIN_NATIVE_SEGWIT_PREFIX=\"tb\"
DEFINES += COIN_P2PKH_VERSION=120
DEFINES += COIN_P2SH_VERSION=110
DEFINES += COIN_NATIVE_SEGWIT_PREFIX=\"tq\"
DEFINES += COIN_COINID_SHORT=\"TEST\"

APPNAME = "Bitcoin Test"
APPNAME = "Qtum Test"

else ifeq ($(COIN),bitcoin)
else ifeq ($(COIN),qtum)

# Bitcoin mainnet, no legacy support
# Qtum mainnet, no legacy support
DEFINES += BIP32_PUBKEY_VERSION=0x0488B21E
DEFINES += BIP44_COIN_TYPE=0
DEFINES += BIP44_COIN_TYPE_2=0
DEFINES += COIN_P2PKH_VERSION=0
DEFINES += COIN_P2SH_VERSION=5
DEFINES += COIN_NATIVE_SEGWIT_PREFIX=\"bc\"
DEFINES += COIN_COINID_SHORT=\"BTC\"
DEFINES += BIP44_COIN_TYPE=88
DEFINES += BIP44_COIN_TYPE_2=88
DEFINES += COIN_P2PKH_VERSION=58
DEFINES += COIN_P2SH_VERSION=50
DEFINES += COIN_NATIVE_SEGWIT_PREFIX=\"qc\"
DEFINES += COIN_COINID_SHORT=\"QTUM\"

APPNAME = "Bitcoin"
APPNAME = "Qtum"

else
ifeq ($(filter clean,$(MAKECMDGOALS)),)
$(error Unsupported COIN - use bitcoin_testnet, bitcoin)
$(error Unsupported COIN - use qtum_testnet, qtum)
endif
endif

Expand Down
42 changes: 39 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Ledger Bitcoin Application
# Ledger Qtum Application

## Prerequisite

Expand Down Expand Up @@ -26,7 +26,7 @@ make load # load the app on the Nano using ledgerblue
## Documentation

High level documentation on the architecture and interface of the app:
- [bitcoin.md](doc/bitcoin.md): specifications of application commands.
- [qtum.md](doc/qtum.md): specifications of application commands.
- [wallet.md](doc/wallet.md): supported wallet signing policies.
- [merkle.md](doc/merkle.md): rationale and specifications for the usage of Merkle trees.

Expand Down Expand Up @@ -55,6 +55,42 @@ The flow processed in [GitHub Actions](https://github.com/features/actions) is t

It outputs 4 artifacts:

- `bitcoin-app-debug` within output files of the compilation process in debug mode
- `qtum-app-debug` within output files of the compilation process in debug mode
- `code-coverage` within HTML details of code coverage
- `documentation` within HTML auto-generated documentation

## Develop on Ubuntu

This is a quick start script for developing app-qtum on Ubuntu.

# Install docker
sudo apt update
sudo apt install snapd
sudo snap refresh snapd
sudo snap install docker
sudo addgroup --system docker
sudo adduser $USER docker
newgrp docker
sudo snap disable docker
sudo snap enable docker

# Pull the latest dev tool
sudo docker pull ghcr.io/ledgerhq/ledger-app-builder/ledger-app-dev-tools:latest

# Clone app-qtum
sudo apt install git -y
git clone https://github.com/qtumproject/app-qtum

# Add rules for the supported devices
sudo app-qtum/script/add_udev_rules.sh

# Add ledger_env with command line to ~/.bashrc
app-qtum/script/ledger_ubuntu_env.sh
source ~/.bashrc

# Build the ledger app
cd app-qtum
ledger_env
make
make load
exit
2 changes: 1 addition & 1 deletion doc/merkle.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ and
### Serialization

A Merklelized Map commitment is serialized as a string of bytes containing, in sequence:
- the number of key-value pairs, encoded as a Bitcoin-style varint;
- the number of key-value pairs, encoded as a Qtum-style varint;
- the 32 bytes `keys_root`
- the 32 bytes `values_root`

Expand Down
31 changes: 16 additions & 15 deletions doc/bitcoin.md → doc/qtum.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Bitcoin application: Technical Specifications
# Qtum application: Technical Specifications

This page details the protocol implemented since version 2.1.0 of the app.

Expand All @@ -10,7 +10,7 @@ The protocol documentation for version from 2.0.0 and before 2.1.0 is [here](./v

The messaging format of the app is compatible with the [APDU protocol](https://developers.ledger.com/docs/nano-app/application-structure/#apdu-interpretation-loop). The `P1` field is reserved for future use and must be set to `0` in all messages. The `P2` field is used as a protocol version identifier; the current version is `1`, while version `0` is still supported. No other value must be used.

The main commands use `CLA = 0xE1`, unlike the legacy Bitcoin application that used `CLA = 0xE0`.
The main commands use `CLA = 0xE1`, unlike the legacy Qtum application that used `CLA = 0xE0`.

| CLA | INS | COMMAND NAME | DESCRIPTION |
|-----|-----|------------------------|-------------|
Expand All @@ -19,7 +19,8 @@ The main commands use `CLA = 0xE1`, unlike the legacy Bitcoin application that u
| E1 | 03 | GET_WALLET_ADDRESS | Return and show on screen an address for a registered or default wallet |
| E1 | 04 | SIGN_PSBT | Sign a PSBT with a registered or default wallet |
| E1 | 05 | GET_MASTER_FINGERPRINT | Return the fingerprint of the master public key |
| E1 | 10 | SIGN_MESSAGE | Sign a message with a key from a BIP32 path (Bitcoin Message Signing) |
| E1 | 10 | SIGN_MESSAGE | Sign a message with a key from a BIP32 path (Qtum Message Signing) |
| E1 | 81 | SIGN_SENDER_PSBT | Sign an op_sender output |

The `CLA = 0xF8` is used for framework-specific (rather than app-specific) APDUs; at this time, only one command is present.

Expand All @@ -37,7 +38,7 @@ The specs for the client commands are detailed below.

## Descriptors and wallet policies

The Bitcoin app uses a language similar to [output script descriptors](https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md) in order to represent the wallets that can be used to sign transactions.
The Qtum app uses a language similar to [output script descriptors](https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md) in order to represent the wallets that can be used to sign transactions.
Wallet policies need to be registered on the device, with an interactive process that requires user's approval.

See [here](wallet.md) for detailed information on the wallet policy language.
Expand Down Expand Up @@ -65,7 +66,7 @@ Once the user approves, the `REGISTER_WALLET` returns to the client a 32-byte HM
| 0xE000 | `SW_INTERRUPTED_EXECUTION` | The command is interrupted, and requires the client's response |
| 0x9000 | `SW_OK` | Success |

<!-- TODO: add an introduction section explaining the comand reference notations (e.g. the Bitcoin style varint) -->
<!-- TODO: add an introduction section explaining the comand reference notations (e.g. the Qtum style varint) -->

## Commands

Expand Down Expand Up @@ -230,7 +231,7 @@ No output data; the signature are returned using the YIELD client command.
Using the information in the PSBT and the wallet description, this command verifies what inputs are internal and what outputs match the pattern for a change address. After validating all the external outputs and the transaction fee with the user, it signs each of the internal inputs; each signature is sent to the client using the YIELD command, in the format described below. If multiple key placeholders of the wallet policy are internal, the process is repeated for each of them.

The results yielded via the YIELD command respect the following format: `<input_index> <pubkey_augm_len> <pubkey_augm> <signature>`, where:
- `input_index` is a Bitcoin style varint, the index input of the input being signed (starting from 0);
- `input_index` is a Qtum style varint, the index input of the input being signed (starting from 0);
- `pubkey_augm_len` is an unsigned byte equal to the length of `pubkey_augm`;
- `pubkey_augm` is the `pubkey` used for signing for legacy, segwit or taproot script path spends (a compressed pubkey if non-taproot, a 32-byte x-only pubkey if taproot); for taproot script path spends, it is the concatenation of the `x-only` pubkey and the 32-byte *tapleaf hash* as defined in [BIP-0341](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki);
- `signature` is the returned signature, possibly concatenated with the sighash byte (as it would be pushed on the stack).
Expand Down Expand Up @@ -282,7 +283,7 @@ User interaction is not required for this command.

### SIGN_MESSAGE

Signs a message, according to the standard Bitcoin Message Signing.
Signs a message, according to the standard Qtum Message Signing.

The device shows on its secure screen the BIP-32 path used for signing, and the SHA256 hash of the message; the hash should be verified by the user using an external tool if the client is untrusted.

Expand All @@ -303,7 +304,7 @@ The device shows on its secure screen the BIP-32 path used for signing, and the
| `4` | `bip32_path[1]` | Second derivation step (big endian) |
| | ... | |
| `4` | `bip32_path[n-1]` | `n`-th derivation step (big endian) |
| `<var>` | `msg_length` | The byte length of the message to sign (Bitcoin-style varint) |
| `<var>` | `msg_length` | The byte length of the message to sign (Qtum-style varint) |
| `32` | `msg_merkle_root` | The Merkle root of the message, split in 64-byte chunks |

The message to be signed is split into `ceil(msg_length/64)` chunks of 64 bytes (except the last chunk that could be smaller); `msg_merkle_root` is the root of the Merkle tree of the corresponding list of chunks.
Expand All @@ -314,16 +315,16 @@ The theoretical maximum valid length of the message is 2<sup>32</sup>-1 = 4&nbsp

| Length | Description |
|--------|-------------|
| `65` | The returned signature, encoded in the standard Bitcoin message signing format |
| `65` | The returned signature, encoded in the standard Qtum message signing format |

The signature is returned as a 65-byte binary string (1 byte equal to 32 or 33, followed by `r` and `s`, each of them represented as a 32-byte big-endian integer).

#### Description

The digest being signed is the double-SHA256 of the message, after prefixing the message with:

- the magic string `"\x18Bitcoin Signed Message:\n"` (equal to `18426974636f696e205369676e6564204d6573736167653a0a` in hexadecimal)
- the length of the message, encoded as a Bitcoin-style variable length integer.
- the magic string `"\x18Qtum Signed Message:\n"` (equal to `185174756D205369676e6564204d6573736167653a0a` in hexadecimal)
- the length of the message, encoded as a Qtum-style variable length integer.

#### Client commands

Expand Down Expand Up @@ -360,7 +361,7 @@ The request contains:
- `32` bytes: a sha-256 hash.

The response must contain:
- `<var>`: the length of the preimage, encoded as a Bitcoin-style varint;
- `<var>`: the length of the preimage, encoded as a Qtum-style varint;
- `1` byte: a 1-byte unsigned integer `b`, the length of the prefix of the pre-image that is part of the response;
- `b` bytes: corresponding to the first `b` bytes of the preimage.

Expand All @@ -374,8 +375,8 @@ The `GET_MERKLE_LEAF_PROOF` command requests the hash of a given leaf of a Merkl

The request contains:
- `32` bytes: the Merkle root hash;
- `<var>` bytes: the tree size `n`, encoded as a Bitcoin-style varint;
- `<var>` bytes: the leaf index `i`, encoded as a Bitcoin-style varint.
- `<var>` bytes: the tree size `n`, encoded as a Qtum-style varint;
- `<var>` bytes: the leaf index `i`, encoded as a Qtum-style varint.

The client must respond with:
- `32` bytes: the hash of the leaf with index `i` in the requested Merkle tree;
Expand All @@ -397,7 +398,7 @@ The request contains:

The response contains:
- `1` byte: `1` if the leaf is found, `0` if matching leaf exists;
- `<var>`: the index of the leaf, encoded as a Bitcoin-style varint.
- `<var>`: the index of the leaf, encoded as a Qtum-style varint.

### GET_MORE_ELEMENTS

Expand Down
4 changes: 2 additions & 2 deletions doc/wallet.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,9 @@ The wallet policy is serialized as the concatenation of:
- `1 byte`: a byte equal to `0x02`, the version of the wallet policy language
- `1 byte`: the length of the wallet name (0 for standard wallet)
- `<variable length>`: the wallet name (empty for standard wallets)
- `<variable length>`: the length of the wallet descriptor template, encoded as a Bitcoin-style variable-length integer
- `<variable length>`: the length of the wallet descriptor template, encoded as a Qtum-style variable-length integer
- `32 bytes`: the sha256 hash of the wallet descriptor template
- `<variable length>`: the number of keys in the list of keys, encoded as a Bitcoin-style variable-length integer
- `<variable length>`: the number of keys in the list of keys, encoded as a Qtum-style variable-length integer
- `<32 bytes>`: the root of the canonical Merkle tree of the list of keys

See [merkle](merkle.md) for information on Merkle trees.
Expand Down
Binary file modified glyphs/Bitcoin_64px.bmp
Binary file not shown.
Binary file modified glyphs/bitcoin_logo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified glyphs/nanos_badge_bitcoin.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified glyphs/nanos_badge_bitcoin_testnet.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified icons/bitcoin.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified icons/nanos_app_bitcoin.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified icons/nanox_app_bitcoin.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified icons/stax_app_bitcoin.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions script/add_udev_rules.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/bash
cat <<EOF > /etc/udev/rules.d/20-hw1.rules
# HW.1 / Nano
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2581", ATTRS{idProduct}=="1b7c|2b7c|3b7c|4b7c", TAG+="uaccess", TAG+="udev-acl"
# Blue
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2c97", ATTRS{idProduct}=="0000|0000|0001|0002|0003|0004|0005|0006|0007|0008|0009|000a|000b|000c|000d|000e|000f|0010|0011|0012|0013|0014|0015|0016|0017|0018|0019|001a|001b|001c|001d|001e|001f", TAG+="uaccess", TAG+="udev-acl"
# Nano S
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2c97", ATTRS{idProduct}=="0001|1000|1001|1002|1003|1004|1005|1006|1007|1008|1009|100a|100b|100c|100d|100e|100f|1010|1011|1012|1013|1014|1015|1016|1017|1018|1019|101a|101b|101c|101d|101e|101f", TAG+="uaccess", TAG+="udev-acl"
# Aramis
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2c97", ATTRS{idProduct}=="0002|2000|2001|2002|2003|2004|2005|2006|2007|2008|2009|200a|200b|200c|200d|200e|200f|2010|2011|2012|2013|2014|2015|2016|2017|2018|2019|201a|201b|201c|201d|201e|201f", TAG+="uaccess", TAG+="udev-acl"
# HW2
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2c97", ATTRS{idProduct}=="0003|3000|3001|3002|3003|3004|3005|3006|3007|3008|3009|300a|300b|300c|300d|300e|300f|3010|3011|3012|3013|3014|3015|3016|3017|3018|3019|301a|301b|301c|301d|301e|301f", TAG+="uaccess", TAG+="udev-acl"
# Nano X
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2c97", ATTRS{idProduct}=="0004|4000|4001|4002|4003|4004|4005|4006|4007|4008|4009|400a|400b|400c|400d|400e|400f|4010|4011|4012|4013|4014|4015|4016|4017|4018|4019|401a|401b|401c|401d|401e|401f", TAG+="uaccess", TAG+="udev-acl"
# Nano SP
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2c97", ATTRS{idProduct}=="0005|5000|5001|5002|5003|5004|5005|5006|5007|5008|5009|500a|500b|500c|500d|500e|500f|5010|5011|5012|5013|5014|5015|5016|5017|5018|5019|501a|501b|501c|501d|501e|501f", TAG+="uaccess", TAG+="udev-acl"
# Ledger Stax
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2c97", ATTRS{idProduct}=="6011", TAG+="uaccess", TAG+="udev-acl"
EOF

udevadm trigger
udevadm control --reload-rules
groupadd plugdev
usermod -aG plugdev -aG plugdev `whoami`
16 changes: 16 additions & 0 deletions script/ledger_ubuntu_env.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/sh

#alias ledger_env='sudo docker run --rm -ti --user "$(id -u):$(id -g)" --privileged -v "/dev/bus/usb:/dev/bus/usb" -v "$(realpath .):/app" ghcr.io/ledgerhq/ledger-app-builder/ledger-app-dev-tools:latest'
# For manual update of ~/.bashrc with ledger_env, just append the above line without the leading # character

# Add ledger_env to ~/.bashrc, alias for the command that is needed to connect to docker
DEVTOOLSET="alias ledger_env='sudo docker run --rm -ti --user \"\$(id -u):\$(id -g)\" --privileged -v \"/dev/bus/usb:/dev/bus/usb\" -v \"\$(realpath .):/app\" ghcr.io/ledgerhq/ledger-app-builder/ledger-app-dev-tools:latest'"
FILENAME="$HOME/.bashrc"
# Search file
if grep "$DEVTOOLSET" $FILENAME > /dev/null
then
echo "ledger_env present"
else
# Add ledger_env ~/.bashrc if not present into the file
echo $DEVTOOLSET >> $FILENAME
fi
1 change: 1 addition & 0 deletions src/commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ typedef enum {
SIGN_PSBT = 0x04,
GET_MASTER_FINGERPRINT = 0x05,
SIGN_MESSAGE = 0x10,
SIGN_SENDER_PSBT = 0x81,
} command_e;
Loading

0 comments on commit d92f011

Please sign in to comment.