-
Notifications
You must be signed in to change notification settings - Fork 74
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add initial set of performance tests
- Loading branch information
Showing
6 changed files
with
162 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# Benchmarks | ||
|
||
The tests in this folder are meant to measure the performance of various app operations. | ||
|
||
These tests are implemented in Python and can be executed either using the [Speculos](https://github.com/LedgerHQ/speculos) emulator or a Ledger Nano S+, Nano X, or Stax. | ||
|
||
Python dependencies are listed in [requirements.txt](requirements.txt), install them using [pip](https://pypi.org/project/pip/) | ||
|
||
``` | ||
pip install -r requirements.txt | ||
``` | ||
|
||
## Build | ||
|
||
The app must be built with the `AUTOAPPROVE_FOR_PERF_TESTS=1` parameter when calling `make`. This flag compiles the testnet app in a mode that requires no user interaction at all. | ||
|
||
## Launch with Speculos | ||
|
||
Performance measured in speculos is not a good proxy of the performance on a real device. | ||
|
||
Simply run: | ||
|
||
``` | ||
pytest | ||
``` | ||
|
||
## Launch with your device | ||
|
||
Compile and install the app on your device as normal. | ||
|
||
To run the tests on your Ledger device, you also need to install an optional dependency | ||
|
||
``` | ||
pip install ledgercomm[hid] | ||
``` | ||
|
||
Be sure to have you device connected through USB and open on the bitcoin testnet app, sideloaded from the build above. | ||
|
||
``` | ||
pytest --hid | ||
``` |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
|
||
from pathlib import Path | ||
from test_utils.fixtures import * | ||
import random | ||
import sys | ||
import os | ||
|
||
absolute_path = os.path.dirname(os.path.abspath(__file__)) | ||
relative_bitcoin_path = ('../bitcoin_client') | ||
absolute_bitcoin_client_path = os.path.join( | ||
os.path.dirname(os.path.abspath(__file__)), '../') | ||
sys.path.append(os.path.join(absolute_path, relative_bitcoin_path)) | ||
|
||
from ledger_bitcoin import Chain # noqa: E402 | ||
|
||
TESTS_ROOT_DIR = Path(__file__).parent | ||
|
||
random.seed(0) # make sure tests are repeatable |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
bip32>=3.4,<4.0 | ||
embit>=0.8.0,<0.9.0 | ||
ledgercomm>=1.2.1,<2.0.0 | ||
pytest>=8.2.2,<9.0.0 | ||
pytest-benchmark>=4.0.0,<5.0.0 | ||
typing-extensions>=3.7,<4.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
[tool:pytest] | ||
addopts = --strict-markers | ||
|
||
[pylint] | ||
disable = C0114, # missing-module-docstring | ||
C0115, # missing-class-docstring | ||
C0116, # missing-function-docstring | ||
C0103, # invalid-name | ||
R0801, # duplicate-code | ||
R0913 # too-many-arguments | ||
extension-pkg-whitelist=hid | ||
|
||
[pycodestyle] | ||
max-line-length = 120 | ||
|
||
[mypy-hid.*] | ||
ignore_missing_imports = True | ||
|
||
[mypy-pytest.*] | ||
ignore_missing_imports = True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
|
||
from pathlib import Path | ||
|
||
import pytest | ||
|
||
from ledger_bitcoin import WalletPolicy, Client | ||
from ledger_bitcoin.psbt import PSBT | ||
|
||
from test_utils import txmaker | ||
|
||
tests_root: Path = Path(__file__).parent | ||
|
||
|
||
def make_psbt(wallet_policy: WalletPolicy, n_inputs: int, n_outputs: int) -> PSBT: | ||
in_amounts = [10000 + 10000 * i for i in range(n_inputs)] | ||
total_in = sum(in_amounts) | ||
out_amounts = [total_in // n_outputs - i for i in range(n_outputs)] | ||
|
||
change_index = 1 | ||
|
||
psbt = txmaker.createPsbt( | ||
wallet_policy, | ||
in_amounts, | ||
out_amounts, | ||
[i == change_index for i in range(n_outputs)] | ||
) | ||
|
||
sum_in = sum(in_amounts) | ||
sum_out = sum(out_amounts) | ||
|
||
assert sum_out < sum_in | ||
|
||
return psbt | ||
|
||
|
||
@pytest.mark.parametrize("n_inputs", [1, 3, 10]) | ||
def test_perf_sign_psbt_singlesig_pkh(client: Client, n_inputs: int, benchmark): | ||
# PSBT for a legacy 2-output spend (1 change address) | ||
|
||
wallet = WalletPolicy( | ||
"", | ||
"pkh(@0/**)", | ||
[ | ||
"[f5acc2fd/44'/1'/0']tpubDCwYjpDhUdPGP5rS3wgNg13mTrrjBuG8V9VpWbyptX6TRPbNoZVXsoVUSkCjmQ8jJycjuDKBb9eataSymXakTTaGifxR6kmVsfFehH1ZgJT" | ||
], | ||
) | ||
|
||
psbt = make_psbt(wallet, n_inputs, 2) | ||
|
||
def sign_tx(): | ||
result = client.sign_psbt(psbt, wallet, None) | ||
|
||
assert len(result) == n_inputs | ||
|
||
benchmark.pedantic(sign_tx, rounds=1) | ||
|
||
|
||
@pytest.mark.parametrize("n_inputs", [1, 3, 10]) | ||
def test_perf_sign_psbt_singlesig_wpkh(client: Client, n_inputs: int, benchmark): | ||
# PSBT for a segwit 2-output spend (1 change address) | ||
|
||
wallet = WalletPolicy( | ||
"", | ||
"wpkh(@0/**)", | ||
[ | ||
"[f5acc2fd/84'/1'/0']tpubDCtKfsNyRhULjZ9XMS4VKKtVcPdVDi8MKUbcSD9MJDyjRu1A2ND5MiipozyyspBT9bg8upEp7a8EAgFxNxXn1d7QkdbL52Ty5jiSLcxPt1P" | ||
], | ||
) | ||
|
||
psbt = make_psbt(wallet, n_inputs, 2) | ||
|
||
def sign_tx(): | ||
result = client.sign_psbt(psbt, wallet, None) | ||
|
||
assert len(result) == n_inputs | ||
|
||
benchmark.pedantic(sign_tx, rounds=1) |