Code documentation

ragger.address_book

Generic helper for the SDK Address Book feature: each sub-command serializes itself into a TLV payload and builds its own APDUs via get_chunks().

class ragger.address_book.address_book.AddressBookFieldTag(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: IntEnum

Address Book specific fields .

class ragger.address_book.address_book.BlockchainFamily(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: IntEnum

Blockchain family (tag BLOCKCHAIN_FAMILY).

ragger.backend

ragger.backend.interface

Interface contract

The contract a backend must respect:

Response management policy

To change the behavior of the backend on response APDU, one can tinker with the RaisePolicy:

class ragger.backend.interface.RaisePolicy(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)
RAISE_ALL = 3
RAISE_ALL_BUT_0x9000 = 2
RAISE_CUSTOM = 4
RAISE_NOTHING = 1

Concrete backends

Speculos backend (emulator)

Physical backends

ragger.error

class ragger.error.ExceptionRAPDU(status: int, data: bytes = b'')

Depending on the RaisePolicy, communication with an application can raise this exception.

Just like RAPDU, it is composed of two attributes:

  • status (int), which is extracted from the two last bytes of the response,

  • data (bytes), which is the entire response payload, except the two last bytes.

ragger.firmware

Most Ragger high-level class needs to know which Firmware they should expect. This is declared with this class:

class ragger.firmware.Firmware(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: IntEnum

NANOS = 1
NANOSP = 2
NANOX = 3
STAX = 4
FLEX = 5
APEX_P = 6
APEX_M = 7
property device: str

A proxy property for Firmware.name. This property is deprecated. It is advise to not use it.

property is_nano

States if the firmware’s name starts with ‘nano’ or not.

property name: str

Returns the name of the current firmware’s device

ragger.firmware.touch

ragger.firmware.touch.screen

ragger.firmware.touch.layouts

ragger.firmware.touch.use_cases

ragger.navigator

Interface and instructions

ragger.pki

Helper to sign payloads and onboard a PKI certificate on a device, acting as a Trust Services signing partner.

class ragger.pki.SigningPartner(pem_key_path: ~pathlib.Path, cert_pub_key_usage: ~ragger.pki.signing_partner.CertificatePubKeyUsage, certificates: dict[ledgered.devices.DeviceType, str], hash_func=<built-in function openssl_sha256>, sigencode=<function sigencode_der>)

A PKI signing partner that can sign payloads and onboard its certificate on a device.

Generic over: - PEM key file used for signing - Signing algorithm (hash function + signature encoding) - PKI certificate APDU data per device firmware

__init__(pem_key_path: ~pathlib.Path, cert_pub_key_usage: ~ragger.pki.signing_partner.CertificatePubKeyUsage, certificates: dict[ledgered.devices.DeviceType, str], hash_func=<built-in function openssl_sha256>, sigencode=<function sigencode_der>)
Args:

pem_key_path: Path to the PEM private key file. cert_pub_key_usage: PKI certificate public key usage (sent as P1 in cert APDU). certificates: Mapping of DeviceType -> hex-encoded certificate data string. hash_func: Hash function for PEM key loading and signing (default: SHA-256). sigencode: Signature encoding function (default: DER encoding).

get_certificate_payload(device_type: DeviceType) bytes

Return the raw PKI certificate APDU bytes for the given device type.

Raises:

KeyError: If the device type has no certificate configured.

sign(data: bytes) bytes

Sign data and return the encoded signature.

class ragger.pki.CertificatePubKeyUsage(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)
BACKUP_PROVIDER = 5
CALLDATA = 11
COIN_META = 8
EXCHANGE_PAYLOAD = 2
GATING = 15
GENUINE_CHECK = 1
LKRP_TOPIC = 16
NETWORK = 12
NFT_METADATA = 3
PERPS_DATA = 17
PLUGIN_METADATA = 7
RECOVER_ORCHESTRATOR = 6
SAFE_ACCOUNT = 14
SEED_ID_AUTH = 9
SWAP_TEMPLATE = 13
TOKEN_MULTIPLIER = 18
TRUSTED_NAME = 4
TX_SIMU_SIGNER = 10

ragger.tlv

Generic TLV serialization primitives and the Trust Services tag/enum registry.

ragger.tlv.serializable

class ragger.tlv.serializable.TlvSerializable

Base class for objects that serialize themselves into a TLV payload.

Subclasses implement serialize(), concatenating one serialize_field() (a.k.a. format_tlv()) per field. This is transport-agnostic: APDU framing (CLA/INS, chunking) is the caller’s responsibility.

ragger.tlv.serializable.der_encode(value: int) bytes

DER-encode an unsigned integer (used for both TLV tags and lengths).

Values below 0x80 are encoded as a single byte. Larger values are encoded as a length-prefix byte (0x80 | byte_count) followed by the big-endian bytes.

ragger.tlv.serializable.format_tlv(tag: int, value: Union[int, str, bytes, bytearray]) bytes

Serialize a single (tag, value) pair into a DER-style TLV triplet.

int values are encoded as minimal-length big-endian bytes and str values as their UTF-8 encoding before the length/value are emitted.

ragger.tlv.common_tags

class ragger.tlv.common_tags.LedgerCommonFieldTag(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Globally unique TLV tags (Ledger Trust Services spec).

ADDRESS = 34
CHAIN_ID = 35
CHALLENGE = 18
COIN_TYPE = 33
DEPTH = 54
DER_SIGNATURE = 21
DOMAIN_HASH = 40
HMAC_PROOF = 41
MAGNITUDE = 37
NOT_VALID_AFTER = 16
PUBLIC_KEY = 51
PUBLIC_KEY_CURVE = 50
PUBLIC_KEY_ID = 48
PUBLIC_KEY_SIGN_ALGO = 52
PUBLIC_KEY_USAGE = 49
SIGNER_ALGO = 20
SIGNER_KEY_ID = 19
STRUCTURE_TYPE = 1
TARGET_DEVICE = 53
TICKER = 36
TIME = 38
TRUSTED_NAME = 32
TX_HASH = 39
VALIDITY_INDEX = 17
VALID_UNTIL = 22
VERSION = 2

ragger.tlv.feature_tags

class ragger.tlv.feature_tags.AddressBookFieldTag(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Address Book specific fields .

ACCOUNT_IDENTIFIER = 242
CONTACT_NAME = 240
GROUP_HANDLE = 246
HMAC_REST = 247
PREVIOUS_CONTACT_NAME = 243
PREVIOUS_IDENTIFIER = 244
PREVIOUS_SCOPE = 245
SCOPE = 241
class ragger.tlv.feature_tags.AleoFieldTag(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Aleo application specific fields.

FEE_FUNCTION_NAME = 178
FEE_PROGRAM_ID = 179
FUNCTION_NAME = 182
GAMMAS = 194
GAMMAS_COUNT = 193
INPUT_COUNT = 183
INPUT_TYPES = 185
INPUT_VALUES = 184
MAX_BASE_FEE = 176
MAX_PRIORITY_FEE = 177
NESTED_CALL_COUNT = 186
NETWORK_ID = 195
PROGRAM_CHECKSUM = 196
PROGRAM_ID = 181
RECORD_COMMITMENT = 189
RECORD_COMMITMENTS_COUNT = 188
REQUEST = 180
R_HINT = 197
TPK = 192
TVK = 191
class ragger.tlv.feature_tags.CoinInfoFieldTag(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Coin info / dynamic network specific fields.

BLOCKCHAIN_FAMILY = 81
COIN_CONFIG = 80
NETWORK_ICON_HASH = 83
NETWORK_NAME = 82
class ragger.tlv.feature_tags.EvmFunctionFieldTag(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

EVM function info / plugin descriptor specific fields.

DELEGATION_TYPE = 66
EVM_FUNCTION_SELECTOR = 64
IMPLEMENTATION_ADDRESSES = 65
class ragger.tlv.feature_tags.LesMultisigFieldTag(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

LES Multisig specific fields.

ROLE = 162
SIGNERS_COUNT = 161
THRESHOLD = 160
class ragger.tlv.feature_tags.PerpsActionFieldTag(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Perps action wrapper.

ACTION_STRUCTURE = 219
ACTION_TYPE = 208
NONCE = 218
class ragger.tlv.feature_tags.PerpsApprovalBuilderFeeFieldTag(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Perps ApprovalBuilderFee action structure.

BUILDER_ADDRESS = 211
MAX_BASE_FEE = 176
class ragger.tlv.feature_tags.PerpsCancelOrderFieldTag(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Perps cancel_order action structure.

ASSET_ID = 209
CANCEL_ORDER = 217
ORDER_ID = 220
class ragger.tlv.feature_tags.PerpsContextFieldTag(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Perps context descriptor.

ACTION_TYPE = 208
ASSET_ID = 209
BUILDER_ADDRESS = 211
LEVERAGE = 213
MARGIN = 212
NETWORK_TYPE = 210
class ragger.tlv.feature_tags.PerpsCreateOrderFieldTag(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Perps create_order action structure.

BUILDER = 235
BUILDER_ADDRESS = 211
BUILDER_FEE = 236
GROUPING = 234
ORDER = 221
class ragger.tlv.feature_tags.PerpsLeverageFieldTag(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Perps leverage action structure.

ASSET_ID = 209
IS_CROSS = 222
LEVERAGE = 237
class ragger.tlv.feature_tags.PerpsOrderFieldTag(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Perps Order structure, incl. its ORDER_DETAIL tags.

NB: here ASSET_ID is 0xe1 (vs 0xd1 in the other sub-structures).

ASSET_ID = 225
IS_BUY = 226
ORDER_DETAIL = 215
ORDER_TYPE = 224
PRICE = 227
REDUCE_ONLY = 229
SIZE = 228
TIF = 230
TRIGGER_MARKET = 231
TRIGGER_PRICE = 232
TRIGGER_TYPE = 233
class ragger.tlv.feature_tags.PerpsUpdateIsolatedMarginFieldTag(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Perps UpdateIsolatedMargin action structure.

ASSET_ID = 225
IS_BUY = 226
NTLI = 214
class ragger.tlv.feature_tags.PerpsUpdateOrderFieldTag(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Perps update_order action structure.

ORDER = 221
ORDER_ID = 220
UPDATE_ORDER = 216
class ragger.tlv.feature_tags.SeedIdLkrpFieldTag(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

SeedID / LKRP specific fields.

ADDRESS_SIGNATURE = 97
DERIVATION_PATH = 105
DISPLAY = 104
DISPLAYED_STEP_COUNT = 108
MEMBER = 106
MEMBER_COUNT = 109
PROTOCOL_VERSION = 96
STEP_COUNT = 103
STEP_TYPE = 102
TOPIC_CONTROL_DISPLAY = 100
TOPIC_DICTIONARY = 99
TOPIC_HASH = 107
TOPIC_NEW_AUTHORITY = 101
TOPIC_PARENT = 98
class ragger.tlv.feature_tags.SwapTemplateFieldTag(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Solana swap template specific fields.

AMOUNT_OFFSET = 148
AMOUNT_RULES = 149
AMOUNT_SIZE = 147
ASSET_ACCOUNT_INDEX = 150
ASSET_ATA_INDEX = 151
DISCRIMINATOR = 146
PROGRAM_ID = 145
RECIPIENT_ACCOUNT_INDEX = 152
RECIPIENT_ATA_INDEX = 153
TEMPLATE_ID = 144
class ragger.tlv.feature_tags.TrustedNameFieldTag(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Trusted domain name specific fields.

TRUSTED_NAME_NFT_ID = 114
TRUSTED_NAME_OWNER = 116
TRUSTED_NAME_OWNER_DERIVATION_PATH = 117
TRUSTED_NAME_SOURCE = 113
TRUSTED_NAME_SOURCE_CONTRACT = 115
TRUSTED_NAME_TYPE = 112
class ragger.tlv.feature_tags.TxSimulationFieldTag(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

TX Simulation specific fields.

NORMALIZED_CATEGORY = 129
NORMALIZED_RISK = 128
PROVIDER_MESSAGE = 130
SIMULATION_TYPE = 132
TINY_URL = 131

ragger.tlv.enums

class ragger.tlv.enums.BlockchainFamily(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Blockchain family (tag BLOCKCHAIN_FAMILY).

BITCOIN = 0
CARDANO = 5
COSMOS = 4
ETHEREUM = 1
POLKADOT = 3
SOLANA = 2
TRON = 6
class ragger.tlv.enums.LedgerStructType(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Structure type discriminator for Ledger Trust Services (tag STRUCTURE_TYPE).

TYPE_ALEO_INTENT = 40
TYPE_ALEO_PREPARED_REQUEST = 41
TYPE_ALEO_REQUEST_SIGNATURE = 42
TYPE_CERTIFICATE = 1
TYPE_COIN_INFO = 6
TYPE_DOMAIN_TRUSTED_NAME = 3
TYPE_DYNAMIC_NETWORK = 8
TYPE_EDIT_CONTACT_NAME = 46
TYPE_EDIT_IDENTIFIER = 49
TYPE_EDIT_LEDGER_ACCOUNT = 48
TYPE_EDIT_SCOPE = 50
TYPE_ERC20_INFO = 4
TYPE_EVM_FUNCTION_INFO = 5
TYPE_GATED_SIGNING = 13
TYPE_LESM_ACCOUNT_INFO = 39
TYPE_LKRP_STEP = 14
TYPE_LKRP_TOPIC = 12
TYPE_NFT_COLLECTION_NAME = 2
TYPE_PERPS_ACTION = 44
TYPE_PERPS_METADATA = 43
TYPE_PROVIDE_CONTACT = 51
TYPE_PROVIDE_LEDGER_ACCOUNT_CONTACT = 52
TYPE_PROXY = 38
TYPE_REGISTER_IDENTITY = 45
TYPE_REGISTER_LEDGER_ACCOUNT = 47
TYPE_SEED_ID_AUTHENTICATION_CHALLENGE = 7
TYPE_SOLANA_SWAP_TEMPLATE = 10
TYPE_TX_SIMULATION = 9
TYPE_VERIFIABLE_ADDRESS = 11
class ragger.tlv.enums.LesMultisigRole(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

LES Multisig address role (tag ROLE).

PROPOSER = 1
SIGNER = 0
class ragger.tlv.enums.LkrpStepType(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

LKRP intent step type (tag STEP_TYPE).

ADD_MEMBER = 1
AUTHENTICATE = 5
DISPLAY = 4
HEADER = 0
REMOVE_MEMBER = 2
SET_TOPIC = 3
class ragger.tlv.enums.ProxyDelegatorType(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Proxy/delegator type (tag DELEGATION_TYPE).

DELEGATOR = 2
ISSUED_FROM_FACTORY = 1
PROXY = 0
class ragger.tlv.enums.SimulationType(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

TX simulation type (tag SIMULATION_TYPE).

MESSAGE = 2
TRANSACTION = 0
TYPED_MESSAGE = 1
class ragger.tlv.enums.TrustedNameSource(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Trusted name namespace (tag TRUSTED_NAME_SOURCE).

CRYPTO_ASSET_LIST = 1
DNS = 5
DYNAMIC_RESOLVER = 6
ENS = 2
FREENAME = 4
LESM_ADDRESS_BOOK = 7
LOCAL_ADDRESS_BOOK = 0
UNSTOPPABLE_DOMAIN = 3
class ragger.tlv.enums.TrustedNameType(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Trusted name account type (tag TRUSTED_NAME_TYPE).

CCD_CONTEXT_ADDRESS = 7
COLLECTION = 3
CONTEXT_ADDRESS = 6
EOA = 1
SMART_CONTRACT = 2
TOKEN = 4
WALLET = 5

ragger.utils

ragger.utils.structs

class ragger.utils.structs.RAPDU(status: int, data: bytes)

The dataclass containing the application’s response of an APDU from the client to the application.

It is composed of two attributes:

  • status (int): from the two last bytes of the payload. Common values are 0x9000 for success, other being errors.

  • data (bytes): the rest of the response (the entire payload without the two last bytes)

ragger.utils.misc

ragger.utils.coverage

ragger.utils.coverage.enable(device_name: str, elf: Path, trace_dir: Path) None

Turn on QEMU in_asm tracing for the upcoming Speculos launches.

Sets the QEMU_LOG* environment variables (inherited by the QEMU process Speculos spawns) and registers the (elf, trace_dir) couple for this device so the traces can be converted at the end of the session. %d in the filename is expanded by QEMU to the process pid: the backend is usually class-scoped, so several QEMU instances run and each must write its own file.

ragger.utils.coverage.finalize(project_root: Path, output: Path, readelf: str = 'readelf', exclude: Optional[List[str]] = None) List[Tuple[str, int, int, int, Path, Optional[Path]]]

Convert every registered device’s traces into an lcov file.

For a single device, writes output. For several devices, writes one file per device next to output (<stem>-<device><suffix>). An HTML report is rendered next to each .info (<stem>_html/) whenever genhtml is available; otherwise only the lcov file is produced. exclude removes matching repo-relative source paths (e.g. vendored submodules). Returns the per-device results (rendering of the human-readable summary is left to the caller).

ragger.utils.coverage.to_html(info: Path, html_dir: Path, project_root: Path) Optional[Path]

Render an lcov .info into an HTML report with genhtml.

Run from project_root so the repo-relative SF: paths resolve to their sources. Returns the report’s index.html on success, or None (with a warning) if genhtml is unavailable or failed.

ragger.utils.coverage.to_lcov(elf: Path, trace_files: List[Path], output: Path, project_root: Path, readelf: str = 'readelf', load_base: int = 1073741824, exclude: Optional[List[str]] = None) Tuple[int, int, int]

Convert in_asm traces into an lcov tracefile.

exclude is an optional list of patterns (see _excluded()) removing matching repo-relative source paths, e.g. vendored submodules.

Returns (files, covered_lines, instrumented_lines). Raises ValueError if the ELF has no DWARF line info, or if no app code was executed.