Handshake Ledger app
Some checks failed
Checks on the Python tests / Call Ledger Python linters (push) Has been cancelled
Build and run functional tests using ragger through reusable workflow / Build application using the reusable workflow (push) Has been cancelled
Run coding style check / Check linting using the reusable workflow (push) Has been cancelled
Ensure compliance with Ledger guidelines / Call Ledger guidelines_enforcer (push) Has been cancelled
Misspellings checks / Check misspellings (push) Has been cancelled
Build and run functional tests using ragger through reusable workflow / Run standalone ragger tests using the reusable workflow (push) Has been cancelled

Hardware-wallet app for Handshake (HNS). Derives Handshake addresses and signs
Handshake transactions, including name-auction covenants, on Ledger Stax, Flex,
Nano S+, Nano X and Apex+.

The design premise is that the host computer is untrusted: every APDU byte is
attacker-controlled, and the device's job is to be correct when the host lies.
Two failures outrank all others, and the code is shaped around them.

Signing something other than what the user approved. Any field the signature
commits to and the host can vary has to appear on the review screen, and
anything the screen cannot represent honestly is refused rather than shown under
a label that does not describe it. So the device signs SIGHASH_ALL only,
checked per input rather than once for the session; it displays a TRANSFER
covenant's destination, which decides who ends up owning the name and appears
nowhere else in the output; it shows a covenant's name hash when the plaintext
name cannot be verified against it; and it refuses covenant kinds it cannot
name, outputs whose values exceed their inputs, and declared input totals that
would overflow the fee arithmetic.

Misusing key material. Derivation paths are constrained to
m/44'/{5353..5356}'/account'[/change/index] in the app itself, not only by the
install manifest, because BOLOS terminates the app on an out-of-whitelist path
instead of returning an error. One coin type per signing session, since the
review renders every address under a single HRP.

Panics count too: set_panic!(exiting_panic) means a panic kills the app and
strands the session, so nothing unwraps on host-derived data and the session
ceilings are sized to the configured heap.

Consensus follows shd, the Swift Handshake node, which is the reference for the
sighash preimage, covenant item layouts and address encoding.

SIGN_TX is a PSBT-style state machine driven by P1 (BEGIN / ADD_INPUT /
ADD_OUTPUT / REVIEW / SIGN_INPUT): the host streams the transaction as
structured records, the device accumulates its own view of the values, shows one
review, then signs each input on demand.

Tests run under speculos in a container (./scripts/test), 66 of them, green on
all five devices. test_sign_tx_policy.py covers each refusal above and needs no
golden snapshots because every case is rejected before anything is drawn; the
snapshots that do exist are the record of what the user sees before approving.
tests/application_client/handshake_sighash.py is a deliberately independent
reimplementation of the sighash, used to verify real signatures.

Status: v0.1, pre-audit. Not for mainnet keys. Signing has not yet been
exercised on physical hardware.

Forked from LedgerHQ/app-boilerplate-rust (Apache-2.0).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
eskimo
2026-09-06 15:13:36 -04:00
commit 1b70b558c6
315 changed files with 6172 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
name: Build and run functional tests using ragger through reusable workflow
# This workflow will build the app and then run functional tests using the Ragger framework upon Speculos emulation.
# It calls a reusable workflow developed by Ledger's internal developer team to build the application and upload the
# resulting binaries.
# It then calls another reusable workflow to run the Ragger tests on the compiled application binary.
#
# The build part of this workflow is mandatory, this ensures that the app will be deployable in the Ledger App Store.
# While the test part of this workflow is optional, having functional testing on your application is mandatory and this workflow and
# tooling environment is meant to be easy to use and adapt after forking your application
permissions:
contents: write
actions: write
pull-requests: write
on:
workflow_dispatch:
inputs:
golden_run:
type: choice
required: true
default: 'Raise an error (default)'
description: CI behavior if the test snapshots are different than expected.
options:
- 'Raise an error (default)'
- 'Open a PR'
push:
branches:
- master
- main
- develop
pull_request:
jobs:
build_application:
name: Build application using the reusable workflow
uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_build.yml@v1
with:
upload_app_binaries_artifact: "app_handshake_binaries"
builder: ledger-app-builder
tests_standalone:
name: Run standalone ragger tests using the reusable workflow
needs: build_application
uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_ragger_tests.yml@v1
with:
download_app_binaries_artifact: "app_handshake_binaries"
regenerate_snapshots: ${{ github.event_name == 'workflow_dispatch' && inputs.golden_run == 'Open a PR' }}
test_dir: "tests/standalone"

View File

@@ -0,0 +1,24 @@
name: Run coding style check
# This workflow will run linting checks to ensure a level of code quality among all Ledger applications.
#
# The presence of this workflow is mandatory as a minimal level of linting is required.
permissions:
contents: read
on:
workflow_dispatch:
push:
branches:
- master
- main
- develop
pull_request:
jobs:
check_linting:
name: Check linting using the reusable workflow
uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_lint.yml@v1
with:
source: './src'

View File

@@ -0,0 +1,27 @@
name: Ensure compliance with Ledger guidelines
# This workflow is mandatory in all applications
# It calls a reusable workflow guidelines_enforcer developed by Ledger's internal developer team.
# The successful completion of the reusable workflow is a mandatory step for an app to be available on the Ledger
# application store.
#
# More information on the guidelines can be found in the repository:
# LedgerHQ/ledger-app-workflows/
permissions:
contents: read
actions: write
on:
workflow_dispatch:
push:
branches:
- master
- main
- develop
pull_request:
jobs:
guidelines_enforcer:
name: Call Ledger guidelines_enforcer
uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_guidelines_enforcer.yml@v1

View File

@@ -0,0 +1,22 @@
name: Misspellings checks
# This workflow performs some misspelling checks on the repository
# It is there to help us maintain a level of quality in our codebase and does not have to be kept on forked
# applications.
permissions:
contents: read
on:
workflow_dispatch:
push:
branches:
- master
- main
- develop
pull_request:
jobs:
misspell:
name: Check misspellings
uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_spell_check.yml@v1

View File

@@ -0,0 +1,28 @@
name: Checks on the Python tests
permissions:
contents: read
# This workflow performs some checks on the Python client used by the ragger tests
# It is there to help us maintain a level of quality in our codebase and does not have to be kept on forked
# applications.
on:
workflow_dispatch:
push:
branches:
- master
- main
- develop
pull_request:
jobs:
lint:
name: Call Ledger Python linters
uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_python_checks.yml@v1
with:
run_linter: pylint
run_type_check: true
src_directory: application_client
setup_directory: tests
req_directory: tests