././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1770638540.7551503 trezor-0.20.2/AUTHORS0000644000000000000000000000164415142346315011127 0ustar00python-trezor is free software, created in 2012 and maintained by SatoshiLabs as part of the Trezor project. Over the years, many people have contributed to the project. Here is an incomplete list of credits: alepop Jan 'matejcik' MatÄ›jek Jan Pochyla Jiří Musil Jochen Hoenicke Jonathan Cross Karel Bílek Marek Palatinus Martin Milata mruddy Pavol Rusnak Peter van Mourik Petr SedláÄ�ek Roman Zeyde Saleem Rashid Tomáš Sušánka ZuluCrypto ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1785490180.6809711 trezor-0.20.2/CHANGELOG.md0000644000000000000000000014016615233065405011672 0ustar00# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [0.20.2] (29th July 2026) [0.20.2]: https://github.com/trezor/trezor-firmware/compare/python/v0.20.1...python/v0.20.2 ### Added - Support for [Solana off-chain message signing v0](https://docs.anza.xyz/proposals/off-chain-message-signing). [#6759] - Add ML-DSA-44 device authenticity check. [#6826] - Add testing module to trezorlib. [#6994] - Tron: Claim voting rewards (WithdrawBalanceContract). [#7101] - Stellar: Support signing Soroban authorization entries (`stellar.sign_soroban_authorization`, `stellar.from_authorization_entry` and `trezorctl stellar sign-soroban-authorization`). [#7365] ### Changed - `TrezorClient.ensure_unlocked()` will not allocate a session and will not cause seed derivation. `Session.ensure_unlocked()` now just forwards to `TrezorClient`. [#7168] - Generated Merkle trees are now balanced. [#7359] ### Fixed - Solana: allow chunkified addresses. [#6545] - Tron: allow chunkified addresses. [#6730] - Skip stale protocol v1 responses on probing. [#6859] - Fix non-functional `trezorctl get-session` with THP. [#7168] - Fix broken HID transport. [#7428] ### Incompatible changes - Solana: add support for off-chain message signing (OCMS) v1 and remove v0. [#7053] - Stellar: Enable signing Soroban smart contract transactions; `sign_tx` / `from_envelope` now accepts / returns a transaction extension. [#7259] ## [0.20.1] (11th May 2026) [0.20.1]: https://github.com/trezor/trezor-firmware/compare/python/v0.20.0...python/v0.20.1 ### Added - Support THP ACK piggybacking. [#6202] - Support WebAuthn credentials' pagination. [#6349] ### Changed - Default to advanced recovery for mnemonics shorter than 24 words on legacy. [#6525] ### Deprecated - `trezorlib.ui` is deprecated, the module has been moved to `trezorlib.cli.ui`. [#6564] - `trezorlib.tools.EnumAdapter` and `TupleAdaper` have been moved to `trezorlib.construct_helpers`. [#6564] ### Fixed - Handle missing THP continuations during multi-chunk payloads. [#6555] - Fix THP pairing after credential invalidation. [#6575] - Fetch root fingerprint from older firmware. [#6580] - Skip unrelated device response when probing transport. [#6588] - Fix THP auto-connection after unlocking the device. [#6633] ## [0.20.0] (10th February 2026) [0.20.0]: https://github.com/trezor/trezor-firmware/compare/python/v0.20.0-dev0...python/v0.20.0 Version 0.20.0 introduces a set of **major breaking API changes**. All user code must be upgraded. As announced, the API has changed significantly since the pre-release version 0.20.0-dev. ### Incompatible changes - Refactor trezorlib session-based API. [#6273] ### Added - Use keyring package for storing THP keys and credentials. [#6273] ### Removed - Deprecate uploading language blob during firmware update. [#6103] - debuglink: Remove vestigial memory_write/read/erase methods. [#6273] - Deprecated `@expect` decorator was removed. [#6273] - Deprecated `str` return values in functions whose result is a success have been removed. [#6273] ### Fixed - Avoid dropping WebUSB chunks in case of a timeout. [#6112] - Support resuming THP sessions. [#6273] - trezorctl: BLE behavior on macOS was improved. [#6449] - trezorctl: fix crash when device authentication allowlist is unavailable. [#6449] ## [0.20.0-dev0] (21st October 2025) [0.20.0-dev0]: https://github.com/trezor/trezor-firmware/compare/python/v0.13.10...python/v0.20.0-dev0 Version 0.20.0 introduces a set of **major breaking API changes**. All user code must be upgraded. This version is a pre-release. The new API is unstable and may change until 0.20.0 is released. ### Incompatible changes - All Trezor functions now run on top of a `Session` instead of `TrezorClient`. - Reworked API of `TrezorClient`. ### Added - Support for T3W1. - Support for Trezor-Host Protocol. [#4976] - Cardano: Add support for signing arbitrary messages. [#3509] - Added support for Bluetooth Low Energy transport. [#4948] - Added new translation blob format to support larger fonts. [#4975] - Generation of SLIP-21 node for a new way of storing labels (using Evolu). [#5220] - Add support for displaying the message hash when signing Ethereum EIP-712 typed data. [#5344] - Check Tropic fields to AuthenticityProof. [#5760] - Allow exporting device serial number. [#5928] - `debuglink`: Add new optional enum DebugTouchEventType to DebugLinkDecision message. [#5328] - `debuglink`: Add screen buttons and button actions. [#4740] - `debuglink`: Add 'navigate_to_menu_item' button action. [#5499] ### Changed - Changed trezorlib to session-based. Changes also affect trezorctl, python tools, and tests. [#4976] - Changed build system to uv. - Loadable definitions from data.trezor.io query the new path structure. ### Deprecated - `trezorlib.__version__` is deprecated, use `importlib.metadata.version("trezor")`. ### Removed - Remove BNB Beacon Chain support. [#4227] - Dropped support for Python 3.8. - `ethereum.network_from_address_n` was removed. ### Fixed - Fixed device restart handling during firmware update. [#5000] - Fix broken interactive test mode. [#5455] ## [0.13.10] (12th February 2025) [0.13.10]: https://github.com/trezor/trezor-firmware/compare/python/v0.13.9...python/v0.13.10 ### Added - Added support for T3B1. [#3728] - Added support for Trezor models not known by the current version of the library. [#3993] - Added ability to set Optiga's security event counter to maximum: `trezorctl debug optiga-set-sec-max`. [#4000] - Enum for valid device rotations. [#4041] - Added pretty-printing of protobuf messages in IPython (`_repr_pretty_`). [#4076] - Added support for benchmarks. [#4101] - Added support for entropy check workflow in `device.reset()`. [#4155] - Added shortcut for loading a debug device with the "academic" SLIP39 seed. [#4282] - Added support for lexicographic sorting of pubkeys in multisig. [#4351] - Added an `expect` argument to `TrezorClient.call()`, to enforce the returned message type. [#4464] - Introduced `device.setup()` as a cleaner upgrade to `device.reset()`. [#4464] ### Changed - Most USB level errors are now converted to `TransportException`. [#4089] ### Deprecated - `@expect` decorator is deprecated -- use `TrezorClient.call(expect=...)` instead. [#4464] - String return values are deprecated in functions where the semantic result is a success (specifically those that were returning the message from Trezor's `Success` response). Type annotations are updated to `str | None`, and in a future release those functions will be returning `None` on success, or raise an exception on a failure. [#4464] - `device.reset()` is deprecated, migrate to `device.setup()`. [#4464] - Return value of `device.recover()` is deprecated. In the future, this function will return `None`. [#4464] ### Removed - CoSi functionality. [#3442] - Removed display_random feature. [#4119] ### Fixed - It is now possible to interrupt USB communication (via Ctrl+C, or a signal, or any other way). [#4089] - Use `frozenset` for `models.TREZORS` to prevent accidental modification. ### Incompatible changes - Return values in `solana` module were changed from the wrapping protobuf messages to the raw inner values (`str` for address, `bytes` for pubkey / signature). [#4464] - `trezorctl device` commands whose default result is a success will not print anything to stdout anymore, in line with Unix philosophy. [#4464] ## [0.13.9] (19th June 2024) [0.13.9]: https://github.com/trezor/trezor-firmware/compare/python/v0.13.8...python/v0.13.9 ### Added - trezorctl: Automatically go to bootloader when upgrading firmware. [#2919] - Support interaction-less upgrade. [#2919] - Added user adjustable brightness setting. [#3208] - Added Solana support. [#3359] - trezorctl: support for human-friendly Trezor Safe device authenticity check (requires separate installation of `cryptography` library). [#3364] - Added support for T3T1. [#3422] - Stellar: add support for StellarClaimClaimableBalanceOp. [#3434] - Cardano: Added support for tagged sets in CBOR (tag 258). [#3496] - Cardano: Added support for Conway certificates. [#3496] - Added ability to request Shamir backups with any number of groups/shares. [#3636] - Added flag for setting up device using SLIP39 "single". [#3868] - Added `--quality` argument to `trezorctl set homescreen`. [#3893] ### Changed - Renamed `trezorctl device self-test` command to `trezorctl device prodtest-t1`. [#3504] - Increased default JPEG quality for uploaded homescreen. [#3893] ### Incompatible changes - Renamed flag used for setting up device using BIP39 to `bip39`. [#3868] - Minimum required Python version is now 3.8. ## [0.13.8] (19th October 2023) [0.13.8]: https://github.com/trezor/trezor-firmware/compare/python/v0.13.7...python/v0.13.8 ### Added - Added full support for Trezor Safe 3 (T2B1). - Added support for STM32F429I-DISC1 board [#2989] - Add support for address chunkification in Receive and Sign flow. [#3237] - Implement device authenticate command. [#3255] - trezorctl: support unlocking bootloader via `trezorctl device unlock-bootloader`. ### Changed - Use 'h' character for hardened BIP-32 components in help texts. [#3037] - trezorctl: Use 'h' character in generated descriptors. [#3037] - ClickUI: notify user in terminal that they should enter PIN or passphrase on Trezor. [#3203] - Internal names are used consistently in constants and names. Original model-based names are kept as aliases for backwards compatibility. - Trezor model detection will try to use the `internal_name` field. ### Fixed - Drop simple-rlp dependency and use internal copy [#3045] - Fixed printing Trezor model when validating firmware image [#3227] - Corrected vendor header signing keys for Safe 3 (T2B1). ## [0.13.7] (2nd June 2023) [0.13.7]: https://github.com/trezor/trezor-firmware/compare/python/v0.13.6...python/v0.13.7 ### Added - Recognize signing keys for T2B1. - Add possibility to call tutorial flow [#2795] - Add ability to change homescreen for Model R [#2967] - Recognize hw model field in vendor headers. [#3048] ## [0.13.6] (24th April 2023) [0.13.6]: https://github.com/trezor/trezor-firmware/compare/python/v0.13.5...python/v0.13.6 ### Added - Signed Ethereum network and token definitions from host [#15] - Support SLIP-25 in get-descriptor. [#2541] - trezorctl: Support prompt configuration for `encrypt-keyvalue` / `decrypt-keyvalue`. [#2608] - Support for external reward addresses in Cardano CIP-36 registrations [#2692] - Auto-convert image to Trezor's homescreen format. [#2880] ### Changed - `trezorctl firmware verify` changed order of checks - fingerprint is validated before signatures. [#2745] ### Fixed - Removed attempt to initialize the device after wipe in bootloader mode [#2221] - Limit memory exhaustion in protobuf parser. [#2439] - `trezorctl ethereum sign-tx`: renamed `--gas-limit` shortcut to `-G` to avoid collision with `-t/--token` [#2535] - Fixed behavior of UDP transport search by path when full path is provided and prefix_search is True [#2786] - Fixed behavior of `trezorctl fw` with unsigned Trezor One firmwares. [#2801] - Improve typing information when `TrezorClient` has a more intelligent UI object. [#2832] - When enabling passphrase force-on-device, do not also prompt to enable passphrase if it is already enabled. [#2833] ## [0.13.5] (28th December 2022) [0.13.5]: https://github.com/trezor/trezor-firmware/compare/python/v0.13.4...python/v0.13.5 ### Added - Add support for model field in firmware image. [#2701] - Add support for v3-style Trezor One signatures. [#2701] ### Changed - More structured information about signing keys for different models. [#2701] ### Incompatible changes - Instead of accepting a list of public keys, `FirmwareType.verify()` accepts a parameter configuring whether to use production or development keys. [#2701] ## [0.13.4] (4th November 2022) [0.13.4]: https://github.com/trezor/trezor-firmware/compare/python/v0.13.3...python/v0.13.4 ### Added - Add UnlockPath message. [#2289] - Added new TOI formats - little endian full-color and even-high grayscale [#2414] - Add device set-busy command to trezorctl. [#2445] - Support SLIP-25 accounts in get-public-node and get-address. [#2517] - Add possibility to save emulator screenshots. [#2547] - Support for Cardano CIP-36 governance registration format [#2561] ### Removed - Remove DATA parameter from trezorctl cosi commit. - Remove firmware dumping capability. [#2433] ### Fixed - Fixed issue where type declarations were not visible to consumer packages. [#2542] ### Incompatible changes - Refactored firmware parsing and validation to a more object oriented approach. [#2576] ## [0.13.3] (13th July 2022) [0.13.3]: https://github.com/trezor/trezor-firmware/compare/python/v0.13.2...python/v0.13.3 ### Added - Support for Cardano Babbage era transaction items [#2354] ### Fixed - Fix Click 7.x compatibility. [#2364] ## [0.13.2] (30th June 2022) [0.13.2]: https://github.com/trezor/trezor-firmware/compare/python/v0.13.1...python/v0.13.2 ### Fixed - Fixed dependency error when running trezorctl without PIL. - Fixed dependency error when running trezorctl on Python 3.6 without rlp. - Fix `trezorctl --version` crash. [#1702] ## [0.13.1] (29th June 2022) [0.13.1]: https://github.com/trezor/trezor-firmware/compare/python/v0.13.0...python/v0.13.1 ### Added - New exception type `DeviceIsBusy` indicates that the device is in use by another process. [#1026] - Support payment requests and GetNonce command. [#1430] - Add press_info() to DebugLink. [#1430] - Add support for blind EIP-712 signing for Trezor One [#1970] - Add ScriptUI for trezorctl, spawned by --script option [#2023] - Support T1 screenshot saving in Debuglink [#2093] - Support generating Electrum-compatible message signatures in CLI. [#2100] - Support Cardano Alonzo-era transaction items and --include-network-id flag [#2114] - trezorctl: Bitcoin commands can detect script type from derivation path. [#2159] - Add support for model R [#2230] - Add firmware get-hash command. [#2239] - Jump and stay in bootloader from firmware through SVC call reverse trampoline. [#2284] ### Changed - Unify boolean arguments/options in trezorlib commands to on/off [#2123] - Rename `normalize_nfc` to `prepare_message_bytes` in tools.py [#2126] - `trezorctl monero` network type arguments now accept symbolic names instead of numbers. [#2219] ### Fixed - trezorctl will correctly report that device is in use. [#1026] - Allow passing empty `message_hash` for domain-only EIP-712 hashes for Trezor T1 (i.e. when `primaryType`=`EIP712Domain`) [#2036] - Fixed error when printing protobuf message with a missing required field. [#2135] - Add compatibility with Click 8.1 [#2199] ## [0.13.0] - 9th December 2021 [0.13.0]: https://github.com/trezor/trezor-firmware/compare/python/v0.12.4...python/v0.13.0 ### Added - `trezorctl firmware update` shows progress bar (Model T only) - Enabled session management via `EndSession` [#1227] - Added parameters to enable Cardano derivation when calling `init_device()`. [#1231] - two new trezorctl commands - `trezorctl firmware download` and `trezorctl firmware verify` [#1258] - Support no_script_type option in SignMessage. [#1586] - Support for Ethereum EIP1559 transactions [#1604] - Debuglink can automatically scroll through paginated views. [#1671] - Support for Taproot descriptors [#1710] - `trezorlib.stellar.from_envelope` was added, it includes support for the Stellar [TransactionV1](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0015.md#xdr) format transaction. [#1745] - Ethereum: support 64-bit chain IDs [#1771] - Support for Cardano multi-sig transactions, token minting, script addresses, multi-sig keys, minting keys and native script verification [#1772] - Added parameters to specify kind of Cardano derivation to all functions and `trezorctl` commands. [#1783] - Support for EIP-712 in library and `trezorctl ethereum sign-typed-data` [#1835] - Add script_pubkey field to TxInput message. [#1857] - Full type hinting checkable with pyright [#1893] ### Changed - protobuf is aware of `required` fields and default values [#379] - `trezorctl firmware-update` command changed to `trezorctl firmware update` [#1258] - `btc.sign_tx()` accepts keyword arguments for transaction metadata [#1266] - Raise `ValueError` when the txid for an input is not present in `prev_txes` during `btc.sign_tx` [#1442] - `trezorlib.mappings` was refactored for easier customization [#1449] - Refactor protobuf codec for better clarity [#1541] - `UdpTransport.wait_until_ready` no longer sets socket to nonblocking [#1668] - Cardano transaction parameters are now streamed into the device one by one instead of being sent as one large object [#1683] - `trezorlib.stellar` will refuse to process transactions containing MuxedAccount [#1838] - Use unified descriptors format. [#1885] - Introduce Trezor models as an abstraction over USB IDs, vendor strings, and possibly protobuf mappings. [#1967] ### Deprecated - instantiating protobuf objects with positional arguments is deprecated [#379] - `details` argument to `btc.sign_tx()` is deprecated. Use keyword arguments instead. [#379] - values of required fields must be supplied at instantiation time. Omitting them is deprecated. [#379] ### Removed - dropped Python 3.5 support [#810] - dropped debug-only `trezorctl debug show-text` functionality [#1531] - Removed support for Lisk [#1765] ### Fixed - fix operator precedence issue for ethereum sign-tx command [#1867] - Updated `tools/build_tx.py` to work with Blockbook's API protections. [#1896] - Fix PIN and passphrase entry in certain terminals on Windows [#1959] ### Incompatible changes - `client.init_device(derive_cardano=True)` must be used before calling Cardano functions. [#1231] - The type of argument to `ui.button_request(x)` is changed from int to ButtonRequest. The original int value can be accessed as `x.code` [#1671] - Due to transaction streaming in Cardano, it isn't possible to return the whole serialized transaction anymore. Instead the transaction hash, transaction witnesses and auxiliary data supplement are returned and the serialized transaction needs to be assembled by the client. [#1683] - `trezorlib.stellar` was reworked to use stellar-sdk instead of providing local implementations [#1745] - Cardano derivation now defaults to Icarus method. This will result in different keys for users with 24-word seed. [#1783] ## [0.12.4] - 7th September 2021 [0.12.4]: https://github.com/trezor/trezor-firmware/compare/python/v0.12.3...python/v0.12.4 ### Fixed - trezorctl: fixed "Invalid value for " when using Click 8 and param is not specified [#1798] ## [0.12.3] - 29th July 2021 [0.12.3]: https://github.com/trezor/trezor-firmware/compare/python/v0.12.2...python/v0.12.3 ### Added - `trezorctl btc get-descriptor` support [#1363] - `trezorctl btc reboot-to-bootloader` support [#1738] - distinguishing between temporary and permanent safety checks - trezorctl accepts PIN entered by letters (useful on laptops) - support for 50-digit PIN for T1 ### Changed - allowed Click 8.x as a requirement - replaced all references to Trezor Wallet with Trezor Suite, and modified all mentions of Beta Wallet ### Fixed - added missing requirement `attrs` - properly parse big numbers in `tools/build_tx.py` [#1257], [#1296] - it is now possible to set safety checks for T1 ## [0.12.2] - 27th August 2020 [0.12.2]: https://github.com/trezor/trezor-firmware/compare/python/v0.12.1...python/v0.12.2 ### Added - `trezorlib.toif` module (moved from internal) can encode and decode TOIF image format - `trezorctl set homescreen` was improved and extended to support PNG images for Trezor T ### Changed - trezorctl will correctly notify the user if the image decoding library is missing ### Fixed - fix exception in `trezorctl btc get-address` [#1179] - fix exception in `trezorctl lisk sign-message` - fix exception in trezorctl commands that accept filenames [#1196] - fix "Invalid homescreen" error when un-setting homescreen ### Removed - removed option `--skip-vendor-header` from `trezorctl firmware-update` which did nothing [#1210] ## [0.12.1] - 5th August 2020 [0.12.1]: https://github.com/trezor/trezor-firmware/compare/python/v0.12.0...python/v0.12.1 ### Added - `trezorctl set safety-checks` controls the new "safety checks" feature. [#1126] - `trezorctl btc get-address` can create multisig addresses. - the following commands are now equivalent in trezorctl: `firmware-update`, `firmware-upgrade`, `update-firmware`, `upgrade-firmware` - support for EXTERNAL input type [#38], [#1052] - support for ownership proofs - support for pre-authorized CoinJoin transactions [#37] - support for Cardano Shelley [#948] ### Changed - do not allow setting auto-lock delay unless PIN is configured ### Fixed - correctly calculate hashes for very small firmwares [f#1082] - unified file arguments in trezorctl - `TrezorClient.ping()` does not crash when device is PIN-locked ## [0.12.0] - 1st April 2020 [0.12.0]: https://github.com/trezor/trezor-firmware/compare/python/v0.11.6...python/v0.12.0 ### Incompatible changes - `trezorlib.coins`, `trezorlib.tx_api`, and the file `coins.json`, were removed - `TrezorClient` argument `ui` is now mandatory. `state` argument was renamed to `session_id`. - UI callback `get_passphrase()` has a new argument `available_on_device`. - API for `cosi` module was changed - other changes may also introduce incompatibilities, please review the full list below ### Added - support for firmwares 1.9.0 and 2.3.0 - Model T now defaults to entering passphrase on device. New trezorctl option `-P` enforces entering passphrase on host. - support for "passphrase always on device" mode on model T - new trezorctl command `get-session` and option `-s` allows entering passphrase once for multiple subsequent trezorctl operations - built-in functionality of UdpTransport to wait until an emulator comes up, and the related command `trezorctl wait-for-emulator` - `trezorctl debug send-bytes` can send raw messages to the device [f#116] - when updating firmware, user is warned that the requested version does not match their device [f#823] - `trezorctl list` can now show name, model and id of device ### Changed - `trezorlib.tx_api.json_to_tx` was reduced to only support Bitcoin fields, and moved to `trezorlib.btc.from_json`. - API for `cosi` module was streamlined: `verify_m_of_n` is now `verify`, the old `verify` is `verify_combined` - internals of firmware parsing were reworked to support signing firmware headers - `get_default_client` respects `TREZOR_PATH` environment variable - UI callback `get_passphrase` has an additional argument `available_on_device`, indicating that the connected Trezor is capable of on-device entry - `Transport.write` and `read` method signatures changed to accept bytes instead of protobuf messages - trezorctl subcommands have a common `@with_client` decorator that manages exception handling and connecting to device ### Fixed - trezorctl does not print empty line when there is no output - trezorctl cleanly reports wire exceptions [f#226] ### Removed - `trezorlib.tx_api` was removed - `trezorlib.coins` and coin data was removed - `trezorlib.ckd_public`, which was deprecated in 0.10, was now removed. - `btc.sign_tx` will not preload transaction data from `prev_txes`, as usage with TxApi is being removed - PIN protection and passphrase protection for `ping()` command was removed - compatibility no-op code from trezorlib 0.9 was removed from `trezorlib.client` - `trezorlib.tools.CallException` was dropped, use `trezorlib.exceptions.TrezorFailure` instead ## [0.11.6] - 30th December 2019 [0.11.6]: https://github.com/trezor/trezor-firmware/compare/python/v0.11.5...python/v0.11.6 ### Added - support for get-and-increase FIDO counter operation - support for setting wipe code - `trezorctl device recover` supports `--u2f-counter` option to set the FIDO counter to a custom value ### Changed - `trezorctl` command was reworked for ease of use and maintenance. See `trezorctl --help` and `OPTIONS.rst` for details. [f#510] - updated EOS transaction parser to match `cleos` in `delegatebw` and `undelegatebw` actions [f#680] [f#681] - `RecoveryDevice` does not set fields when doing dry-run recovery [f#666] ### Fixed - fixed "expand words" functionality in `trezorctl device recover` [f#778] ### Removed - trezorctl no longer interactively signs Bitcoin-like transactions, the only allowed input format is JSON. See [`docs/transaction-format.md`](docs/transaction-format.md) for details. - support for "load device by xprv" was removed from firmware and trezorlib ## [0.11.5] - 26th September 2019 [0.11.5]: https://github.com/trezor/trezor-firmware/compare/python/v0.11.4...python/v0.11.5 ### Added - trezorctl can dump raw protobuf bytes in debug output [f#117] - trezorctl shows a warning when activating Shamir Backup if the device does not support it [f#445] - warnings are emitted when encountering unknown value for a protobuf enum [f#363] - debug messages show enum value names instead of raw numbers - support for packed repeated encoding in the protobuf decoder - in `trezorctl firmware-update`, the new `--beta` switch enables downloading beta firmwares. By default, only stable firmware is used. [f#411], [f#420] - in `trezorctl firmware-update`, the new `--bitcoin-only` switch enables downloading Bitcoin-only firmware - support for FIDO2 resident credential management - support for SD-protect features ### Changed - package directory structure was changed: `src` subdirectory contains sources and `tests` subdirectory contains tests, so that cwd is not cluttered - `trezorctl` script was moved into a module `trezorlib.cli.trezorctl` and is launched through the `entry_points` mechanism. This makes it usable on Windows - `pyblake2` is no longer required on Python 3.6 and up - input flows can only be used in with-block (only relevant for unit tests) - if not specified, trezorctl will set label to "SLIP-0014" in SLIP-0014 mode - in `clear_session` the client also forgets the passphrase state for TT [f#525] ### Fixed - trezorctl will properly check if a firmware is present on a new T1 [f#224] ### Removed - device test suite was moved out of trezor package ## [0.11.4] - 31st July 2019 [0.11.4]: https://github.com/trezor/trezor-firmware/compare/python/v0.11.3...python/v0.11.4 ### Added - trezorctl support for SLIP-39 Shamir Backup - support for Binance Chain ## [0.11.3] - 29th May 2019 [0.11.3]: https://github.com/trezor/trezor-firmware/compare/python/v0.11.2...python/v0.11.3 ### Added - trezorctl can now send ERC20 tokens - trezorctl usb-reset will perform USB reset on devices in inconsistent state - set-display-rotation command added for TT firmware 2.1.1 - EOS support [f#87] - Tezos: add voting support [f#41] - `dict_to_proto` now allows enum values as strings ### Changed - Minimum firmware versions bumped to 1.8.0 and 2.1.0 - Cleaner errors when UI object is not supplied - Generated files are now part of the source tarball again. That means that `protoc` is no longer required. ### Fixed - Ethereum commands in trezorctl now work - Memory debugging tools now work again ### Removed - Tron and Ontology support removed until implementations exist in Trezor firmware ## [0.11.2] - 27th February 2019 [0.11.2]: https://github.com/trezor/python-trezor/compare/v0.11.1...v0.11.2 ### Added - full support for bootloader 1.8.0 and relevant firmware upgrade functionality - trezorctl: support fully offline signing JSON-encoded transaction data - trezorctl: dry-run for firmware upgrade command - client: new convenience function `get_default_client` for simple script usage - Dash: support DIP-2 special inputs [#351] - Ethereum: add get_public_key methods ### Changed - coins with BIP-143 fork id (BCH, BTG) won't require prev_tx [#352] - device recovery will restore U2F counter - Cardano: change `network` to `protocol_magic` - tests can run interactively when `INTERACT=1` environment variable is set - protobuf: improved `to_dict` function ### Deprecated - trezorctl: interactive signing with `sign-tx` is considered deprecated ## [0.11.1] - 28th December 2018 [0.11.1]: https://github.com/trezor/python-trezor/compare/v0.11.0...v0.11.1 ### Fixed - crash when entering passphrase on device with Trezor T - Qt widgets should only import QtCore [#349] ## [0.11.0] - 6th December 2018 [0.11.0]: https://github.com/trezor/python-trezor/compare/v0.10.2...v0.11.0 ### Incompatible changes - removed support for Python 3.3 and 3.4 - major refactor of `TrezorClient` and UI handling. Implementers must now provide a "UI" object instead of overriding callbacks [#307], [#314] - protobuf classes now use a `get_fields()` method instead of `FIELDS` field [#312] - all methods on `TrezorClient` class are now in separate modules and take a `TrezorClient` instance as argument [#276] - mixin classes are also removed, you are not supposed to extend `TrezorClient` anymore - `TrezorClientDebugLink` was moved to `debuglink` module - changed signature of `trezorlib.btc.sign_tx` - `@field` decorator was replaced by an argument to `@expect` ### Added - trezorlib now has a hardcoded check preventing use of outdated firmware versions [#283] - Ripple support [#286] - Zencash support [#287] - Cardano support [#300] - Ontology support [#301] - Tezos support [#302] - Capricoin support [#325] - limited Monero support (can only get address/watch key, monerowallet is required for signing) - support for input flow in tests makes it easier to control complex UI workflows [#314] - `protobuf.dict_to_proto` can create a protobuf instance from a plain dict - support for smarter methods in trezord 2.0.25 and up - support for seedless setup - trezorctl: firmware handling is greatly improved [#304], [#308] - trezorctl: Bitcoin-like signing flow is more user-friendly - `tx_api` now supports Blockbook backend servers ### Changed - better reporting for debuglink expected messages - replaced Ed25519 module with a cleaner, optimized version - further reorganization of transports makes them more robust when dependencies are missing - codebase now follows [Black](https://github.com/ambv/black) code style - in Qt modules, Qt5 is imported first [#315] - `TxApiInsight` is just `TxApi` - `device.reset` and `device.recover` now have reasonable defaults for all arguments - protobuf classes are no longer part of the source distribution and must be compiled locally [#284] - Stellar: addresses are always strings ### Removed - `set_tx_api` method on `TrezorClient` is replaced by an argument for `sign_tx` - caching functionality of `TxApi` was moved to a separate test-support class - Stellar: public key methods removed - `EncryptMessage` and `DecryptMessage` actions are gone ### Fixed: - `TrezorClient` can now detect when a HID device is removed and a different one is plugged in on the same path - trezorctl now works with Click 7.0 and considers "`_`" and "`-`" as same in command names [#314] - bash completion fixed - Stellar: several bugs in the XDR parser were fixed ## [0.10.2] - 21st June 2018 [0.10.2]: https://github.com/trezor/python-trezor/compare/v0.10.1...v0.10.2 ### Added - `stellar_get_address` and `_public_key` functions support `show_display` parameter - trezorctl: `stellar_get_address` and `_public_key` commands for the respective functionality ### Removed - trezorctl: `list_coins` is removed because we no longer parse the relevant protobuf field (and newer Trezor firmwares don't send it) [#277] ### Fixed - test support module was not included in the release, so code relying on the deprecated `ckd_public` module would fail [#280] ## [0.10.1] - 11th June 2018 [0.10.1]: https://github.com/trezor/python-trezor/compare/v0.10.0...v0.10.1 ### Fixed - previous release fails to build on Windows [#274] ## [0.10.0] - 8th June 2018 [0.10.0]: https://github.com/trezor/python-trezor/compare/v0.9.1...v0.10.0 ### Added - Lisk support [#197] - Stellar support [#167], [#268] - Wanchain support [#230] - support for "auto lock delay" feature - `TrezorClient` takes an additional argument `state` that allows reusing the previously entered passphrase [#241] - USB transports mention udev rules in exception messages [#245] - `log.enable_debug_output` function turns on wire logging, instead of having to use `TrezorClientVerbose` - BIP32 paths now support `123h` in addition to `123'` to indicate hardening - trezorctl: `-p` now supports prefix search for device path [#226] - trezorctl: smarter handling of firmware updates [#242], [#269] ### Changed - reorganized transports and moved into their own `transport` submodule - protobuf messages and coins info is now regenerated at build time from the `trezor-common` repository [#248] - renamed `ed25519raw` to `_ed25519` to indicate its privateness - renamed `ed25519cosi` to `cosi` and expanded its API - protobuf messages are now logged through Python's `logging` facility instead of custom printing through `VerboseWireMixin` - `client.format_protobuf` is moved to `protobuf.format_message` - `tools.Hash` is renamed to `tools.btc_hash` - `coins` module `coins_txapi` is renamed to `tx_api`. `coins_slip44` is renamed to `slip44`. - build: stricter flake8 checks - build: split requirements to separate files - tests: unified finding test device, while respecting `TREZOR_PATH` env variable. - tests: auto-skip appropriately marked tests based on Trezor device version - tests: only show wire output when run with `-v` - tests: allow running `xfail`ed tests selectively based on `pytest.ini` - docs: updated README with clearer install instructions [#185] - docs: switched changelog to Keep a Changelog format [#94] ### Deprecated - `ckd_public` is only maintained in `tests.support` submodule and considered private - `TrezorClient.expand_path` is moved to plain function `tools.parse_path` - `TrezorDevice` is deprecated in favor of `transport.enumerate_devices` and `transport.get_transport` - XPUB-related handling in `tools` is slated for removal ### Removed - most Python 2 compatibility constructs are gone [#229] - `TrezorClientVerbose` and `VerboseWireMixin` is removed - specific `tx_api.TxApi*` classes removed in favor of `coins.tx_api` - `client.PRIME_DERIVATION_FLAG` is removed in favor of `tools.HARDENED_FLAG` and `tools.H_()` - hard dependency on Ethereum libraries and HIDAPI is changed into extras that need to be specified explicitly. Require `trezor[hidapi]` or `trezor[ethereum]` to get them. ### Fixed - WebUSB enumeration returning bad devices on Windows 10 [#223] - `sign_tx` operation sending empty address string [#237] - Wrongly formatted Ethereum signatures [#236] - protobuf layer would wrongly encode signed integers [#249], [#250] - protobuf pretty-printing broken on Python 3.4 [#256] - trezorctl: Matrix recovery on Windows wouldn't allow backspace [#207] - aes_encfs_getpass.py: fixed Python 3 bug [#169] ## [0.9.1] - 5th March 2018 [0.9.1]: https://github.com/trezor/python-trezor/compare/v0.9.0...v0.9.1 ### Added - proper support for Trezor model T - support for Monacoin - improvements to `trezorctl`: - add pretty-printing of features and protobuf debug dumps (fixes [#199]) - support `TREZOR_PATH` environment variable to preselect a Trezor device. ### Removed - gradually dropping Python 2 compatibility (pypi package will now be marked as Python 3 only) [f#41]: https://github.com/trezor/trezor-firmware/pull/41 [f#87]: https://github.com/trezor/trezor-firmware/pull/87 [f#116]: https://github.com/trezor/trezor-firmware/pull/116 [f#117]: https://github.com/trezor/trezor-firmware/pull/117 [f#224]: https://github.com/trezor/trezor-firmware/pull/224 [f#226]: https://github.com/trezor/trezor-firmware/pull/226 [f#363]: https://github.com/trezor/trezor-firmware/pull/363 [f#411]: https://github.com/trezor/trezor-firmware/pull/411 [f#420]: https://github.com/trezor/trezor-firmware/pull/420 [f#445]: https://github.com/trezor/trezor-firmware/pull/445 [f#510]: https://github.com/trezor/trezor-firmware/pull/510 [f#525]: https://github.com/trezor/trezor-firmware/pull/525 [f#666]: https://github.com/trezor/trezor-firmware/pull/666 [f#680]: https://github.com/trezor/trezor-firmware/pull/680 [f#681]: https://github.com/trezor/trezor-firmware/pull/681 [f#778]: https://github.com/trezor/trezor-firmware/pull/778 [f#823]: https://github.com/trezor/trezor-firmware/pull/823 [f#1082]: https://github.com/trezor/trezor-firmware/pull/1082 [#15]: https://github.com/trezor/trezor-firmware/pull/15 [#37]: https://github.com/trezor/trezor-firmware/pull/37 [#38]: https://github.com/trezor/trezor-firmware/pull/38 [#94]: https://github.com/trezor/python-trezor/pull/94 [#167]: https://github.com/trezor/python-trezor/pull/167 [#169]: https://github.com/trezor/python-trezor/pull/169 [#185]: https://github.com/trezor/python-trezor/pull/185 [#197]: https://github.com/trezor/python-trezor/pull/197 [#199]: https://github.com/trezor/python-trezor/pull/199 [#207]: https://github.com/trezor/python-trezor/pull/207 [#223]: https://github.com/trezor/python-trezor/pull/223 [#226]: https://github.com/trezor/python-trezor/pull/226 [#229]: https://github.com/trezor/python-trezor/pull/229 [#230]: https://github.com/trezor/python-trezor/pull/230 [#236]: https://github.com/trezor/python-trezor/pull/236 [#237]: https://github.com/trezor/python-trezor/pull/237 [#241]: https://github.com/trezor/python-trezor/pull/241 [#242]: https://github.com/trezor/python-trezor/pull/242 [#245]: https://github.com/trezor/python-trezor/pull/245 [#248]: https://github.com/trezor/python-trezor/pull/248 [#249]: https://github.com/trezor/python-trezor/pull/249 [#250]: https://github.com/trezor/python-trezor/pull/250 [#256]: https://github.com/trezor/python-trezor/pull/256 [#268]: https://github.com/trezor/python-trezor/pull/268 [#269]: https://github.com/trezor/python-trezor/pull/269 [#274]: https://github.com/trezor/python-trezor/pull/274 [#276]: https://github.com/trezor/python-trezor/pull/276 [#277]: https://github.com/trezor/python-trezor/pull/277 [#280]: https://github.com/trezor/python-trezor/pull/280 [#283]: https://github.com/trezor/python-trezor/pull/283 [#284]: https://github.com/trezor/python-trezor/pull/284 [#286]: https://github.com/trezor/python-trezor/pull/286 [#287]: https://github.com/trezor/python-trezor/pull/287 [#300]: https://github.com/trezor/python-trezor/pull/300 [#301]: https://github.com/trezor/python-trezor/pull/301 [#302]: https://github.com/trezor/python-trezor/pull/302 [#304]: https://github.com/trezor/python-trezor/pull/304 [#307]: https://github.com/trezor/python-trezor/pull/307 [#308]: https://github.com/trezor/python-trezor/pull/308 [#312]: https://github.com/trezor/python-trezor/pull/312 [#314]: https://github.com/trezor/python-trezor/pull/314 [#315]: https://github.com/trezor/python-trezor/pull/315 [#325]: https://github.com/trezor/python-trezor/pull/325 [#349]: https://github.com/trezor/python-trezor/pull/349 [#351]: https://github.com/trezor/python-trezor/pull/351 [#352]: https://github.com/trezor/python-trezor/pull/352 [#379]: https://github.com/trezor/trezor-firmware/pull/379 [#810]: https://github.com/trezor/trezor-firmware/pull/810 [#948]: https://github.com/trezor/trezor-firmware/pull/948 [#1026]: https://github.com/trezor/trezor-firmware/pull/1026 [#1052]: https://github.com/trezor/trezor-firmware/pull/1052 [#1126]: https://github.com/trezor/trezor-firmware/pull/1126 [#1179]: https://github.com/trezor/trezor-firmware/pull/1179 [#1196]: https://github.com/trezor/trezor-firmware/pull/1196 [#1210]: https://github.com/trezor/trezor-firmware/pull/1210 [#1227]: https://github.com/trezor/trezor-firmware/pull/1227 [#1231]: https://github.com/trezor/trezor-firmware/pull/1231 [#1257]: https://github.com/trezor/trezor-firmware/pull/1257 [#1258]: https://github.com/trezor/trezor-firmware/pull/1258 [#1266]: https://github.com/trezor/trezor-firmware/pull/1266 [#1296]: https://github.com/trezor/trezor-firmware/pull/1296 [#1363]: https://github.com/trezor/trezor-firmware/pull/1363 [#1430]: https://github.com/trezor/trezor-firmware/pull/1430 [#1442]: https://github.com/trezor/trezor-firmware/pull/1442 [#1449]: https://github.com/trezor/trezor-firmware/pull/1449 [#1531]: https://github.com/trezor/trezor-firmware/pull/1531 [#1541]: https://github.com/trezor/trezor-firmware/pull/1541 [#1586]: https://github.com/trezor/trezor-firmware/pull/1586 [#1604]: https://github.com/trezor/trezor-firmware/pull/1604 [#1668]: https://github.com/trezor/trezor-firmware/pull/1668 [#1671]: https://github.com/trezor/trezor-firmware/pull/1671 [#1683]: https://github.com/trezor/trezor-firmware/pull/1683 [#1702]: https://github.com/trezor/trezor-firmware/pull/1702 [#1710]: https://github.com/trezor/trezor-firmware/pull/1710 [#1738]: https://github.com/trezor/trezor-firmware/pull/1738 [#1745]: https://github.com/trezor/trezor-firmware/pull/1745 [#1765]: https://github.com/trezor/trezor-firmware/pull/1765 [#1771]: https://github.com/trezor/trezor-firmware/pull/1771 [#1772]: https://github.com/trezor/trezor-firmware/pull/1772 [#1783]: https://github.com/trezor/trezor-firmware/pull/1783 [#1798]: https://github.com/trezor/trezor-firmware/pull/1798 [#1835]: https://github.com/trezor/trezor-firmware/pull/1835 [#1838]: https://github.com/trezor/trezor-firmware/pull/1838 [#1857]: https://github.com/trezor/trezor-firmware/pull/1857 [#1867]: https://github.com/trezor/trezor-firmware/pull/1867 [#1885]: https://github.com/trezor/trezor-firmware/pull/1885 [#1893]: https://github.com/trezor/trezor-firmware/pull/1893 [#1896]: https://github.com/trezor/trezor-firmware/pull/1896 [#1959]: https://github.com/trezor/trezor-firmware/pull/1959 [#1967]: https://github.com/trezor/trezor-firmware/pull/1967 [#1970]: https://github.com/trezor/trezor-firmware/pull/1970 [#2023]: https://github.com/trezor/trezor-firmware/pull/2023 [#2036]: https://github.com/trezor/trezor-firmware/pull/2036 [#2093]: https://github.com/trezor/trezor-firmware/pull/2093 [#2100]: https://github.com/trezor/trezor-firmware/pull/2100 [#2114]: https://github.com/trezor/trezor-firmware/pull/2114 [#2123]: https://github.com/trezor/trezor-firmware/pull/2123 [#2126]: https://github.com/trezor/trezor-firmware/pull/2126 [#2135]: https://github.com/trezor/trezor-firmware/pull/2135 [#2159]: https://github.com/trezor/trezor-firmware/pull/2159 [#2199]: https://github.com/trezor/trezor-firmware/pull/2199 [#2219]: https://github.com/trezor/trezor-firmware/pull/2219 [#2221]: https://github.com/trezor/trezor-firmware/pull/2221 [#2230]: https://github.com/trezor/trezor-firmware/pull/2230 [#2239]: https://github.com/trezor/trezor-firmware/pull/2239 [#2284]: https://github.com/trezor/trezor-firmware/pull/2284 [#2289]: https://github.com/trezor/trezor-firmware/pull/2289 [#2354]: https://github.com/trezor/trezor-firmware/pull/2354 [#2364]: https://github.com/trezor/trezor-firmware/pull/2364 [#2414]: https://github.com/trezor/trezor-firmware/pull/2414 [#2433]: https://github.com/trezor/trezor-firmware/pull/2433 [#2439]: https://github.com/trezor/trezor-firmware/pull/2439 [#2445]: https://github.com/trezor/trezor-firmware/pull/2445 [#2517]: https://github.com/trezor/trezor-firmware/pull/2517 [#2535]: https://github.com/trezor/trezor-firmware/pull/2535 [#2541]: https://github.com/trezor/trezor-firmware/pull/2541 [#2542]: https://github.com/trezor/trezor-firmware/pull/2542 [#2547]: https://github.com/trezor/trezor-firmware/pull/2547 [#2561]: https://github.com/trezor/trezor-firmware/pull/2561 [#2576]: https://github.com/trezor/trezor-firmware/pull/2576 [#2608]: https://github.com/trezor/trezor-firmware/pull/2608 [#2692]: https://github.com/trezor/trezor-firmware/pull/2692 [#2701]: https://github.com/trezor/trezor-firmware/pull/2701 [#2745]: https://github.com/trezor/trezor-firmware/pull/2745 [#2786]: https://github.com/trezor/trezor-firmware/pull/2786 [#2795]: https://github.com/trezor/trezor-firmware/pull/2795 [#2801]: https://github.com/trezor/trezor-firmware/pull/2801 [#2832]: https://github.com/trezor/trezor-firmware/pull/2832 [#2833]: https://github.com/trezor/trezor-firmware/pull/2833 [#2880]: https://github.com/trezor/trezor-firmware/pull/2880 [#2919]: https://github.com/trezor/trezor-firmware/pull/2919 [#2967]: https://github.com/trezor/trezor-firmware/pull/2967 [#2989]: https://github.com/trezor/trezor-firmware/pull/2989 [#3037]: https://github.com/trezor/trezor-firmware/pull/3037 [#3045]: https://github.com/trezor/trezor-firmware/pull/3045 [#3048]: https://github.com/trezor/trezor-firmware/pull/3048 [#3203]: https://github.com/trezor/trezor-firmware/pull/3203 [#3208]: https://github.com/trezor/trezor-firmware/pull/3208 [#3227]: https://github.com/trezor/trezor-firmware/pull/3227 [#3237]: https://github.com/trezor/trezor-firmware/pull/3237 [#3255]: https://github.com/trezor/trezor-firmware/pull/3255 [#3359]: https://github.com/trezor/trezor-firmware/pull/3359 [#3364]: https://github.com/trezor/trezor-firmware/pull/3364 [#3422]: https://github.com/trezor/trezor-firmware/pull/3422 [#3434]: https://github.com/trezor/trezor-firmware/pull/3434 [#3442]: https://github.com/trezor/trezor-firmware/pull/3442 [#3496]: https://github.com/trezor/trezor-firmware/pull/3496 [#3504]: https://github.com/trezor/trezor-firmware/pull/3504 [#3509]: https://github.com/trezor/trezor-firmware/pull/3509 [#3636]: https://github.com/trezor/trezor-firmware/pull/3636 [#3728]: https://github.com/trezor/trezor-firmware/pull/3728 [#3868]: https://github.com/trezor/trezor-firmware/pull/3868 [#3893]: https://github.com/trezor/trezor-firmware/pull/3893 [#3993]: https://github.com/trezor/trezor-firmware/pull/3993 [#4000]: https://github.com/trezor/trezor-firmware/pull/4000 [#4041]: https://github.com/trezor/trezor-firmware/pull/4041 [#4076]: https://github.com/trezor/trezor-firmware/pull/4076 [#4089]: https://github.com/trezor/trezor-firmware/pull/4089 [#4101]: https://github.com/trezor/trezor-firmware/pull/4101 [#4119]: https://github.com/trezor/trezor-firmware/pull/4119 [#4155]: https://github.com/trezor/trezor-firmware/pull/4155 [#4227]: https://github.com/trezor/trezor-firmware/pull/4227 [#4282]: https://github.com/trezor/trezor-firmware/pull/4282 [#4351]: https://github.com/trezor/trezor-firmware/pull/4351 [#4464]: https://github.com/trezor/trezor-firmware/pull/4464 [#4740]: https://github.com/trezor/trezor-firmware/pull/4740 [#4948]: https://github.com/trezor/trezor-firmware/pull/4948 [#4975]: https://github.com/trezor/trezor-firmware/pull/4975 [#4976]: https://github.com/trezor/trezor-firmware/pull/4976 [#5000]: https://github.com/trezor/trezor-firmware/pull/5000 [#5220]: https://github.com/trezor/trezor-firmware/pull/5220 [#5328]: https://github.com/trezor/trezor-firmware/pull/5328 [#5344]: https://github.com/trezor/trezor-firmware/pull/5344 [#5455]: https://github.com/trezor/trezor-firmware/pull/5455 [#5499]: https://github.com/trezor/trezor-firmware/pull/5499 [#5760]: https://github.com/trezor/trezor-firmware/pull/5760 [#5928]: https://github.com/trezor/trezor-firmware/pull/5928 [#6103]: https://github.com/trezor/trezor-firmware/pull/6103 [#6112]: https://github.com/trezor/trezor-firmware/pull/6112 [#6202]: https://github.com/trezor/trezor-firmware/pull/6202 [#6273]: https://github.com/trezor/trezor-firmware/pull/6273 [#6349]: https://github.com/trezor/trezor-firmware/pull/6349 [#6449]: https://github.com/trezor/trezor-firmware/pull/6449 [#6525]: https://github.com/trezor/trezor-firmware/pull/6525 [#6545]: https://github.com/trezor/trezor-firmware/pull/6545 [#6555]: https://github.com/trezor/trezor-firmware/pull/6555 [#6564]: https://github.com/trezor/trezor-firmware/pull/6564 [#6575]: https://github.com/trezor/trezor-firmware/pull/6575 [#6580]: https://github.com/trezor/trezor-firmware/pull/6580 [#6588]: https://github.com/trezor/trezor-firmware/pull/6588 [#6633]: https://github.com/trezor/trezor-firmware/pull/6633 [#6730]: https://github.com/trezor/trezor-firmware/pull/6730 [#6759]: https://github.com/trezor/trezor-firmware/pull/6759 [#6826]: https://github.com/trezor/trezor-firmware/pull/6826 [#6859]: https://github.com/trezor/trezor-firmware/pull/6859 [#6994]: https://github.com/trezor/trezor-firmware/pull/6994 [#7053]: https://github.com/trezor/trezor-firmware/pull/7053 [#7101]: https://github.com/trezor/trezor-firmware/pull/7101 [#7168]: https://github.com/trezor/trezor-firmware/pull/7168 [#7259]: https://github.com/trezor/trezor-firmware/pull/7259 [#7359]: https://github.com/trezor/trezor-firmware/pull/7359 [#7365]: https://github.com/trezor/trezor-firmware/pull/7365 [#7428]: https://github.com/trezor/trezor-firmware/pull/7428 ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1760000640.7847416 trezor-0.20.2/COPYING0000644000000000000000000001674315071675201011120 0ustar00 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1770819678.479207 trezor-0.20.2/README.md0000644000000000000000000001034715143110136011325 0ustar00# trezorlib [![repology](https://repology.org/badge/tiny-repos/python:trezor.svg)](https://repology.org/metapackage/python:trezor) [![image](https://badges.gitter.im/trezor/community.svg)](https://gitter.im/trezor/community) Python library and command-line client for communicating with Trezor Hardware Wallet. See for more information. ## Install Python Trezor tools require Python 3.9 or higher, and libusb 1.0. The easiest way to install it is with `pip`. The rest of this guide assumes you have a working `pip`; if not, you can refer to [this guide](https://packaging.python.org/tutorials/installing-packages/). On a typical system, you already have all you need. Install `trezor` with: ```sh pip3 install trezor ``` On Windows, you also need to either install [Trezor Bridge](https://suite.trezor.io/web/bridge/), or [libusb](https://github.com/libusb/libusb/wiki/Windows) and the appropriate [drivers](https://zadig.akeo.ie/). ### Firmware version requirements Current trezorlib version supports Trezor One version 1.8.0 and up, Trezor T version 2.1.0 and up, and all versions of the Trezor Safe family. For firmware versions below 1.8.0 and 2.1.0 respectively, the only supported operation is "upgrade firmware". Trezor One with firmware _older than 1.7.0_ and bootloader _older than 1.6.0_ (including pre-2021 fresh-out-of-the-box units) will not be recognized, unless you install HIDAPI support (see below). ### Installation options * **Bluetooth**: To support connecting to T3W1 or later models via Bluetooth, additional dependencies are needed. Install with: ```sh pip3 install trezor[ble] ``` * **Ethereum**: To support Ethereum signing from command line, additional packages are needed. Install with: ```sh pip3 install trezor[ethereum] ``` * **Stellar**: To support Stellar signing from command line, additional packages are needed. Install with: ```sh pip3 install trezor[stellar] ``` * **Firmware-less Trezor One**: If you are setting up a brand new Trezor One manufactured before 2021 (with pre-installed bootloader older than 1.6.0), you will need HIDAPI support. On Linux, you will need the following packages (or their equivalents) as prerequisites: `python3-dev`, `cython3`, `libusb-1.0-0-dev`, `libudev-dev`. Install with: ```sh pip3 install trezor[hidapi] ``` To install all four, use `pip3 install trezor[ble,hidapi,ethereum,stellar]`. ### Distro packages Check out [Repology](https://repology.org/metapackage/python:trezor) to see if your operating system has an up-to-date python-trezor package. ### Running from source Install the [uv](https://docs.astral.sh/uv/) tool, checkout `trezor-firmware` from git, and activate the uv environment: ```sh git clone https://github.com/trezor/trezor-firmware cd trezor-firmware git submodule update --init --recursive uv sync source .venv/bin/activate ``` In this environment, trezorlib and the `trezorctl` tool is running from the live sources, so your changes are immediately effective. ## Command line client (trezorctl) The included `trezorctl` python script can perform various tasks such as changing setting in the Trezor, signing transactions, retrieving account info and addresses. See the [python/docs/](https://github.com/trezor/trezor-firmware/tree/main/python/docs) sub folder for detailed examples and options. NOTE: An older version of the `trezorctl` command is [available for Debian Stretch](https://packages.debian.org/en/stretch/python-trezor) (and comes pre-installed on [Tails OS](https://tails.boum.org/)). ## Python Library You can use this python library to interact with a Trezor and use its capabilities in your application. See examples here in the [tools/](https://github.com/trezor/trezor-firmware/tree/main/python/tools) sub folder. ## Changelog Visit [CHANGELOG.md] for the latest changes. [CHANGELOG.md]: https://github.com/trezor/trezor-firmware/blob/main/python/CHANGELOG.md ## Contributing If you want to change protobuf definitions, you will need to regenerate definitions in the `python/` subdirectory. First, make sure your submodules are up-to-date with: ```sh git submodule update --init --recursive ``` Then, rebuild the protobuf messages by running, from the `trezor-firmware` top-level directory: ```sh make gen ``` ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1760000640.7849991 trezor-0.20.2/bash_completion.d/trezorctl.sh0000644000000000000000000000077515071675201016037 0ustar00_trezorctl() { export TREZORCTL_COMPLETION_CACHE local cur prev cmds base COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" if [ -z "$TREZORCTL_COMPLETION_CACHE" ]; then help_output=$(trezorctl --help | grep '^ [a-z]' | awk '{ print $1 }') export TREZORCTL_COMPLETION_CACHE="$help_output" fi cmds="$TREZORCTL_COMPLETION_CACHE" COMPREPLY=($(compgen -W "${cmds}" -- ${cur})) return 0 } complete -F _trezorctl trezorctl ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1770638540.756083 trezor-0.20.2/docs/EXAMPLES.rst0000644000000000000000000001257615142346315012765 0ustar00Examples demonstrating how to use trezorctl =========================================== Show all available `options `_: .. code:: $ trezorctl --help Retrieve features, settings and coin types supported by your device: .. code:: $ trezorctl get-features Bitcoin examples ---------------- Get first receiving address of first account for Bitcoin (Legacy / non-SegWit): .. code:: $ trezorctl btc get-address --script-type address --address m/44h/0h/0h/0/0 Get first receiving address of first account for Bitcoin (SegWit-in-P2SH): .. code:: $ trezorctl btc get-address --script-type p2shsegwit --address m/49h/0h/0h/0/0 Get first receiving address of first account for Bitcoin (Bech32 native SegWit P2WPKH): .. code:: trezorctl btc get-address --script-type segwit --address m/84h/0h/0h/0/0 Get Legacy Bitcoin ``xpub`` (can be used to create a watch-only wallet): .. code:: trezorctl btc get-public-node --address m/44h/0h/0h Transaction signing ------------------- ``trezorctl`` supports offline signing of transactions in a `custom JSON format `_. If you have transaction data in file ``tx.json``, use the following call to get the signature: .. code:: $ trezorctl btc sign-tx tx.json Please confirm action on your Trezor device Signed transaction: 02000000025a6bdf3ac73e3e7047380d484e2f7d58ea633a509b9a63fe95fab84d64(...) A provided script can be used to sign transactions interactively. You will need the following pieces of info: 1) Transaction ID containing the Output we want to spend (aka ``prevhash`` or ``a5ea715a...d201e64e`` in example below). 2) Index number of the Output being spent from the above tx (aka ``previndex`` or ``0`` in example below). 3) BIP32 path to the Node which can spend the above UTXO (eg ``Bitcoin/0h/0/0`` for the first). 4) Destination address where you want to send funds (eg ``3M8XGFBKwkf7miBzpkU3x2DoWwAVrD1mhk`` below). 5) Amount to send in satoshis - ``91305`` in the example below (multiply BTC amount 0.00091305 by 100,000,000). 6) Expected fee (``0.00019695`` BTC in example below). Note: the miner receives all satoshis left unspent from a transaction. If you want to receive some change, you need to send it to an address you own (otherwise it will go to miner). Fee is not needed below, we just want it as a sanity check. There are many ways to retrieve the info above: from a watch-only wallet in Bitcoin Core, https://coinb.in (`screenshot `_) etc. The easiest way is using the Trezor Suite: https://suite.trezor.io After authenticating, open the "Send" tab, fill-out all details, then open the "Show transaction details" menu to see the info needed above (`screenshot `_). Once you have the required details, you can then perform the transaction signing using ``trezorctl`` as shown in the example below: .. code:: $ python3 tools/build_tx.py | trezorctl btc sign-tx - Coin name [Bitcoin]: Bitcoin Previous output to spend (txid:vout) []: a5ea715aa99ca30516f3af6f622dfe7399d883d49ad74b1fe33fdf73d201e64e:0 BIP-32 path to derive the key: m/44h/0h/0h/0/0 Prefilling input amount: 111000 Sequence Number to use (RBF opt-in enabled by default) [4294967293]: 4294967293 Input type (address, segwit, p2shsegwit) [address]: Previous output to spend (txid:vout) []: Output address (for non-change output) []: 3M8XGFBKwkf7miBzpkU3x2DoWwAVrD1mhk Amount to spend (satoshis): 91305 Output address (for non-change output) []: BIP-32 path (for change output) []: Transaction version [2]: Transaction locktime [0]: Please confirm action on your Trezor device Signed Transaction: 02000000014ee601d273df3fe31f4bd79ad483d89973fe2d626faff316(...) The signed transaction text can then be inspected in Electrum (`screenshot `_), `coinb.in `_ or another tool. If all info is correct, you can then broadcast the tx to the Bitcoin network via the URL provided by ``trezorctl`` or Electrum (Tools → Load transaction → From text. Here is a `screenshot `_). TIP: Electrum will only show the transaction fee if you previously imported the spending address (eg ``16ijWp48xn8hj6deD5ZHSJcgNjtYbpiki8`` from example tx above). Also, the final tx size (and therefore satoshis / byte) might be slightly different than the estimate shown on suite.trezor.io The final broadcast and mined transaction can be seen here: https://blockchain.info/tx/270684c14be85efec9adafa50339fd120658381ed2300b9207d0a0df2a5f0bf9 Litecoin examples ----------------- Get first receiving address of first account for Litecoin (SegWit-in-P2SH): .. code:: $ trezorctl ltc get-address --script-type p2shsegwit --address m/49h/2h/0h/0/0 Get first receiving address of first account for Litecoin (Bech32 native SegWit P2WPKH): .. code:: $ trezorctl ltc get-address --script-type segwit --address m/84h/2h/0h/0/0 Notes ----- 1. Bech32 native SegWit encoded addresses require `Trezor Firmware v1.6.0 `_ or later. ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1785487156.8354588 trezor-0.20.2/docs/OPTIONS.rst0000644000000000000000000003450415233057465012703 0ustar00Command-line options for trezorctl ================================== See `EXAMPLES.rst `_ for examples on how to use. ``trezorctl`` is split into a number of subcommands based on currency and/or functionality. The best way to get up-to-date help is to use the integrated help option. The full list of subcommands can be seen like so: .. code:: trezorctl --help Each subcommand has its own help, shown with ``trezorctl --help``. List of subcommands ------------------- For convenience of search, the help texts of all commands and subcommands are listed on one page here. .. ### ALL CONTENT BELOW IS GENERATED BY helper-scripts/make-options-rst.py ### .. code:: Usage: trezorctl [OPTIONS] COMMAND [ARGS]... Options: -p, --path TEXT Select device by specific path. -B, --ble / --no-ble Enable/disable support for Bluetooth Low Energy. -v, --verbose Show communication messages. -j, --json Print result as JSON object -P, --passphrase-on-host Enter passphrase on host. -S, --script Use UI for usage in scripts. -s, --session-id DATA Resume given session. -r, --record DIRECTORY Record screen changes into a specified directory. --version Show the version and exit. --help Show this message and exit. Commands: benchmark Benchmark commands. ble BLE commands. btc Bitcoin and Bitcoin-like coins commands. cardano Cardano commands. clear-session Clear current session and lock the device. crypto Miscellaneous cryptography features. debug Miscellaneous debug features. device Device management commands - setup, recover seed, wipe, etc. eos EOS commands. ethereum Ethereum commands. evolu Evolu commands. fido FIDO2, U2F and WebAuthN management commands. firmware Firmware commands. get-features Retrieve device features and settings. get-session Get a session ID for subsequent commands. list List connected Trezor devices. monero Monero commands. nem NEM commands. nostr Nostr commands. ping Send ping message. ripple Ripple commands. set Device settings. solana Solana commands. stellar Stellar commands. telemetry Telemetry commands. tezos Tezos commands. tron Tron commands. usb-reset Perform USB reset on stuck devices. version Show version of trezorctl/trezorlib. wait-for-emulator Wait until Trezor Emulator comes up. Benchmark commands. ~~~~~~~~~~~~~~~~~~~ .. code:: trezorctl benchmark --help .. code:: Usage: trezorctl benchmark [OPTIONS] COMMAND [ARGS]... Benchmark commands. Options: --help Show this message and exit. Commands: list-names List names of all supported benchmarks run Run benchmark BLE commands. ~~~~~~~~~~~~~ .. code:: trezorctl ble --help .. code:: Usage: trezorctl ble [OPTIONS] COMMAND [ARGS]... BLE commands. Options: --help Show this message and exit. Commands: connect Connect to the device via BLE. unpair Erase bond of currently connected device, or all devices (on device side). Bitcoin and Bitcoin-like coins commands. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code:: trezorctl btc --help .. code:: Usage: trezorctl btc [OPTIONS] COMMAND [ARGS]... Bitcoin and Bitcoin-like coins commands. Options: --help Show this message and exit. Commands: get-address Get address for specified path. get-descriptor Get descriptor of given account. get-public-node Get public node of given path. sign-message Sign message using address of given path. sign-tx Sign transaction. verify-message Verify message. Cardano commands. ~~~~~~~~~~~~~~~~~ .. code:: trezorctl cardano --help .. code:: Usage: trezorctl cardano [OPTIONS] COMMAND [ARGS]... Cardano commands. Options: --help Show this message and exit. Commands: get-address Get Cardano address. get-native-script-hash Get Cardano native script hash. get-public-key Get Cardano public key. sign-message Sign Cardano message containing arbitrary data. sign-tx Sign Cardano transaction. Miscellaneous cryptography features. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code:: trezorctl crypto --help .. code:: Usage: trezorctl crypto [OPTIONS] COMMAND [ARGS]... Miscellaneous cryptography features. Options: --help Show this message and exit. Commands: decrypt-keyvalue Decrypt value by given key and path. encrypt-keyvalue Encrypt value by given key and path. get-entropy Get random bytes from device. Miscellaneous debug features. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code:: trezorctl debug --help .. code:: Usage: trezorctl debug [OPTIONS] COMMAND [ARGS]... Miscellaneous debug features. Options: --help Show this message and exit. Commands: optiga-set-sec-max Set Optiga's security event counter to maximum. prodtest-t1 Perform a prodtest on Model One. record Record screen changes into a specified directory. set-battery-state Set emulated battery/power state (emulator only). set-log-filter Set logging filter string. Device management commands - setup, recover seed, wipe, etc. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code:: trezorctl device --help .. code:: Usage: trezorctl device [OPTIONS] COMMAND [ARGS]... Device management commands - setup, recover seed, wipe, etc. Options: --help Show this message and exit. Commands: authenticate Verify the authenticity of the device. backup Perform device seed backup. forget Forget a THP pairing key. load Upload seed and custom configuration to the device. reboot-to-bootloader Reboot device into bootloader mode. recover Start safe recovery workflow. sd-protect Secure the device with SD card protection. serial-number Get serial number. set-busy Show a "Do not disconnect" dialog. setup Perform device setup and generate new seed. tutorial Show on-device tutorial. unlock-bootloader Unlocks bootloader. wipe Reset device to factory defaults and remove all private data. EOS commands. ~~~~~~~~~~~~~ .. code:: trezorctl eos --help .. code:: Usage: trezorctl eos [OPTIONS] COMMAND [ARGS]... EOS commands. Options: --help Show this message and exit. Commands: get-public-key Get Eos public key in base58 encoding. sign-transaction Sign EOS transaction. Ethereum commands. ~~~~~~~~~~~~~~~~~~ .. code:: trezorctl ethereum --help .. code:: Usage: trezorctl ethereum [OPTIONS] COMMAND [ARGS]... Ethereum commands. Most Ethereum commands now require the host to specify definition of a network and possibly an ERC-20 token. These definitions can be automatically fetched using the `-a` option. You can also specify a custom definition source using the `-d` option. Allowable values are: - HTTP or HTTPS URL - path to local directory - path to local tar archive For debugging purposes, it is possible to force use a specific network, token or contract descriptor definition by using the `--network`, `--token` and `--display-format` options. These options accept either a path to a file with a binary blob, or a hex-encoded string. Options: -d, --definitions TEXT Source for Ethereum definition blobs. -a, --auto-definitions Automatically download required definitions from trezor.io --network TEXT Network definition blob. --token TEXT Token definition blob. --display-format TEXT ERC-7730 clear-signing contract descriptor blob. --help Show this message and exit. Commands: get-address Get Ethereum address in hex encoding. get-public-node Get Ethereum public node of given path. sign-auth-eip7702 Sign EIP-7702 authorization. sign-message Sign message with Ethereum address. sign-tx Sign (and optionally publish) Ethereum transaction. sign-typed-data Sign typed data (EIP-712) with Ethereum address. sign-typed-data-hash Sign hash of typed data (EIP-712) with Ethereum address. verify-message Verify message signed with Ethereum address. Evolu commands. ~~~~~~~~~~~~~~~ .. code:: trezorctl evolu --help .. code:: Usage: trezorctl evolu [OPTIONS] COMMAND [ARGS]... Evolu commands. Evolu is a local first storage framework. See https://github.com/evoluhq/evolu Options: --help Show this message and exit. Commands: get-delegated-identity-key Request the delegated identity key of this device. get-node Return the SLIP-21 node for Evolu. index-management Read the rotation index for the delegated identity key. sign-registration-request Sign a registration request for this device to be registered at... FIDO2, U2F and WebAuthN management commands. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code:: trezorctl fido --help .. code:: Usage: trezorctl fido [OPTIONS] COMMAND [ARGS]... FIDO2, U2F and WebAuthN management commands. Options: --help Show this message and exit. Commands: counter Get or set the FIDO/U2F counter value. credentials Manage FIDO2 resident credentials. Firmware commands. ~~~~~~~~~~~~~~~~~~ .. code:: trezorctl firmware --help .. code:: Usage: trezorctl firmware [OPTIONS] COMMAND [ARGS]... Firmware commands. Options: --help Show this message and exit. Commands: download Download and save the firmware image. get-hash Get a hash of the installed firmware combined with the optional challenge. update Upload new firmware to device. verify Verify the integrity of the firmware data stored in a file. Monero commands. ~~~~~~~~~~~~~~~~ .. code:: trezorctl monero --help .. code:: Usage: trezorctl monero [OPTIONS] COMMAND [ARGS]... Monero commands. Options: --help Show this message and exit. Commands: get-address Get Monero address for specified path. get-watch-key Get Monero watch key for specified path. NEM commands. ~~~~~~~~~~~~~ .. code:: trezorctl nem --help .. code:: Usage: trezorctl nem [OPTIONS] COMMAND [ARGS]... NEM commands. Options: --help Show this message and exit. Commands: get-address Get NEM address for specified path. sign-tx Sign (and optionally broadcast) NEM transaction. Nostr commands. ~~~~~~~~~~~~~~~ .. code:: trezorctl nostr --help .. code:: Usage: trezorctl nostr [OPTIONS] COMMAND [ARGS]... Nostr commands. Options: --help Show this message and exit. Commands: get-pubkey Return the pubkey derived by the given path. sign-event Sign an event using the key derived by the given path. Ripple commands. ~~~~~~~~~~~~~~~~ .. code:: trezorctl ripple --help .. code:: Usage: trezorctl ripple [OPTIONS] COMMAND [ARGS]... Ripple commands. Options: --help Show this message and exit. Commands: get-address Get Ripple address sign-tx Sign Ripple transaction Device settings. ~~~~~~~~~~~~~~~~ .. code:: trezorctl set --help .. code:: Usage: trezorctl set [OPTIONS] COMMAND [ARGS]... Device settings. Options: --help Show this message and exit. Commands: auto-lock-delay Set auto-lock delay (in seconds). brightness Set display brightness. display-rotation Set display rotation. experimental-features Enable or disable experimental message types. flags Set device flags. haptic-feedback Enable or disable haptic feedback. homescreen Set new homescreen. label Set new device label. language Set new language with translations. passphrase Enable, disable or configure passphrase protection. pin Set, change or remove PIN. safety-checks Set safety check level. wipe-code Set or remove the wipe code. Solana commands. ~~~~~~~~~~~~~~~~ .. code:: trezorctl solana --help .. code:: Usage: trezorctl solana [OPTIONS] COMMAND [ARGS]... Solana commands. Options: --help Show this message and exit. Commands: get-address Get Solana address. get-public-key Get Solana public key. sign-message Sign a Solana off-chain message. sign-tx Sign Solana transaction. verify-message Verify a signed Solana off-chain message. Stellar commands. ~~~~~~~~~~~~~~~~~ .. code:: trezorctl stellar --help .. code:: Usage: trezorctl stellar [OPTIONS] COMMAND [ARGS]... Stellar commands. Options: --help Show this message and exit. Commands: get-address Get Stellar public address. sign-soroban-authorization Sign a base64-encoded Soroban authorization entry. sign-transaction Sign a base64-encoded transaction envelope. Telemetry commands. ~~~~~~~~~~~~~~~~~~~ .. code:: trezorctl telemetry --help .. code:: Usage: trezorctl telemetry [OPTIONS] COMMAND [ARGS]... Telemetry commands. Options: --help Show this message and exit. Commands: get Read telemetry data from the device. Tezos commands. ~~~~~~~~~~~~~~~ .. code:: trezorctl tezos --help .. code:: Usage: trezorctl tezos [OPTIONS] COMMAND [ARGS]... Tezos commands. Options: --help Show this message and exit. Commands: get-address Get Tezos address for specified path. get-public-key Get Tezos public key. sign-tx Sign Tezos transaction. Tron commands. ~~~~~~~~~~~~~~ .. code:: trezorctl tron --help .. code:: Usage: trezorctl tron [OPTIONS] COMMAND [ARGS]... Tron commands. Options: --help Show this message and exit. Commands: get-address Get Tron address sign-tx Sign a raw transaction. ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1770638540.7565022 trezor-0.20.2/docs/README.rst0000644000000000000000000000036115142346315012471 0ustar00Documentation for trezorctl commandline client ============================================== * `EXAMPLES.rst `_ - Examples demonstrating how to use trezorctl * `OPTIONS.rst `_ - Commandline options for trezorctl ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1760000640.7854953 trezor-0.20.2/docs/sign_tx-coinb.in.png0000644000000000000000000007017115071675201014666 0ustar00‰PNG  IHDRÉ�'zÛþtEXtSoftwareAdobe ImageReadyqÉe<PLTEâââ4ÃáÕ¤m��’ÕõþЭ…ÿù×w‡¯«]3ççç°ŠtÖîíÌÌÌ�‚ºôØËUUUÿûááûþ®ÃÔÔæñÿÿòÓ©½Ul›XwµM�ÅÖèÖxww÷Ú¨äÅ›vw‹¤ÕóÒȱòòòÊì÷ÝÝݪ¸Ìd33‹wv#†Èµ£”šhUUUj$wºêêêR ÕkUT33a™ÆäÖÖÖòÿÿÊÝéîëÒ“{‘gÉð¦oTb™Åb£Ö¨–‰“£°···íäÆY†·ÇäíUV„¤¤¤þëÅ÷ê×£Èãû⺤‚ºƒÆêììì¶Ôèyƒ™—†yÒËÉúúú‚WSty¹®Ûö˜¹ÙÅ™ftªÔ3T¨…µØp’É“U~¤ÌôܵåÌ£îîãèÔºÿÿùÕÒ¿á¼�¶ƒUfffËòþäîî9…Áùÿÿ=KUÙ³À÷÷ö†¦ÄÆÍ×mO4‡¾ã³ëó×ÎÓÄÔÞ¹ãúšÓóúôòüðâRe|¨ÑëueTÕ¼ŸÛ¦_”¤ÃíÕ¬s½åšÁݳäø$}ÇãÈyªäù¿ëúàóý˜´É5u·ýòÑmql3L‹·§¾Ä¾x¯o ËœÓå‚«Ò»Ýøøï³Ìà‰63ß³x «º¼Þ½ñôûÆ´£º­œþýû�™³äëär–¶8Ÿ×¡¶¼ÑßÎîíé!j¦‘ãòðãØ?o‘õöÜUZŸ33„òïóÑÒИËî­¯¬ÞäðæÆÀ$©æ�„�RªÝéîîƒsZÂâôš›™`u„ÓÞ刴Í{µá�[UbQ_ùõùÍÆÅ$œáž€^»ôþöþö§˜¼3c§òÏŸÐÕßÆÈÆk°Þöõêln€éí纙y§€vöùþÐÆÍÜÛÓËÌÂ_b_ÞÒÉ�ÇëÿùöãñÕåÛØäÔÑåáÕ]�Úôà3c±Æ¢‚èäæmãöµèùîëî~Øì¸x5âéïì÷÷r`sïéåïôðÖãê±äíãåäÞ¼`Z`†¸ÒÌõïî¾ÆÓÁ›»®óü“±Ñ&’Òìñ÷;€ †eQÿùþJxº434äâäôóôÀßîîîõõõøøøÖîøÿÿÿ™’UÚmIDATxÚì½@U¾ÿo‚àtô a•¬+*‘ ¤â?LÅ?‰¨ù¦›¨jfA€™yóþá’íM­�úÑ&šmmßÌ?ݵ¶5ÝÌ]ï­kî®ëm«k[_fý‚Ìïó9gæáA@Ñ„Þ/‹ç™3çœ93ϼæsΙ¦Í•Ÿœ7…+üœh“€É0˜ “€É0˜ L†ÉÀd˜ L†É4Öä ¢2&Ð’MÎøð®{V>ù¤ÿžÊË·Dg˜ @ó›\YqÏ“ÿC<ùd»í±cÛTTÂdZžÉ^%O �Ùæÿ!™£z]£4õ¯JºÒp Là&›¼6¶ï“ÿÃÿ—£._£tppÍ„^ƒ;Ԍ╂/ö‚ÉÜZ“c�nòÉ'7‘ɤó“O¦õzµþÒê‰5Ãoq露šU^,;Qê•“¸¥&—x}Rܳ綬vYDÏžŸ-®?¢fäŸ8QCÒ ¯Òn5ªÌø9˜œQ‰ Ün1¹ ø“6ÿöÛßv¸Øæ“¨â¨6ÁVï:Ã9âÍpþ(ss“£åŒúL¾Ò?Ö->8ãZ£åoòå2·Šfø$ÖÆÇ¯½•·÷ËTµ4ª¹+í´$¾ *býÔ&gÄzÿ6cÇ•QÁ^k× ŽŠ 6ÎÅâ£G½¢è”½,Þs¨ö:z”–iiT1¥\–&GE=Z=OÖ듣ţ2h}ÔÅ(ÊSÙ(“½òóóƒo–É›ù^,UoXå^%ne±Á¥%½nÕ'_¡·‰/iæÎI�*p»³~j“�–�ÉýÉäß-( “KdŽJ¯2uΜ|·¨Œ^滂Qæ8yÔ‰jI)¥g°É¥e¥sæ”ôª1N.6ÓÝê¸\סa¬¢(ÅÎ¥Ï ñ˧ß6‹Éñ*G¢ßÈKÏ¿{Áe݇¿;%ãÝØª&Eä’Š6¥ªœùû,6¾ä½>Ò­©"»‘SÁýcéš ܇ïzQç¯Qfø‘ëÿÔãããËÔ²øÒRzSÀ)Ÿ>œa“áßZ[ý´ÿ×âÉâµt~¨ªs&ôÃwE3?×n­ÉÅ%G‹?a“ûG “‹K„Qê‰|·²²2!¥ZFVæô’ãd2ùD¾šbNÙ(6yNiYe6ÇÆN“çpžeM6¹‡2ì½Lv±LÎà³�TÞšÄ'l¢ºÞeežº÷J;•~4¥kM¹�쥶éÒ•ç?Z×Ä�¡D%Ÿ ¢F‘%fKAõ—9¬Ö³òùã—îX»ÀÖ�åÊ«žçÍ·¢ž�¦Ñ�¯õÊQ®mí EeëŽG5À]TUw‘éU�𦘿¶8ªCÆŽŒQkcc�{I“¯”�˜±rÔ'G•ÌÉ/é_qT=QÚáŠeòœ²£%ù'Ü‚Ùäü‚ŠŠXZ¸Êä²£”œ?êzLVŠèåþ—›Ád!²Z,´Ëtþ¬ŽÉU‹š6FæÓV¾OT Ï_YÚ‘Dhjj£ªýÅ(“['>’¼Ði•Yê´ú ù×grÆGÓšd2_†VªËØaºr<ÿ‘gF]&7\kF©êŒÉj�YGGUÀU­¯o'Ü!áM™ñêPVàÅ&W^,f“?9*MGQ¶}ÀãÆµq#3¹;x"?Øi2]Öƒ)½XŒ“é?Š”•ßô¬6™Öö"Ÿû7drTqqq<™\@¯Á–ÉÊiòçcÈê‹3þ¼¡Ãçý¦uèÐÎç@ÓL–"{‰h N!u?òçÛqÿ€[¶tm™ô—„{�œCÚOã9DO§}Ú­þé¥êCÞ†¡�N¼^–ÖäãEt9èö‰»k;u‘M“éšÂÈó|ƒµ¶q5Yö®gPŽWÜe“z¨/†NçÉ+Õ HxsLŽ'}ÛTîøkðQarÉZy§´¢„:ÌôÍèP’?'_�3§,8£N“UcÍ9áÖ!#ã®Ã‡ïjºÉ4<�e9ãéÕËiò=ã}޳ÉI4sÛ2SÙ9~Õì¸û}ÄXY"×6¹ÂÍìJzUOñ~äy[§–••ÅoþCèÞj“Õem=Ï7tì¼j‰Ü£�‹$„òù¿’/Âdy�h„¥ÅGÛô/Ž·f¼Ö_1m�Æ/ç…É+Uµ,–+]EëÒhÏÎe¼Ê}×Í})>/ÝF½‚U ›Á¡dY^èNª»u¤·W›œÄ¨÷ó�›ñòº|%8Þšñ¢1†`™œñ:L&�Ók�¸w½&ßL“Kâ×z‘ÉÁGKâã×Ç{Éû›£¼Jèó,èp%£¿x·–/åñee4(.++áïr••´¹\Rë[VVІoOÞsχWF”•g´¡ôþWÆQÁ«¿Bш¹ëU:¤)ŠÏŶ á™I4@VÂî¥þõz™¡¬¬áq²©²—KRš:& *£#ß�ê±BØf™üüGIB–k‹L=ö™;·B_ªÃ_½Ägl#M6»¹G¹ócÞ…’&Ÿ5Mæš©Ã~6 Š§�©ËN‡·#õQùÏñ€?ˆ®|ÀܬW® çÍ7®wí:NÒ‰ñ¬š-f¯]z×lðö ×*º×±|!¶îB%ˆ{|y¡Eb\L-õã®:½ÎíH›HPÙdô®oÒ89¶¬À+¸r\Å'kÙd¯øbë[Y.öZWò;ñIu¸x‘'µ.’7•ý9­ý¤Õ̯7|H飸ÔeN'Ý/^̸N“; "“ï‰Öµçøa:œ¥…™4RnÂ](¡²«Èt&©…â&ê�,µ¨†É|´¡ûœjÉ•µQµêÛ5kŒè]S¨ßÙ3T]/Mn¨w}¥—›©”—ùÍŠ„¤ÄµH´'/4 +Õ–}VíýÉÕ3§�ºâ“¾Ô�î¡RÛ§å©IG²(Sr0-Òu¨ëù&˜l^‡hË?ÏÓxvìPu¾9ãŵnçHßP­ò›!5ëC”ãê½ÕÂàmj¥Ë9»Þ´‰itô‡�…7Åä·Xar”0ùh™Ë—²ªÙù=kñÆüÚuõÏš¶f\õ³É&/£Ÿ÷DP_zF„¢ Û@qY)êðùxŸ‹M¹ŸL*{ÕlXG+ÉÕ³JØF?2xöˆ”.jDªý]G1ã¥vÀ=C¨'*#Z^hrCµõQ¹8Þú¶¦9ãU˜#¯,3i1`4\UM¢î}þ8­+£îô6‘G|%…†£¼MÚÞ£k÷Y£Ü\ˆ—ÊtqïZüœÉµŽQƒ¤ÉÏÓПou5XëUßÖ”‘˜/–;–RÓ=sde4 á=q �reÏu,¼)&¯-�=J&ÿ*ª@š\|Óϧ ×’ÉQu|Ýß ©¨ç÷2¾¼ê7œm¦¸Vvôêß÷üæ?ÍÑÃÒø-ÜЄOâÚ¿Añ�¬øÚæ—ôºäKóÒxY4â�%•W–üƒ;N—›å3ÉØJGŹ´¤ÿÖÆ¼ÆoPTÈJ–ô’¯—/þ›:N.v+;ü×+¿-.ˆ§aq||ðOaòOü»Pyñò«œ×Ž¢×\»'Tݹ64Ó9à'29cÔÑ2·²’µ±en¥¥n%Å7ÿwsnC“C“öÝè^ §n¤g7œ`à'2ùJF¯6Åkc©g_{´¸Ã-èáo†Ðü&›íÚü¹ø+¹´T“o50˜ “€ÉÀd˜ L†ÉÀd˜ L&Ãd`2L&Ãd`20&“a20&“øy˜ÜÐòicZ>0˜ €É˜ €ÉÀdLÀdL&`2&`20“0“€É˜ €É˜ LÀdLÀd`2&`2&`20“0“€É˜ €É˜ LÀdLÀd`2&~J“=BôZÄÜ’V¤¶×õÉÞø4¸Y&O޾™[Ï (Mò6MŽtǧ@‹4Ùn “hN“mýò™ÇØát•ßz:nr§ZšÜ1?ÿkô®h&“MIäÈ[ B17ÓdÝ2lǸqãv§ÆÆp/ûT›w b�¾f†éqã>&?[[ðš³äcׯ~{àãêåOiõ‘TW½äSΰUÖͽk=ûÕwjÜ8+øïàYEhûôs×ÚØØ|Z\§ÉËéÝS‡å¢ý¸5x¾ä03í�.Ö»«D¹ Ì Óäèz¦µ¼»›¬xél3!.GÖ-xÅ›ƒó+¢`?k&út³î¾KÛ‹”ÈÑø¸¸>“ÛÒ»ýB#wÛÆêy0_‡ÌäDän[½ü«œæ’!“kK¨žP‹ ªÎéîìfç¹ld„Q{ .¹f3wmwssÛ\Õ"�{^Á@œ|àÖš¬§‹ÅsB¦ýù–S¦ÉkTñ2XŽ®)Ûâ嘵¦ŠÀ<™Ü—ׂt™°&zùÕ&›W ™ƒí7MŽTC®šH·W%ó¯Ýí¶õÚœCþÔm7X�l�¿: '¸Å&둽ƒ�ØØ¥)$ÍóÜC>hšÌ=^Ñù%ɸ^N'©}¶\Þľr™»àÜwÞdEÚüfïŽò.ÔŽΩ/‘c½Cá:¤É´ÙÔûõš³cöŽªZøp›ž¡ª:åÚÑ/TmÎIµÔ�ÔÀ‹Æ¢=þêzœ|à›ü!ް¯D[k›&ï5ÌU8DgZ|%,aü‰Ãr â#ÅÉ/=w¡ØÀTzîzÊ%Ç$ê“"¿0YTÊë\MEåÇÕ€kšêЬÓðÕä*ßÜí ±&Ïåw§F�%&”ím«M^#ÔæpM½g¡öîo�Õ_R Ññ½'DT7ÝYÀH MW ó4Ÿ*¶Â&GÎu¹8CòGj‘|— ªÉ©ÛŸNÝzÉ0zŽ)-ÝœÃÉ=ËJKÝvF§n+SÕ¡›®«ääÛv·ÒÒ²-Õ}æßQKÝIJ}Û˜Ò¤Þ#±l357/ž{ö¾›EÓgćªñ9Kûn°õ%¥�µØúö¾kŒZ:”Gí]†ˆM×ÜÈ®¾”ØÛÙž¼ø Ÿeb­ípSLöµ’w<0¶dÌcÖ°Ø_FbsZŠL¶f§Ò“ºZÂ,ù|í�Ð攘Ë]{ªµLöwù¢÷áj“Ýë09Ou†Æ¿¼FKICTu÷¸‰Òé¬C‘ñÌ\—U–ÿ‚dgŸÙ¹LÝ_Æ3šòdFšÊÝéDUFÒ¶bÝbµ�rV×bâþÁ Õ,ïº31é¼ÙÑ»^©Z�rÝ>7ÇäÁÖ “Ë,²iòdW“�Äê‰æ8ŽHΛP²ºÃ�2y°Kþä¨×ä•5úÔäQÀÎ�$]׿ΠU=‰ªúô¯ØN™>멪«¢¢«WÉÇÕ¤�½hÙ­¦’èOÿãž1ê:~°è¯Y4ü¦«À*Îəڙ3T»ŠÇ¨OGåø³•½sªk¡l¸L¾ ) /ürû_½šDOx™+5Ûão–Yô %z:\¶ÀM5Ùº •¾¿_}&§¶½érª‡ù6ÌMV×£É&çÖo²¿êú=Rr"ÉÛ°…ŠÉ(²&;Q¬ö`Ýi\êîºÊ0G×É"ÂV›–“Qu›Ì2nÚ(&»×,â¯s�sznRÇ{åÔm²oãz×þªë¼‘ôˆ<�_BˆîðŽ¿Ì*ã4¹Æ*³çÿÙÚ¾ª‹ÉsÍ뉵“rö¥² ´‘µ°c€{žsšJ:íou ¬Z®±Ú 驯:\L6)ôºlç$¸©&OuN<®Çä×KbKÄéž7žo('°Èò{[í�3^æ|Ö¦ºç®\î4�»¶ÉÓUqê‹ðZºÅ²Ã"05Ë9lë\VÉRÃÇÈE§ÉÂL6©�3«;9–yX@á•ÆÅFM“…rÕµ�ÉÓdÛ‘Vè]½ÚŒÓÖܵiòqULýÛCÙdçöqN‚›i²üŠ´X;»n“Y5ý¤ÈÁßù˜Äëç‰ÅD½úÓAge{ë¹ ãl‚žY¿É…WÉwÔq!íHPÕÞï=z´ø‘~{àÃ�,“]VY…v.zpe&ÏP¾=ÊYŽ&1/�U³ýÕ·Ú9c¹«É.µ¸˜L‘xV_¸¹¬>.7dÿg“ÏÊ;á\#L·ÈäTŽ‘¹9ÖW§ÃëˆÉË­ïFßÃ3]�âŽð*‡‘:3Ĭ®­™"ªà!ÿ”%[�šŠïwÆœ7RÅwGþä¨ßdÃy™¤�+íð0GÁ}ÝªŽ‹Žkž3&»¬’5`®S¼š&ûÓ™]24š²•R·:/´´Ô9¿æj²K-Õ&ÛûºÉ!±ç=Õ«ÛIEÓèŵw-zä *L·xœ¬§§›ÓXkܯ29A®Q̹j›œÉ¶ P4výæ¶Ωæ¯Fx[šÚÛë5¿«]¿É‰ÔuÞGÉÔ�.2ãÏWñ Ÿ÷Žj¡Ã°u”&«A®«¬Îy¦˜kºÚdФ…ÑFêYÖŒïaН“Õ&�°”s©¥ÚdÚÞ%i²Ëjñ=–á¡ôS¶‡MNß4]ú�Æa2¸¹&/¿jîÚyW©–É]zÔ´0­æ_\ã7(|Õ——ß °¹¨¼Å¸–Éü%/5ÀÍe,,o—–ª�Óø�¸�ë-îP¹W¯²z×bÑü¢˜eòJ6i†Yv„ðQ ~îu1™b¨³wmÕâÒ»>k–Ÿè²:•§ÁJͶò‹¸Ÿlå\Vcû4§Érn*­ú¾�Íü�Ä3�¦ û�ß aÉsùÝ=ÖM¨"1�aþúÃDþ’—˜¶~Þ¼'�¾ÁÔâ,m2ùœSØ,ÓvÏ«jsŹÚ•`¦œOZmÍ"‘Ê"éi‡ùë;é§»‘%r®’ˆ/e$­µÔ6M’7¯Vò·<6˜±;»ÖÍëé¡N“]jq19u»j^"\6b‰…Ü·Ïršlˆy¹¤Ñµ¶@3™\K‚½ŠÛðÝ•]^G¬'K›b¯#_9ÏÆ]ŸÊœK>õj#oËìØ5ÖËë5—ï8Þ©uò>ðˆ¹™ùæŸÁµ3.éÿ+YÝ©o*èÍ_þQÇ*³ð—[9­Ns¾é_ÑÈcRw-—+¶^µzÇ7ý·Öµ¥à$·ØdLÀdL&`2&`20“0“€É˜ €É˜ LÀdLÜ“ícÅÂ[úp}néÃòÁEKµ‚?gOa­Óä<ùä¦Ãz]O–cøëòa ‡õ¹MÛPêì)�Λw=—‰¦•â�ÉÓã ­Òd�ñ7qý#ë2Ù?Ò›LN®›orûðFç]>ùzLnZ)Þû#98@+59Ü29k�¶ŠR>ÒõBa팺2Å_/úQtŸ‘8Á›¨üõ>à~]¢ûÆô7uý éA…Ïô¥I¯�ò_ 7l?êé³"ôtóYg\|ÿ>£GÜÌ�Áö³f1Z]M a™F"•0ýdÕJÜÿÖ6=p)µéÑ-¶~«(Òw�¦­gÒQÊe5Åè,*æmä½'JÛÏ.ò¢gŽØ[è>ƒ3Ÿ©2lã»ÒÓGà„­Íäú™Øz¦m£>ô=ù(ÔoêûGøëzÑö�ÉÊ1Uº=Dþ�{J-Ü®Gæ$„¬‰=Nô4ý*<9:Mß]" gëYHËkJ~”OyK=§m ‰œ»\'¿¦êE}õ5чõ3ïé�¤\Ò¾=�²ŠG?XµòIö´�ÜLmx¿ýŸÔ¼lc97"U”rYí š7×ß°oŒÜy\ÏuܯÆ.ˆtçê«OÎâ�ñYL‹…CôW¼=Bôݼghe&/×3 ŠYiü\˜Mò —½ëI¼ìM9Ú¯ñæÐ,M^È?úGÎån´}ãÑTÕdÛÆ\~Œ„ìV·ƒÞNŽ6ìí…ý‰ül‹D=¹­¾ž^Hîéz`ÛÉ\,Pô“ÏQ®Ôs¢ÃlÖjšœLYöо45#Qצ¶Ÿgõ®k¬nËCúsÊ ñuiÓÞo#ö+�SÓ"Ýygh[i|±X©ôÉ�ææàŒ­ÌdrdÍÐ*c¹~bN~ˆœæò+Oo„úþÞç ç¸ÚNÊ.];&Dì²�ƒîä=!‘ù'ÏŒ*Štã°¸.øó%‚ý•¦çÏY@QwøöP]4�Ì?‘o>?FÖ*Mf·í¯Y àHÔŸzòƒÙóØ}§É.«¹fJŒ>§ë(ùó¾oR}ËÍG8s“©¤X´·¶�@œ 5Íx±lK·ÑètÀrÝÍÍ­,¾ªÚä@Ëdcxßzd¶Ódruº®'ņ„W›¼†JÇ÷6œ&ïuN§ù‹Éïq“jô~?odô&=’:é¦É‘\t3_ÌZ�ófõý±ä¬}ãàso<ùÊŒHïj“]V›&;ŒÓCBô5ÞçôÝ›ïg“¹Êq§ÉÑ¢Vq ó€É •˜lã~±a̦qò4v"| —ÐÙ»ºwí4ùøî/–½kJMÐs„Kmÿ†-$×�½k`Ÿ!¤Þ5§SM“r‘‘¬Z"wqmÝÛ>—Ÿ˜œ,œ<·†2c>÷®ÍZ�&‹~ÁrùÄæ@Oç5L¶V›&ï¹;ˆÇ~!ÇDÃÛr_à°žmö®7ñbw#`2hE&“»�߯ç:–ëóÛdéáy!kÍ\`Ík^p1¹}d×6gÍ~·¹áóñzær}âç³õ¼—ëEŸ¶ç®>íâYC³ƒkºF/×c>9.çÏì#G|Þžb$io¯¯¢rÙí#Gº@�!wæ¬ÔË/déód›d­Õ&ц#÷Ñ ÒݾQ7ŸˆÊ¥\W[&Ó|>ˆLÞ} ‹: úš�3C&GóÎ�¹y!‘ßö ‰œ+:#0´“ù~�®ÇEv~Èê™cz ˜å½&[?=ý´þý ›|=ø×úvç9½ð÷?êèªвLNœPó»›öíú°Ñ8º´,“0“0˜ €É˜ €ÉÀdLÀdL&`2&`2?O“‡{U?òé´—|†‹ýÓF=j©(ú™W7z;vÑûc½rìc‹YÚª­Qìòâ‚G>®•ܨ:R?-‰/¨ª•hÛ/ @#MN=§ë'­÷í͇æ…è�yÎJ"ÿÙy[ˆžËÀö•?„è‹© Àݵ¶F±\ŒÜW³u�©ÃÖ^­õlÈ<Ýåñ’ ãã 5hÕ&³{¹§7òoqÙBõÄ$ûF}0ëüŠ7•ŒñÑéÿGUUõñv­­Q´Õõ²1ºþ'G-“s»@�¬ù\Xû¶ÍÞÎ}2L­Údþc²ì@j;%ÝmÇØŽééez¤{Úœ®gõ䥕ô3ÔqÍz,=Ý3ÇÈûHI?ÑÕYx*‰ÇdR`Þkšü”«…©gó¿öNm¡?::õxþ*Ãh—/ÿˆîLª¯0ÇHœ3?+d’4™^Î�¢™ñXzØD—Ym�õ¶Ð€m Ò=?ï—6Ú¼¬‰6lã�l /] Ø'k]÷Q’w⟠‡¤§ÏwÌÑ#÷g®üu&NÐJM¶·×ßj¯1‘ L•]U~äñÜF¹pX×óCôÉï·×ÓÓ«Ãäa ÇÔ;×&êüÇà…ÉoG½fšœL•$§Î5&O%KmeWþ°HzÅÛŸ_Â¥Žü4¸s;ÓĺcÎÙÌ6Xõx˜=xNô¶:æIßn•ý ¾.‰Z}©_á/³Åˆ} œŠ¡ƒVk2?ÖaÅ4Ò%Ʊ’Nwê, @Í�aÑ‹‚7铽IöcË)!/Ôóüàµ,u„K×üï#·ë¾iä¡i²ÓM29]×·ð&2�ûõ\¶=QÊGU΋N Ñ’jÉ1{×~îëB£‡þÊ­Ym°ê¡mÄ�ò\™|Ö¢9N^ç¸_…Ÿ²ú¸¨õÒäTs$]1è:±äKô°Ak5yªþʽ›D �:Õý¹«JKî"HÞ¯§Ÿ8Añ�c(õ†íìÌþ ®]Ñ'ß’A†›&Gªùs¦˜&ë<<¥²\Ç+Þíõ…›ä£e([&o{°¿n È�&'„è'Âèúß­¹´AÔóG^±‰:ã¶«w°«/жçgO‘¯¢Va2íC^GiŒ“Ak6Yö\I>ïYÌ@qÎۄɃ ƒ:´ùsJK=÷ ág´xÛ·=&z¾.óTz¸�+I¶LNv'³^ü˜˜ü9¥9ûÈÕâºA½b2ù‡UI7|£îK‘6}ÎþRõïV‹¬6Xõp°åìi²-ôÏÙ†qÏF=¼=?2jÉ«‹Z¥ÉðÎèÉÕÛ 5šLq. ´ô1tÏ(N§°Hɦɛô\ØY6:-OR�õŒ¦áêK·›óÂ<ÝKÁ•"®er ‹É#¦REÓye^ÙD®^—ÏŽ£ È$þ1¸:V¶®-×'ïáxmï;t�Õ"« V=µMÞ¨�ÃÏ^�9§ç:Èýƒ¢Vi²¹3¢§@k59õ[b$�Ždã~2-�l©n™Lkv¿©‹™«¡ïé‘äûî’úÎN1÷¦çÒ¨VÏO½Êd^Î¥#©ÆÁâÖõ`¹Ž:ôû讽^“ÅOjIéJ·ZdµÁªG˜¼¼Úd1ý®pÇœ®B�Fèú\W“õ|¾³Åo2Óð¼ÐJM&öÊán®m�®¯y“Îõ~RâÓdñ8E}¢!º9˜ÎãÑ8ïé–É$' ˜Àá“+K®Õ»Næ®u`^?ó‰�‡9DÊuüˆÈ5û ×Þ5ßÕö·ð¸;Çp¶ÈlƒaÖcÛHßD-“S³¸Ÿ>Ú0f„ˆçAÊNõF69’®ȺÛêx4#h­3^.,yÕz³µf²|ª¢™ú?Œ1uj£¾9âRZÛOÄ]ÉŽW·Ö›ý”¹®ºE² ²ž:7ð¥YÛ’^®ÉþŽ—lŧ~V&7�õ¿Ù¸Bºõó[…¿Ë¥˜|UüÇuZ{áïm^lWLY˜ €É€[fòÜ;þµxš…½.î˜Û€ÉsÿõÿÝѼ^í¸a^õºãºøÿ:÷Ú&ßÑ(‘ïðʸa2®ÓdõÚ&ÿkãªñ‡q 7θë5ùŽ…ÉÀd˜ LÀd`2L&ÃdZ¸É/ÍÍÉ™ûL E›ü”L~ª“S?¿,¸ä³ôºë€±ôÈÒßñ_ÈÜÅ�‘Iý´Æƒ]lÁœ÷ÃÏ^«ë·’dòénré4×ñ—O¾²Öžv>IF>¥F,.¹L8ŒÓâ±5ÅGŒÓD†G¼ céÚøøEV�«ŸBÓåˆCät™4™ÊfE(�®2ø8a;C“9šÇ98'm¨�¢ÌI6¦’ö÷Ó…Ç_qíµwL¢í^rð>±ÉY “¼ó"èâ°|˜7ÎCp“L~‰ÎáÊ“d/…´Ê…wÜAzmußqC&L½êcÂkõ®ýÉÎÔÙgú*aó£9xs÷§ŽõÔ¸asíýâÈ ¥p;G@êÇN§—Ĉ3ÚQßö~…|ëÝVQ6¡>¸™ÌÁ2ö=%™2'*;ßTöï3lã•Í}5M9S¡d{È€ž¨®½lW*$1™ü`ÿþý§+�TÍ™o¿rñÁ\¶àMe/×EW Zß=KÀ&Ó†Î>¦$ñf†õTb g{©ŠG©%“xŸ(h§QW�vÕöö°E=#|q‚›dòQ7ØÛØñøKƸ*oã+ùŠ»Ã¸1“ŸºÃÝ]Î{5d2ûWöžâËg=-{DL²�Ü#b¯GÄB2c!‹6ŘÊ=Wšý›kØÞ{ŒÛòpzv÷h3™b²»a‹8f4˜”:3„ÌM㇕u¶ñ¢ÿ;Ø4™,l«ýþ=e�;s7Ìq3!žG÷§£M“©·Í~›$êjË&û8qCéÝ`cÓË1 V8ÖZíµz™GâüiŸÚúd)ëbW§rý'q‚›dò\c �‹� ÿ»ƒâ±ã«ÿ28Ùqc&¿t‡ÃqÇK�49“s˜»4Ù>»û]J¦½_¸?%ózÒwðaó=é÷oY uWƶåÕmI™,ÆØöAáÂä8޼ëÚ²_¶ˆÁyajþ›ŠÏir‚¸ôÛKUÙÞV2Åè÷ëÁÁÁ3YWãÔgÛ#8Æ “ó"äŸ u% “£ilo“&›Ãà©¢œÕ^»™û´‰ìÍ«ü•3fŽ›‹óÜ“½Oñ3ãÿš{Þ0Èä œxc&{ßñ/ÿr‡wãLîî°Îz^Þ4¬/)ÓÖç8ý4ÍX7HÙ?ç„–Ìæ )æN2M^N›ÉÒäÁÂäd¡”4y<ÙøhYYY|o3&Sx=%Èa•UrË''𴽟OV€7¬="8ŒžúØÕdZï¬aò&1}]—ÉmiìLhU[êMPôÆŸ½7Íd±ðÕÿÆyw6y ê3Ù¨úïÿ–·ƒ2Yúx¿Óäé õ´YU1î ä:i[|YÙ%é^KY�ñ>ÉÕúM΋˜ÄÝæÁ›ØèDî]s„=;ƒÓ�„ˆaÞow7¨'ðrt;e’QÓd…c0­£6qLöˆˆc=ã6ñTx[Ód{?1b,æ® s'œí••Mû$ÆÉS`2¸™&/‘&Ëî žðkÞ;§´×þËèE‰Ñ×or�¯n849Qñ9�¥Ä9L“m㕽<¦åŸþJ؆Ï~½_ƒïðlRŠ.lSº¿?[ɶ�æmšm%W÷®)ÒNü¬Ÿò��ÍOÃá¶Ê´‹g•…y_ÄQ”ÆýJQðqeuÓwÆß¾ï4™$-:òIG%¦‡׿8õâ§*oñ+Õõ÷mŠi2÷ï…ÉmÃv渘,ÛK#†˜6í¨‡/LަÅlÚµDåÌÀžòÞ3Íj²QUUå^õ”±#èÿ;NzÝžŠ62þÅÛxð)ï˜ñz)Ç…—4Y|3ä w¨£å\6�$åO%_QÂäc–ý©sk?ËYssÔ\© N!½»ÃLN�-LžÄ‚ÙÞ£$ê6O� 5�­“_™M— "i YžÖZí¯Xß ™m™l,å²”Y”‰£‘4g]ï0~T7ö7ޝUm¥É‰âÆsši²*ÚkaíýG�€î¼k=(ñÑ-8 As›,¿£°cäÿòÏÑw¼D'è¸hc�owÜ@LnòoPì¸l>©åp­€EqøÔåšy—ÔýuG×dù�®%fA«îS—?®½Õzÿý©¿ôë–ô—…O]¡²Ããsx„=·ö†j½,ºêƒ�Ëu5ô In‚ÉÕü÷ËïYÒ ¿û¯ÿþI~ªGD­¯Mø+×Ñ¥p¼ðf¼åë®Û—¯hÕ¿¡ºà˜|{üVc�€Ñ5=¯ã«�¶� oÎרºŒQתëß�ýø2œlàçk2&“a20&“0˜Ü|&7ö o0€ŸÒ䆞ðÖØ§®Âd~B“|ê*ž„@kx: E“€É˜ €É˜ LÀdLÀd`2&`2&“0“0˜ €É€ŸÚäè _ns‚¢09úAU€Ûœ _D_Ûä ˆ @KP9èÚ&ÿ‡€–À/`20“0“€É˜ €É˜ LÀdLÀd`2 uš<ú­˜˜·FãÐÐ’M¾7&Es/-Öä{HIùaÕ*þ)UîTЕÙwuÕ�º^óŽßHXo îxmÞÐè¼GÍýnD‘[ÄË‘ [d{¾ÝòíÑ4Þ±]kä=Ây;-Ú°¯®}ÉÌ=:Àu\X´!ȹ§Î2Gø@‹†uº—¡2’}ºf˦ЪoWL»d92âª�]èºÅÌy@®üVn÷@×}ߎ¾êw’õÒ®Ñ��¶À—Öc2G䪪~à¨,^ô‘1z€óp›$ß¼˜2òZ[îûìu4w–OfCuûì­±Ü3%å…F_ îþÞ*ôDƒy'ü†vÖ4-¼ÊOIˇ´§ªªÞÕVSú!͵‚±5¡¸œ²»úŠ&“Çjr�Þ¥: (E[lîN®sOŸÑ¸>buл2Ai~fu·'WÓöšžª½5*™-sÒ†ü&,¦Ôßnm'óÚ9£V”káÂØÝi‹9r~;ZuH#‰;uîãÚ¤ ¤ 9¶ì¡«Ü²’Çj'Í ô‰æ»¯¸»Y�_¹‹ÉÉݺ=<�4}F½hÑ–*:ðݺѕ#Ûi2]R㺯’ž¨Ãäp™“6ÄuÓösÎÇ;u~£vLÞgmœÂõ3ÚÂn±ÚHÓJL~K˜üƒ9å-ÓdáË¿gWÅîOùa„_Òî”3™CÖ—¤¬J ¬ê¿;%.Ó/`ŠŒÕ¿OJIá·e»SŠÊ„É�†øò�I~Oß�’2±ªª„*™Rå—T@WŒ*³‚ªíq%ôš½Ö'åÌz±Õ¤ÀYgzSÖe¦ )5™^÷rÌþ;•‹«Z�’²Nö¨9î^å–’É/ ’UQ*+rÄû¤ì¦F}B«ç³É%>)q%)™Û| |ÂýܨŒlð™eÖ‹09®ˆƒ™_ù1yÊ{v:t̯{8Å/_ dÁåÇ:ò¥0&ú'‡úL óÆj�ï–/¤”y¿84i…¦ v&�Õbâ´y�TñÏpØäžñÑ8mõÓ$“_!å 2Åô#Ç}ïz•xªÊ¼ �Ÿ2 Çú:M¦FøÒe©w¹æ»ÂWDóÅ"gTÜßiƒ¾UŸä®z1·_|d{‹Ë§QÞdŠÂ�l²Ÿ'µuaÕ¡Õ¼·�ØVbrŒÙ«*ÇT›<‹bò¶”†ú¤<çæ“RDVþÐÕgdÕ�”¢¡)Ïvº›¬�•²pÖI) ;¹¥ÄlöI‘&ó* ã~´¼3 å‹m)q›RöÒ¢x5+êK–•¥„oKJ93Qnu$õšcâ}žåÞséžÙ3å$ÇÒ¿'íþ¡pÖîg7»¥ æœÛRR<»Ò îï))CÝRúTqUn\v÷³fÌ.¢-=á�2?>%%¼j{Ê;Iê̾|­ H)tKñ¥V’ïÙæ‹y,:s�Y[ïÉþÑ)ß©ó �:¯®zQ{ŽV¼Kaº³¶ú’'ë¾–z®á¬§<muÄcµyOw§×±Ú€ °Ÿá m(Ê�7�sëLþ;ÛK-YG Ȥ}âÿ&ð®¼@Á>|t¡Õå­Âdkœlš¼_Ž“ýúð 5¼ŠâZ§»iÜLÝÜY)ÇØ®“ÛR’É�ì!ÿÄêÎ"_h|íjr¸Ÿ��}oß”@¸~>¾¬k«‚¾¬éÝÏ:{×TwO6u{Ê=Sr–I¦É™~›EÚ�)"ëög¹�O��ɬ-mao•¨¾ï³Î5ÛÆÅ³RÂýDƒØäItämüíîg³«fÅÉ—l«[.:«óæ—k�Âäp’"{­–MƒPzCZg³Ù/æyŨ–‚)Ár�ä¥_÷7¬ä±ìü3Úl2©ä©½Ðé>ޝ‡´‘²ÿû„iò3«ýʵ‰›sEô=$FÞcÍ3}<ìö ´L.àq�ö· }‚hkìïÉbÚ’0ù‰?–Ÿ4‡úܳ°Ú;V£Èû;í˜0yÊ-Pìª_.oãäÖÕ»6M6{×ÏîO9IaôÌ™3€Ã¥ŸÂ6‘þ¢Ï±NwO~ðRJlÊbSaW“ë¤û))…[ÌÁî�g­ ú²Á}ŸuŽ_EÝ{ÅÌ”H¢ªM>I Ôœãq®¼ÓÝ<ð|q÷I®ÊÏgaõ@ýèP‚³ù²D áñvNx‚ħ­ûð•(åÌü *ó¥†Éßsì 7M.Öú^„ÕïåzòÔzOú XÔ™-)ÐD\Íu¼`%�•±õ)aòbVŠ rå#ŸÑæÅù–ó«0ùÐêNïãš…£ßËÑï±E6,âpUÕÀÞÈ“M“EOÝt^-&ÖhT.M6‡ÁQ¹¤¹³½Ô‚'x’‹÷ɯ»¸öÐ*jÏ”�+´`L+šñú�Fp#~p™ñ‘ÙW*=ô’4ùÓ¶8NÑÉíÙSö’É´T¸¢'G:ÒÔiòœ&Wù•ðXZšÜ÷Y«‚¾¬km“¥¹"L[&o“&WuŠ¥Z|«MiNÄÑJ®Jä1c²[ʳÔqÏìKýîRøù}òL^M=onñ–ªâ¡Ôõ´^\M>)Þ™&ûu<ái³¾ûãUri¬ÖUÓâÊs5_/–د<\ÌAŸ´Lk&‹I+’Hô®EAir³nÝ´ifLîD½ãnb¼ÌWŽÕÙÒdkœ|HLޝÕFv>hšÌWžnb„k™L#íÍ®&û•‹ék³½Ô‚/¬}ò+ïS¨�” ÂèÕÊ­è.Ô뉬»PÒdÒ/€Í‰Ÿ(M¶",ž?º%S·Õí߃Èg–dÚ,ê·V‰^,‹ô,GJ§ÉÛÖ™>…³àÏZT›üÅÕ&Ÿ5Ìâ=Dö®gyR7~ȳÕ&Ÿäs6º·–É/ú SâÛ¹ø,î]³GnÒäí)Ôƒ}Ñ3¨ŒZñû”‘æ‹‹ÉB‚Ë-“¹£(~>eN_ÒF¯˜6mZùêõïZ&SŸ }a™ü»«L&û¾à‚›³ÙÆ‘b듘l_©?ý.w·‹µÇ)d>aÎH›s×´é/D _Xþ‚¸ õ g]«=ÇSá²w=RôóûH“OJ“ÅGh¶÷ qYx1÷ 9Nî$ÚJ;øLnU&ß+§­Sœß 1ç®I›¾)ëŧ$©Ÿ2M&}ÞzØ�‡¾)b8:oCìî>”zéá»S¬ §·¾¥•–É\I ‰½?eý"7®LVPm²ì4W›L½ë”U^4N÷™·!>%å ?Ÿ¸®Ê7¬ ¨a2e}¶k‰˜<«a2u%¨M) _ôI麖[)wCš,ÿ=èî”§)í¤ùâb2™sðaOm±i2¹ÃçºøI«ÂGo–½_ž#íVQÖ“~´ìbí{gïÚLþ�4™û¶ÅZŸ ½©à»ÚPWWC2w3³¸VÔíê¦tª#Í,&ÖX­ïváêzj¾Ô(}¯evÍé ¶´Vöú¶ïš<–»Ò�î•IÖk%»Õ{@ ë: h@j`§Í|o~ µ7TWKÆjÙÖ>Õ:|ð¸u™|+à9ªFÒˆ/VÞ’{Öú&fm³…Ôì›Ñ¼CÚàÞžÚÉÆl¨.ÅL¾N/’’›uV\Ðíaòºšft:tòzLöpSš×is¹6o@£6Tì‹Ø “0“€É0˜ €É˜ €ÉÀdLÀdL&`2&®Ïä üª*-€  k›ý ¨ Àí/ò/¢¯m²ô ÀmNPm‘¯2Ð�ÉÀdLÀdL&`2&`20“0“€É˜ €É˜ LÀdÀOmrÅÅ6€Ûœ‹ ˜\Ñ¿ÿ(ÀmNÿþ×6ùâ¨W{ns^uñÚ&·yõr%à6çò«m0¹·?½`20“0“€É˜ €É€3ù«õ1¾LÌÄà¸ÐRM~mžfáëTyø·œU=òZ¶;üaó͇¿[±¢÷WµW?Ò  7ÅäuÚ¼õS˜Iš6ÑJüNësÞR²óoš°Ý×µ ñº«»¦åjÚÇ',kb]€Æ›ü�¦­£þP¹æ+M~H ”BO¹WhZLY=Ï÷¯‡V~ø e[F!ºkg�/"f%€5ùA*ûV›üá}}*i9d›¶þM ]Û[Yyhõ_;kë7—¯>§¦­?¤½Aºöéí©�ÜÓY›H{�çÑ¢0ùÃûVŸ¯4_)÷¥CZŸÏŠrç­ÿë}/Pž›»kË(j÷é=A z]ó¥—eøÄ¸a“+iÚj—˜ÜE;YÉö>Ä¿®…ï™ð…×cûŸ¬¬¼“ݤäûúì™@ºî™ðÆCZ2%k~¼øagÓdM³ïÔ‚îÔ2ù5yO÷ÅÜSs¬îsWw‰wÑ–ÑšÊ=�·ààÆM&‰ÅÓä;5ß+(ÊÞ©QzO÷ðÊï4÷×iàüáïVÄi}Èä 6ú.ÑçÜqqqåÚ*±øP͘|ˆ¼ç·Ãs÷/ßË&¿.†Îß­þC÷7Øè½]è"2ÿ>0šÃäË£+«MÞ3�§�5íÞ;5w^ §Øø]ŸóÔÙöíÝyuµÉ�Sæo*îÔÖÍŸ?Å‹bQšLêÉš,“Ë-“»hÙ•²t¸H®þ uÉâàÆLžç¼U´Þœ»Ãb²÷ØC<~åîð‡�ç‘§¯ó4Ö�N“èþ=ߣúþ!vsW‘ß¾quH*,úÐìõã•"÷ëÚsÃËÍÞõ16¼�eòCëøU8>1nÌämÞˆ ̪yÚz9MÅ¡˜¯«ï*×6<2�¥|ˆg²^×yFÓ¶˜&ŸÿN›|H;9¼ûjÎåN±™WÉnµæ»(ê�¶:‡L^½èwåšûðrß d2ÕþVqgmápar÷½wj“ŽäÂdnÐä�ίxióÄw²†óVŒ“Ow×4_VnWù BOM£ñ³èAßÙç¼Xžt¾’s­-Wšß ùð®0&G £iõ–Ê¿ÓVÿõ¾ðÊá�iÅÑi§MŠR|K p#&WŒ‘ßל·®Ž¯eþåKץ˕•£\¾�ýM…\øRæú¦Ãy—üçE±’‚÷7¿ªQç—_Öø‚w¯/_ÅçÀ ›|“¹sõy|´x“š„O€–o2&“a20“0“€É˜ ¸µ&_„É´“/^ÛäŠþ—q�¸Ý¹Ü¿âÚ&Ûns.Öù*“-˜ LÀdLÀd`2&`2&“0“0˜ €É˜ €ÉÀdLÀäkp¥CðmC‡+8yL¾>‘ƒ{í¸]Ú²£W0T0ùºèÐëvjM¯8{L¾‚wÜN­ÙŒ³Àäë2Í&Ãd“¡L0&“a20&˜ “a2€É0˜ “€É0Àd˜ “A+4ùtソº=Õ9}&Ð(“m÷iZ®¦«NéRžsU.û¡ƒµR·@ûÛ/G×ÛîñÉ0Àd§,÷i«ÆÒCÚÈj“5÷«²¥Þ÷B­b�?ÿLÜ:©¼ùî´gÜÊùP\̪¤Ðw"ËnïìmPõqë)ÃðCq—¢�¥+V¬˜æ}ßâÆ˜<ȧ^“="k-gÛúæ{Ê “¿‚JÎ ý�®¼ØcŠH=.ÜOð¤5fV™!5+?iŸG„;L-×ä.2“ÐÞÍ#é^÷ý´\‹;Ø¥ûŠîšo�aëL±ØÖy´g®—sÚSÓ&ÉXÜeõû÷i];¯Ž–eù]mp,]Ò&Ò²ia³nØÿó�6—lîÓÕsu´­{Ÿ‚òßÐ/m^áÝeutãLžþ¿�Pöï3¦ÿ¹,B9D¯äcâŸý~TNxFÏ|S ›/+šêkVð£âg¶EøþJÑvå¤ñMψÁ”ø—v ¹¿äô�tu0³š6);;*Ùm}a2h¹&?D¦™¯âí�«ç©ùŽèBÎöÎÕrlÝß �ZþÜ¡rmÚ]¹}z²Äc¸ö„‘—ËqÑ|÷Ý÷Tº�mÂãdîwö¡‹‚æMÕP€ç Ÿ Í¥e~{§ˆîö ‹g²¿BºEˆ×ÂíJ˜»?ûè6+TÙ¿"Añ‰}O9(Cò J¦‘§pÜMæmsŸG‚û¼?HQÖq…K¶U2ÙÌ*3ØÆ¤~üà„0w˜ Z¼É]´À‡¸WýÐjGaÜH¯…ɶòÅÆ}oÐâBÃøn€¤–Ïå\vÑG–ª÷”“Jw¾pçoÌ^:å4–¼Fýë>ÑwöqðâwZù<ê…sŽÆ™<É06±Á´õ•ÊÓdw[D²q˜Óޝâ¬þ/G“»d$·¨mw‡áñk÷·�‰tZ—£îÅfNCf}NfØC5Qs5L-Òä;ÍA±ˆÉ–É2Œrl•&w_LAذMдiå8Tsï²ÚÁ¡Yô´Å;¶º‹æW.*yH½´³e2§k¿18ÛÊŸëÜgÑ3ÚbÊÝH““…¹þ2)tZ&ó8Ù6^ +”-J#“_æn3w¤Ù\�ˆeoËœu™,²®“ü~MY–¿üþ p˜ Z¬É¯k2}§¹ “¿ëãbò}o,e“ór…Ɇýw…šö‚9)&#ñHgLyßã2&g“É¿±Ò4_÷ÒdÃøT[|ç÷bq‡œ?cÿgràÕ&÷�&öžc%†³¶¥Q/õ©íoŸäê5{ü:èí…õÅd3«Ì°'‚š¼Ü×Ì“A‹4ÙÖ½�·°ñ{ ËÞ<9eö®Ùà7lÞ¶³É»Š(�}'B©0y.EiÙ»æwÏÝ÷ÿq0ÞÓ�’î{a×k; T�0ùuêVÛ;/æ(œ uz†R¿{¡ 1Ù4™_”I‰£§²ÉÉFbµh¶˜äÚÄóWÔŽñ‹å‚‘æÎAvSÝ&‹¬ÏÉ {"(}vxêl˜ Z®É¤éê m 4-ˆŒœtä�Ö'š^RwxÃg�µLû}«�Íe“ûtí¢ùˆš B)ùi›þ>uÉm‡ö™ïÒö-�ðõœ.Úâ×i¡ó÷2'U<€2$ר‘êáçOó÷÷�'¯tš¶á³•L�ˆ¸í”0÷¼ˆ3‹ü•3f�&“Ÿ¶ñ1ï· sOèì�¨¬bÁÓÂöå�7ê0ÙÌjf˜í“³RYlû L-×dãõîš¦Í âohZŸÂ>[gí²–RGPÀÍ¥Áqn2 Ï®R†}B êVóšÆÒòÅæ;QÜÛXJ£éÁsÁì]ßIòX\Óö]Êù^Vªb7 NêlŸèD§ÉùŠF-jG/c†¹§Þ¯¼Mï•GE‹<¨‹¼’–ˆ‘1çÙGáZQ|¼ë2ÙÌjfȯ(불§`2hÁ&FEÿ­òÍÿuþ­vêaŸzU¾}ÿãêœK¬ Üa6–8GºòÝ©wä‚(pê²ËvÈ5;–8sç™sæ�VÇ?ÌÛ¬rÇ)—öe«uSyªë²µf‡Ìzjk½õɬfnò“W}Ÿ &ƒ–ert©K4×~o]·ƒ›Âw/M4Yq¿f…Wßnöñ‹ ˜ Z›É»b¢¯�aék7Ö¬àè&šœèÙ@‹våܘÉÁL­ÎäŸüV#0&˜ u`2€É0˜ “€É0Àd˜ “L†ÉÀd˜ L†É&Ãd˜ `2Là609øvfÔíuèFðÓÑ‚c2 5ô®0˜ €É˜ €ÉÀdLÀdL&`2&`20“0“0˜ €É˜ €É´r“íc‹™EÑ •³�Í©{ÅÒ#u&ŸÎ1NWÕ¹¦Kì@3CsbÄÚ…¥GßXMcspš€–fr^ˆ.˜k%¤Å9®*cŸiäéáuWxXw¯£¬}ã÷©_¨+¿¿.j¢ õ¶±®64Dž¾Ø¹�À-¿þšh1&{„ÄŒ{‡p&,Ÿ\‡É!�”qpÝúGº×Uöôk©íëtù+Þf†zÛXWŽÉ9N““k´¼©\O~r“¥ ©³××õi޳º–i$þ¨§¯2lýFÏfMÆëJœGÈî÷ôôTâ#]/4û¯Y ô3Û(‹Ì/ËfEèé…Ñ©°Éyïéú©˜ýìýëÑ©³Óõ_³iœÁÜfêì3Tõ%z¥Xœ:uЍÇN«¾Þ'bäøܾ8Ç=oê‘´å´at)Hëβ÷xÙÛHüõ2Z³'t7'l™\ô£þ¨(*Zî�[v¶˜²Ø~t¯‡m�Ë�n1¿þ}ˆ(2s¼¾¦&ƒ“{�5ª"µ½ûžžL'}Ò¾=½äG}¯õ¼}ÈšÄPýÑ´°;vA¤»m£>ô=ÝWÞ¤ï.øQ�t—ùˆ²‡õ3ïé�¤1ýgß¹ó¸ž+"ìlýÌö=3K�LbËD¹Mz]ÛO?–Ú~r4§‹z¦êC·‡ˆðmßø'‡‘ /LÔ#7¿G•-ç«‹ Û‡)ün¢Æx„ôYÜC?»@Ϥî{Ñö±^´Üan™af¡�á×d#Mß]¢g[Eõô�u&ƒh²&¿ò~{òÃrL(rŽ J=7Ù#äw³¿™Ls£�D=9�•Ø$zÔ¶�dž� šù\¶-¥y„˜&ç…ø:Œ´iB*=†Gå¹³ë,2Èm¦¶_CåÛ¿âÝžVq$§,vNKœà-/si‹Þç"ƒ £­žéb²�zçô5Ñþú\Úærjš-tŸ¿>‰[èmµÜ¹eî·Ë,!¾¼ë¹¶�¹¼áV‘s\õý0´D“ãÚÿ#ÕÅ"Š‘ù'òõH¿�p+“9N¶±.'æä‡ˆ“�"¡!¬6ó» ½†oÕ­˜œzN×68äè5›~N�íj²Ü¦P¦zªÛ@ÑRßßû¼9+w0µý<úOLGº˜lœ›lÛ¸SŸ»|r4µ1Q×× ­’ãdsôÎ-wnY\ODÑ�ž:yOHdþ‰ÇôÉ+Í"íY÷é0´àqr “#ÝÜÜâ7ï Yìjr¸x³\§ueñU"y!ýL#d~!é&Ën·L6ŒÓCBô5ÞÂä¹r.«.“ß�3g¼lß(M6†÷] GfÒ×<˦“§ÊZGΊüãÆí�‰6.Ýö¦®s×5Lž[=‹&³H“—“Ék¸å½­"âb‘“A+1ùÜŠ_3æ{XS?¢w-Mæ®®‘ÐÙ[ô®9„Q�ÔÌï½bJ£üÒdÛÝAVW|º~�K|P§ÉPÒTªg2ˆ‹6ÁNÉK‰¿þæ+ѩ܇§P�ÌgûFYK^HúdÇT�úÌÔ´Ó¨…ÜUv59¹z˳ȹe1NY6vl­+ó;ïÔ­�“—|,Þ~<®:ù”3{ê9)VªYÙÿW_³ßù¸ž;jdñyÊX"“NõªQdG¯�qŽ€Öcò-¥ž/ƒ9y}LsÒ#_È0¹ÙMî¸ìšë7é󛹯k �‹3ÀdLÀdL&`2&`20“0“€É˜ €É˜ ÀÏÒäÓâQ�Å^M<ái¯­u¦ÛÇzåÈ'@¾†¿…u}œöâgfíòz­ÙjÜ/Ÿ�Ù˜O°u�úéØ×~F&ÛÛËG5êáM©ÃÖïëûÆzþ$Oÿ9=ùd‹È-°òzÎÁöºøãüúäèfªð~ñqÌ«ye­ñ òGÚºŽb¢®¿Òèã—z6,³e›œÚñ?T]OWó§4Éä�Hoãõ’º�ì¢Òÿ�ªtòdÃËë2YŸÇƒ¸¹þT/?öªà=½ö¥×õi«‚¯^ÉM8äÉ-Ûd¹ƒé’ì9kA®#ë±ôôý[Œ´9›ßKOŸh¼ì™cØ·ÿZOO¢köÌÇÒʼ~Ôõ9Ïd©Yéa—ÕªMNæ?V¯S•nàfÓMÖÉäÉÍfrä\#u¶rаWÒ¿Þ`$ΙŸ2‰>A[hRßégräGÚš¢øóϾšÿ\ØWIkæ‚ôýtÝþQzú™}†-ÔÇ›‚çûÇ÷Çþ˜>l ÿñäEŽÖ`²xÐÛä4ÚŸ~¾“ìqgÖõüêã�£WZí8,’'¯äŸƒÛÓÉföÚ «€‹ÉâÁKúä÷Û7­ãL“_ñnN“ù![:S‹ýÅ€ª½ø ˜5ò#mMñ°¾f›Ný ÝÉŸ rw3=BhøâOg¶<¯ü�Ó?h-&GnxmSúz#�Ln«¯©¢�\NïóB=½g‡ñóIÙÊòh~dæÑ� b�”gŠÑƒ¬µL¦sñýsüDÐD“»nÔ�mj6“Íqònoº'§žÓséôþàHŽ49ƘA©ü‘¶ªcxN·…è{Ùä½õÜèMt2OÕ×äØÚë¹–É⌞A+ìí[Þ#„ê5™÷ätß7uar 'r N/Ì1R{yŒbññâo*¦Éþ9ø:h¸Úähˆy=&?E‡~A³™l>ØNŸ·\Ï5ŒS£¶úó”Zª0™ûÝíùYÙ­ËdŠ+“>'�þúšhqŠO×ù¡¢9Zó3:-“÷ò�{j+2Y>9X#L,żg? æ�ÔÙÿ¦Øÿ¹†±äU“×D‹ŒÎ5ÆÉä8¯t}&òój›ËäÔŽù{IæAúäåô=ŠÉ!ú™¾<#@ºý!ú+Ñ|»xŠ8èhMŽ®ÃdÁܱÁŒ×õ˜L'Z³™<�GIôÿA9¦S7{¯«É<©é->ÒÖs§Ë;P³y.ÏÅdJ~”ö1ŤHžÃušÌS�ó­Ædƒg0Ýì,ŸÓÅ“ #GíD:]¹ÎÒ›G÷üNë Û{”à“cXL““¥Éé—¢eíà:L¦³­ÙÆ&3ðçq‰†�üf½Cö®Ï “óÅ7xÄGÚzár÷ñ�X/àÞõ9Ódc�W®±l/ñâ×S^sùU¯š%Nym­Yâê ©Ü„#÷Î7¯Ê7K^u½<ÐÜ{É«­ø^õOžÐt"×Z³cGËî]ëºqóÿ�&¡ßº#×Ú&ºnè´náã䨛þÜ1¹¾™¡ØØèV}[ñiZËdU5nþ?Ð$ª?º>„�ÿ§¶l“-˜ LÀdLÀdZ·É•Á^à–\ÙÐgÔÄϤÙ+üùŸ …Ímr¥WppK öjàSnêgÒìþüá­oa³›|±Cp ép18øÚ&M¡QþüáíÝÂf7ÙëbÿQà2ªÿE¯kDMüLš½ÂŸß!ü ZÈŒóõõØl&Cä[ÿ)7tvhÚg2ªCC¶¶¹áCøSïqƒ-d¶jš6¢ùL†Z·š†Mnb… ›ü³;„ýo÷Âd˜ “a2L†É0ùöháÖ¯¾új ™<‘^4Ó>þÊb+L†É0¹E˜D6æ´ÈþÏÚ'dSM>]½U«AæùW½»Ÿ›YN×XMG¥Âõµ¹LþjôèÑ#ÈÙIôjÝS~p´E·f2ùž…¸·vª"ˆ¡·ibe[^ô­]ø®A”êÓ©¢Ëxz]wUÝ=¸ÐÄŠŠ,z íZÉÔ—éÐýò8—îV1ƒ6t×PT}FRÂî5‹Q _~Ðz/²=ÈEå’™÷m_™Çe£Š2à�÷dÛêl#mW?Z>ó`ÅL>ë+*Îò¶X»?€_Îò 7rؾš;6õå{[lÅçA37Âjûøë6y:·eJó™l ç'`R½OSÍÃv×xzSëCèázZðºuçq$Ì#Y«õV²•U4%Œ«œA'–ó€=Б’¿¾·â.Î÷+óÌ»n“ÍjjÎê½7w÷�ñ¾æç|²¢zµy::_[ØÜõJ¥kTTÔƒµRx×Ë«x�²á—ÛÆˆƒÿËAqQQ®WXÉýÊÓÿÖNY÷ÀÛa>兀¨íùxŸ�Ÿ »÷žŸ�3#^~Ъ䮾o Ò”ùÿ–¥Lªh;¬SÅlªá¸²ÌY4b}Åt%îÂÌŸ_¦dóýog‡u¥l ïÿè¢Oú™Þý²_LÅáꢻ¨é³"†uk§\¢Ú×ÕÝÆ¶/?ØV™x± ßoØ¢Ï;†Ý»R)º0‹¶fn~€84ä@šRt±g„OÍDÅ?=êõðýÊ[V¶ú –«º”E(×kòƒ¨�ƒÂö5›ÉÖ±°¥™lí“õAÐ1œÍoj}3‚\Â{¿˜G��’YÜ:’µZo&;#ïQ/¯,%îA>/ècq°J!5&F|NÇ©yæ]·Éf5®‡Ó:ÿ¬öòGÄ—ôžCø“«°V÷PŠè„‰©°^[ŒÉ3ÞT”€{+Ò†uúRìv_EI"g·=¦(…ÊC<€Âfé›ÿ?{çÕuæñ•Éb{{b@cÊ: 8ŽðØcb1æ1¶¹j têG¬„ƒM�-…�H �XÙ(‹w‘‰S°ÊDÑ:¸P¨h͏›…H�K²d#+¬°qÖŠ,ÔHé 岺ÙÜý¾ó¸3vŒº˜?øÿˆrîó̹ß9¿{ιs­a“#¡Z[¦wW ñ‡]‘Ü–Üô×rë§-ÝÎŽï2G­å8¥øJ³D%·ž=&“¢?e5"�L›Yâ¿f‡(r§èx•1uf²àvÝYgņ�z9HŸÁÄE“‡çAáÛ�[,�±·ùå‡s#¢öÔ@·_:ô[e,¢>`_ª·±Z}CXT¾ÆP€¶-Ü*¢‡Øä¢Ð*Jªù“é"Ì•›Ó¥ïí¶9,ˆRQ^è±ëæ·É²ŒAÅ$qžÌ±Ðá³#ËÏ ß—î5éŠ <¾>ÛT‚n aq”"Jâê(»Q>Hûç˜z´u$ÝÒë–¥7»-‹Õ’ŸÖà½Z÷ü±ÜYO‘%¦å�ÓäÄlL�Lû3åå*âšÛv_/ßÙÍn•'ÊÒL:ULú£‡– ¾ªSƒXµ\\I«õÉ@FB™ò~ŠM–cp/y¯vS·b‘¿k¿²¤ì€´$”ù~ƒ˜¹×ï{Ûd2`ð­Ÿ=àÚ1™¨N�Nè\-¢U4¸ñ­ªè‰|”ë{[g\wT_ð.¾§ÉÏ£­z9¶ãaÎigÑJüxĺ»¯ k;SU/Ž?âÜc¬¥ŽÞŽ Æ>Lå>w¬2Ò½™:¦î>T5ˆÖõW¯¤ÙÃö…ªà05ÚÕò^ÝÐUdL¦�Ò×3§s‹”µ­£é@ôP¯½çŽ×ä07,y·JžÉ‹˜Uö¾C[}¥æštEðA‹yAW‚i 4˜Þ·ˆ†d&ʉQ_¤B Oב4¥7-+`™› ðGÖûJÅñ€µø½›. º´ÕMË�É Ù¸á4íϽ\ª¢âøØËì–'ÑŠI“kò™�yy·Ää0ÕXäDqä„XÑ‹[xªH—“B—”cK�f…ùš²„÷g©TyzwÐÿ¢¼7ˆYÄ¡²‡iÒë­ã–Ü"ÊÝL(wÚäa½hÝdb«Û8‰]vl+ÍcRºzä°ˆv™Œ‹ü¿ä©òŒ>Qb·øîw—‰:™ ò6‘Ù(oõÜ|÷“¥¬j1Õ 5KNËF•±…ËHªF9!+kTsÉýl <ÖÀ—[-‡Õ•\ÑñdM¥M`ÜÓùBwÊÖY©L¦¶ ðGnÂä§ùôdš,caÂ!ƒì,_©¹&]²“ ªL[ó3Kìt£œu�lêò,ISzݲÌf“›¼�öðѵ<r‘Oö…JL~žøÿ†MNÈÆ §iî7Ær£ÙÝG��[»I“krrÿjD%¿Ù±š§ �–÷­,mkÛJwÒó‹*ìzZ%¯i躺KTEzwdÇŒ­Tçò‘éR¯ÿd™*0™Øë{Å?š›ž›‰1™ê’>¦Q…w¨°Ÿ§O*c ,5¿-6‹Ep—íØ%õ삹Þ4Õaò�9̳q_[[ß(Öê[±;„·g¬2R'µ? Z?ìóè´Ùõq�Ûú}¥¹ÜÚäb'åüKõ…××dN§7¨ÁŠ:Lµ�z9·ÉY*ðÉ4YÆ"¾5Çz¹“5פ›6‡QÝNe%˜¶ kžœt£œu=+íâY’Ф[zÕ²â›uË¢›A9G'S>Ùp–": ;D—ŠÈÎÔmyãë“‹Ý>Ù(¡OËäÛÓ'ß:“iè´ê]6o‹ºÂâøŒ3Žíò�¨óþZ;nrŒcKS$½›æ±÷Êå¨w<²‰G,çöî> ‰�móóÍQ»ÓäpÇ£BUn2qMnWKô_ð©€÷‚ÎXšÌš¥MÖËÔ<:ÓÔ÷/i‹œÿqã‘&Gù ZùQ »ÞÁSæjúè±ÊØ@óæù‰òÆMõÿ«dÝ—ó`œºÛÅÕ"ºá¬OÚ±�Ì^Èý˜¼&s:OåÝ_¦àdÝœÉ-²éùÛ“h²Œ…¾>]‘Ê÷CuMñÁQÛ!®tëJ0mÁ˜ìF91êö==îé*’uºôºeŬrÓ#ñ‡]Üoà.°šÆLFÁð¨§÷7Ø'ÇM6á4íïz}²ÞÝ  n˜b&WÓ5rbY�Ç>4$iá]´úî’‚þrõ $nòjfµGï–=Sµ·Ç“)‡f‘¾�rÔ*u�ªäÕš°~òe21÷r¾ðÿØd®½È‰L“1‡¸ZŽs¥Éîrƒzø\º"-Ça<à ólŽ¿Y询z4#F.÷œ±ÊH·ý žlhYÚdY8šÈT!×Qó[-Ž?æõBúšÌéÜà^ä±¾>,ï¦Ço²ì÷F>î¹I“U,LøðM‚ï�úštE-?6ãX¯oÆ] º-¨‰/uê&Ê&ê)¼^ïÖ£‰¤)½iYzsX禮Î~s9EÌ}á}0YÂjÕÊCRF=¼¿±'^n6ñpšöw“Ín>‚G[&�2&‹Öõ}ÂûÝ¢uM.?’ë¹¾Ù C¢³'â^Š4¹^x7íÞýzw–èìî§a®Gì+L¥@ðS£õ˜'|¬Ï¥ª:Š†Ï»(­, ùvÑüªGgÒŸuv§’´Bg¶þ®OÔšŒ9Ä-t¸‡Nãèeš îX¹råÃt§ƒA’4™çÐØ°ÖÔ#­þ[?M€G—‘/4@¥ˆèÓ©yúf¯Ïåõââ3¢,�&ó›:ÔÔ@›×Òv�(Žèkzßœžp×–£ë€()¼$çÛã7™Ë¸#TVš<“u,âáãk«Ò×dÇ›6? ê1• ÛBeXPh®Š e7êâÊ ý]¦c:’¦ôºe¥éÍ&·Ä[”œ'ë€yÄÌnnÔÞë£{Dd´D7ö-”ɦA>"‘2íï:&›Ý¤÷úE�mÒ©b2¿íÿÌUÏ®eÚj‡iV¹êª(e2H½Ä¡w÷ÑÌs†˜'¿Õ‡Nî¥uͯR:Û=*‹Rõ\¼-u3áv#ŸQòWðûmߨéLñTODg,C¼MÞÂPËaý¦ƒÇ¼eÀ9÷·Ëcdaö™Q»üºHÌL³¿UFºÐh¯·ñÍ>õ’I]H€ß ‰îQ…<ª&üAÿµ^Òè^“9=Ád>,ˆÒÓd·0n“9s_yßÖÔ±0¡äk™Aêk2!xÌ¡*Ám b~¼þ(ÊnÔ¹^£{ÜÓM$uéMËJÜL¹éñ­©&°ˆ~CÖÓSöÍš¬³‰¨œ&œ¦ý¹—+ý¹ï $6Ï‹�ñtª<ñ²/Øö5ù�Z�/gÚ±A;vmŒâÆÔ‹xz÷ej�tµCÉ'Ûù#2Ö/�È$þ_<`ꓱzÙðp‹‡c¿ÆhrVÙ ŽÌ]•itôåņÍ~ý ƒ#R÷“‡¯%^¹{ú·¼ù÷®óÿÒ{Øã|ïZ‡ïòP�=t8~M£Ñ•à†Ê´�Ä(�±n"©KoZ–Ùlr»^ÀT:”ß“Œ÷®³1á]þ±Q,pD:ULø üÅí(!L†É0&Ãd˜ “a2€É0&˜ “a2L†É0&Ãd˜ “L†ÉSÀäìlüšÌm汿üód�Ml†w^o “nò×éÙè•oïÍúÿó“¡ù™á� (aÒMÆ/¡ã—ÐÂéðKè€) L&`2&`20“0“€É˜ €É˜ LÀdLÀd`2&`2&“'Œ9å55åsPLe“ÏÔäIjΠ:HŽÉç»%éÛo8£óé¯�¹}î™ã¦%×ycžf#T )&Ï�e)º‘<îͽ²}î«Ö�ÇÜùJŽÊñ®ë�M=òÆŠ×ÿ»œ{eÔÉ0y]êæ[Vóü¶Ú29§ ÃùÕ¡oÆÜywŽ�?¾7ãzsd2¸‚ªhse’4O^7ËZF½ìÌõû“¦m[››�ïqê7ìîkn®r^Ÿ¹Ý™»÷Ÿ­æU4¯ÛÚìëÌxôªem¨ºt߳κmþfß—Mñ”É/«Œ=~+ZO5ÜשׁpvÑB9*€$š|7‰¯·¬³9VÁ]Ï«ññ³§,«-Çz|ɧ”Òî¦Sróã-üÿe³¬NµÜ°Ñ1'h“ßÉÎ.<¼®An«4iÂàšho”}2†×$Ùä‚]‡_kÞé¸yßvgÝÂå[©/þ§îuÿd7Ý­Mþë­ ~h¶Àœ M.˜ß¶¡–N>{Ö²ÞZ¨ÓŒ„ÑuÞKííò 6F×$×ä‚»,ûVK“—)1ƒË©ƒ-ø�Y–u¼—M.ø‘ãN}ä‰ÿÖìvÓà/(H®É–åÜ®€ÛÔ'߀[hòüùÎíú¸u}2&`2&“00ÙLþ:;}z‘ý5*Üy&�žýWÓ‹ìt¨ î<“³³‡ïÉŸNÜ3œ��ZwœÉéÃù�ÙÓ‰Çò‡ÓQËàÎ3yš‰Ì*Ãdp'šlO7`2€É0˜ “€É0˜ “L†ÉL/“ßÜÜÝh–/tŸ–éùîßpÙÜ}X®Ç6ËCÎ¥«ÝÖÈ4V˜þ9'׈a˜ ÀDš¼Má«PËý´ì�cåRZÒc¯õSZË;êE©mxwšÓ‡}'Di»m‡)]�0€‰39è÷>\çWf‰ÎýÛD±]-Z÷÷‹Å‘€o×…€ïíXÇjá#“y³‡Ô­OÑa5‘´;U”Ûž²g O£O`MΕÜåîáåê²4Û~¢,-·„Ö'J‚~ê�ƒ¢*Ö´—LŽðæXÀ»?�IÇþî¹»È_l7”Ø—1O`BMNáÞ6,ó¬8àmä üír%Lý-õÙÅ´ëTÜä²ï†:W‹h•­Le¾Ïƒnß.˜ Àšìáî8èg“c}edrØw TÂtWXä+ úËf/ôcž ÀDšl‡iö-¥‰n;»*ÄEêpS)}Š:Ü\š—ÛÆd¹ùJùÍ�}�v°W=³æÊðì€ 5Ù¶Þ´ŒåÊt(¿Grψ#‡†õîkê�®�kê°Ëø>€‰6AL†ÉÀd˜ L†É&Ãd`2L&Ãd`2L0™ÉΞv¿&ƒ_xw É_§gO¯^9¿º îD“ñKèL “0“0˜ €É˜ €É˜ LÀdLÀd`2&`2&“0“7nòçóÞ¸Yæ}ް0±&þFÞÍóT`bMž—— æ!®L¨Éo$Åä7W`2&“a20&“0˜ “˜Þ&¿ô›Ã³ã«¿®èü–µ®Ø“˜Ì&¿ô‰Ü6änXêü÷¬=âœÏ{ù¹Âd&«É¿vþÔ™wd{\ߥλcôÉ­y/ÏÍ„ÉLV“—RwKÿÿÁÊ¥MPÚôîRç`“ó¿?Ë;ùÙo2œŸoºßq.gžÌø‚ºî|“˜¤&ir>ó¥Tz³Z/%uç8Îî“MÎÇ”:‡3œÍ'›6߯ùŸ/`2“Ôä¼ïF›~~:Áäsœ¾y²éãæ}â¬$×ÙdŒ®˜Ô&ÓTyË7Žs.n2M™_Ê:Ù4”—÷òº¿Î;iLÆ/&­É?–�¤�4 I“ÿ“M~7ÁdÒ&0ùM~ÙáçX^¢Lþ=›¼™¿vÃdŒ®˜´&ir—oùÌ9w²é¹ÙÏ:ò‰×éÅŸ9;ŽŒ2ùçð/`2“už¼t oËÎ{éï(Ù¾îÝ¥Îoi¡�»i2ùc×ä¥Mòû*˜ À¤49/oYí“_É÷?*Vªù ï]0ÕLÆ_P“0“€É0˜ “€É˜ Lfð oL“ñ««L“ñKèL “0“0˜ €É˜ €É˜ LÀdLÀd`2&`2àzüŸ{IÙV£êeIEND®B`‚././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1760000640.785611 trezor-0.20.2/docs/sign_tx-electrum1.png0000644000000000000000000003155315071675201015071 0ustar00‰PNG  IHDRò x¹ÆtEXtSoftwareAdobe ImageReadyqÉe<€PLTEhÿäâäP Gc¦³ëþ���Ÿ¸ËÔÒÔ÷Ò�‘ ŒÐòµµµþýäÕ�+0/3aŒ¦O§ÿæýþ ‹âàâÜÛÝüå³Í¹¡öÚ©yËñ®Šeýÿü-”ÿþú×Ù¹ÿòÿÿ¬Ýô@GZÕ§oÇÅÆÁöÿþÿóÝǬ“yNÒ“J¶^Óýÿk¹çêÖ¾Éïý¼Øî‚ÿ¯ÅØCk‘r©ÔÿöÈF<†Êãµt¤=÷æÇ1•ÓI�Å 8�üìÓ?ŸÿÄy¾§’y5Mÿ©’‰ÖÐÁêíõ¬s?ìêëT¨Ý�g1òôõÅÑÛ“¬¿çåç»À«¿Ìר֨ߍ_†‚Š$z´øîꆘ±¿™w”Þú]†þíÄÒàïÞÊÀ’WR>îëäDCÿíèÐÝÚÖÙóüáëïÞ Kýõðòýõž•ÿ‰Âãîå¼ÔÚÜÖÔÖÏÕØ{|eÅåñôöú¹y ëåæûÞÿååêäëã¡£�ðüÑÝúÑÒÐÒÙ×Îÿõÿ:¼ÿ¤c!`47ÿÿÿìì섹Û1�IDATxÚì� CÇÖ†“\@Ydq›�q5‚ˆÆàö‰.\I‚ ƨ¸^s57Ló׿:§Î{j™ÁQo®ZIMw×rªÞ®îžyúT}u9…/,|•º IžÂç.ù×)|a!I^ú>ƒþ’÷näÐ;Pºø®Y'f¯?´×ÉÞŸg/½¥kÞ, ëç�¹¸Ò·[qã:ý«ÛˆW¯Þè|ç4(®Q²�ÎKïRæü«W{?¤ä½(Ìu–J¥‘¾�΋ÑÓýoÍ8ÐYZ»dÓléYì¼Þ+g:Gúæz³´ççF6>ŒË¼Ø{£«Q^sÄ;è}|³Tšy¸eæáJm5ç[M‰«I+ÉÞ,N­¢CµÌù™Å΋½.|(ÉûæÖig÷¾.¿f[Ëå¾Þ¾-�ÃÓ½ë{'Ê}ë�‚ÓÓ½�úÞ”ö¾)?¶9·—öNt®³ÚõõÞàæõÍ��ìÃõ+›/O±ä}eSPïÄÒº>®Ì|~dþæ×Ó‰7¿½ëŸ1f³·o½Iü†m¥é Oßtïü£ysÈÔÒK9_[Km^2¾ïç¥KÓ¨�Å׬’•Üî�JSNrúsƒ˜®r!ŸÀev»^oI~s>] $_²WÎÎÒÅ \w;!ùÕ©Rž¿R*w–;§pC`É߈™µ’�‹äd¶És‰+cY¶�?ö$çüSö@—+âÊÒðܺ¹ëæÁ76•\’Q™NrÎ}¶ËoUN½¹�îÃt]·=÷?'9'�òsw^?M}ÖWÞè�rºóÍ™¾$³›¤ÜÍ-[â'{¿á)ßÊ/É(§œë§©ð s5DÙ±äæVkÆyéñ 9ùd”[3ëJ>J>`F¹1vznä�•œ$lí»yPjoæFÌ3C©sØ|xHÏšvbãc'9 5×väF³¨råóºÌ¹óÁ%Ÿþ0áÍÜuú^>Íý}ýõIR¤d.£#fϥצ%ÓÓf(—Ov’,ÓÓÛé¯ô˜rîîÜøšw�<27èòRé±ùÞ:}²sÄ7U·.J6gJ49Ëø:idï2WÑ.Úue‰%ŸÞÞ¹ñ±˜fl7OJ>S¹ù'fºtÓÓlæ–ñÇæ5dš%çL�MjSÁ%6~úÍÒÈj§Txyæ"—q£“Š6M»P*“)’– ¹H­Vɧm_�¼šëìòš5E•ɹ‹Ì£ÜÛ55ýᇓœ¯s¦k.NÓ%íúôt™y/NOÌÑ»éKÚ_šëzI>A­]�Í ñx‚ ™"1lqFúz�’uÍ�éj><Í…Ÿ6eïËí"õäEê®u6ýv.sçQÉa¦K'’›F”<ÉK\‰¤fã©¶ñÇR;j6�e\�¯æ>oʱ¦pÚ7”ÖªÈe®{$’SªëÛ­äR UÉM§LxÉ}„°þõkŽ%òö×Mn¾ñâc¹¼~5 `¯‚õµ»�\¤p½6_h¦†‰ÎÒâT¼kÝ£×õS? Z¹{¤ÖÊG�jÖ°eíãG¯—º%2ç�1añBçÔTç£Hþ¿ʯ(l\uú×&õÅXòK«Ëºt½ èJ`Ϊúá´¹lÖµêý$_ŸÂÛ‚¹­.ájÓÅÙN¯][ntðÊÆ×¡IIò/.|õ:…/,|µ6…/+¼új9…/,$É“ä)$ÉSH’§�$O!IžB’<…$y Iò’ä)$ÉSH’§�$O!IžB’<…$y’<…$y Iò’ä)$ÉSH’§ð?/ùÏv>¯©w*gkîAêÌOVòÁjgÕüûaÕeÌz²üÇÜŽÔ™Ÿò…½£çžùÿ×Ëó?-/?ÔËŸ{ѾÛÓ}œb^¢‡fçáüŽsËnsù%ަð‰IþGîBulùFµjü‡«Õü“å�\µÚr�£ñ'Ëw~1;ÌšWÿ8´C6—gó§ÌŽ{Ë[ºž¤þýÔ$oùéå‡,äw˜Ï÷þh»z»íèò¾ÜƒÛÿpïNÛË{z¾»ý,¿ßŒòe’œ6·çŸÌV.T7,wäÓµþ““|}~þh ÷€?wŒÝ>2>L—îåÛóoþ»“Ûk>½¾7k%¿COpf߬É|»ÍêMÝû©I~hÍ2_¬«ÕüùÙØò¾¹juä ]íó¹þ ÉéñÍJΛFk•<…OOò$§¹e›QNŸ�ä&LäÎÿAãy�Œò²åkì(ßK—†$ù'/ùð�³UH~'÷ý}$ùÁm1uÏÌAs/ßZ}ð’<ËOÝ9kîå"ùáRz|ût$‡äwþ®V»NYÉ;Æ–·˜Gõ‘{ta¿puùöYs�¦‹ÿ?±ÓæŽeH>h ŸŠä~xþ2ØìåÍÛòhö<|D{žžØ>ÉSH’§�$O!IžB’<…$y Iò’ä)$ÉSH’§ðÁ$O3Û~>a•’oÌRøLÂÆ$y’[µi/_,ØR‘êì† —lU¶ˆ±.HÒïÙ ïOÏ LÜ�ÆqvSèÉ™KÝ\£Í/ñ1.ÖÔ‡ôsµàcRêè?mÓ`?¶½<ÜRn‡vÁ¾©Wwé®ëóÂÏÒQÍJ¾9ײ»úÀ47WÝæ¶â¸ýH~m®¥Xg?V»Nå÷gÙáj~×*qWG.TÏÇuqòžb6XíºP}Pù›?5û¬Žì¦Ä8ücþÒÝÊ‘üÌ©¼QþHË0ÔÄ>[5Žœ¨öt›lî´«´mëÏQÉù]í¿�±kÓ¨ÓÿmdÐlud¦zµhÌŸÉ�w#{6š_K�D~Ä­U*·§éGs]?é©T_¤²P‡I³X5i°Û~ÛRÓtAûYjMe5t�öy¥ÍÔ[Ýд䦊BöcÏÐÖj—i¶â8;lzu³©&ŽGsL¦±ì·ü•C»¸ïº8®[µiÍ_/Rs’¬pûLÅÈ:Æ‹dtá„9ž-<ŸÌÔ:QZ¸ñGÉ‚]lÌ(Y%Ù3ýÞÞ¶7C~WNÆû‘~–O'Ûô-dÌ.ÔašN2oÀ~ݶy®½¤ÑK-¥v  L¢³¦–Ãæl£>FŸ÷’AU8w¦ÉGs7é¶ø|¶[qL5f…=cqœÍÒx2ÿÛ²ßÒ1þ'Å[sÕêÕnUcïážâíÞb\WÖš«æÇ‹ítYþ‘Ç%[8Wäåðý#¦ˆ] Ô¶=c£¦Øžn)Uöe\µ=BüÖC’ï®VÇïfý§ªÕ‘SÛÐN>¯Lv’Ëeð¾#"ùfÓ¯ “l¦f?LCM¤¥´ˆydšc’¾Õ”zTš^øÙ\˜GMWHý¹› ½gè¢l÷c›ópƒL“(·Cº ²±8HgËXáë{¶s¸ÏMöÛ÷2ÛÉãCMHN ñHàK˜lű*cqœ¹ÖsR3ò(îÏ�/Ë�ÏNŒß­<ëé§6íˆêêÏýP<ÖfÇŠÉ`Çè.¾Ÿ4—6ç>�×}·Ó¥µm[¥bŸ­š��9dQk•ò¶d'zöWÎÚK ÊAÊôc~Wÿ¡ t=Q̨b«¶æº^åòÉÆSæâ‹ìí¿Œ¼ú¥¥[ó#æ«Ú^—žF,šN{Oôt£ŽÍù#®½kÓ~ݦ<³ãw ƒ=¶¥¶¶ 2nPåH¹wkŸÓém´®üýC‘¯ï*ùæ¼/¶âXª¿ÅÅPòö¶£öÔÎïx¾|büÏÜÞÛ÷fMÚŸõ …uµÒÅ{–¯«íGXy>�M7.-Uõpï<\êÌ'§Š-ûlÕ\ìæê> Ù Öž›‘j’“䛫|�i)ßàg�…çų̂D æÂÍÙr¥Ec*=³•ª-wû‘ýØ©ÎÅÜø~ÍïÊÁÕ‰ÓsµÒô"ßš×h#[«=w ³d„ìǶ=˯�;,-µ=m»’ç7˜§ ³qSÖƒ‚9¡ Yåö¿ž�53ÊרˆŒr»Ç>›ht‡qö[ ¹¹ëLþqhG¡•ç§ù“NÇΞ]ƒÔîQÓUA]üŒÅ·ÒÊžž!7ÈíÃÏM=l%7A”•R±ÏInN™ÉÉÓ—6¯¹Jn“úÌ-”Ÿ–w0WUv¹Ü€¾Ïí�¼Ö¶÷¾9—2{ç{ôبd¯ì¡g¦=¦�%¿ÆgAz+¹mz‘ž*ofÚHºO�f²_·)]¡sã¾ä¶ ù7ô>úœƒ¹îïdÑw—œžhtȲ[q\ §ca[•Xwê÷Ž*‡m|nKÙ,å_Nº8+ ²Â3«x¥�šÓ?c6ÚsÛô05ràz�Ÿ¬ÔÆÌís’óÉ@·~ÉûoJÉ�˃<;6eûª5—F/jhµV�ًБ±Ê�ö©D²ËùÝÓ�üˆe�#}ÑŽò!Ñ„o(¨ƒO–Üî×mz”Û3VÔ“›[(]`%/ìi±ç6ú|ëLѶÎ\úO41ʳŽü~{]åó [qL“�|A ãö¶«æ;Êy\]'Ÿ>ýÞ å~³÷˜1®£çÉ‚¹ñÑfÿ/¦w‚ºúsWïþaNîÂ`õÁ×}}EÜÉÛÆº+;«kp˜;‚ªëß3^´6ÚR±Ï»°/L>­t˜ó§Õ<@™Kav"ÿ¤ýoêb;È7›‹åVc¬ÿ Û«Ôcu»5¨»@Šœèy’í£G›½@Ûß›óùc�#=5MßZýá_}}Ý®=O¨UدÛô4y¢¥ûû6o”£ ¬ä&˃¾ÜQísªÞ˜c*¿?[mb”g¦QÕžýò T·âØ\Žªô�º&ÞL¨E<"¦½#Ýô½’Ûx3(Mž–øaÖŽMúÞbͧË\þ�¶AÓš˜»©µÑ–Š}žä|©ç/iÛé�‡ëë:µÁ^YÄhs¯ÆnÔàd© Yÿß”Îe§˜îÕȯ±½“kz>gmÓ+{ìõNëà2ÌZì—m\Ø]KaHžßɼ�^µèû–!Ú=¾ûhS?¸Þ~Yô¾Õc+Ž^>­WôË¡ O%Õdø 2¨«0Y¨÷ëaáœMÆ}¿Ô`_$ÉäÓ`/r,뀚Í÷ä§AökçÂãš‘ÞozÜÈkçŠa·]Ójˆ˜-ÕG}^™L¿±§ßØ“äIò$y’<…$y _‚ä`³¦öB=FëØv¥|·�•Ÿ-£®%ëq¼"¢\ìžg‰É×Àj­Ç2sÇîQcy/Fý€ùèPó¨^W¾†�ç]1̹%ÍÎóú¢ñnÅï¨I²Zà¯�yGäwN­´¾!.GÉÁf}LíPpÈh•m;ð]6L6_:kÈz¯„è�‹=Æ]µ¿l°Zëf®ìåY,ïbGú-ÌG€šGõzåk /ÒR sn¤Á¯¢–w+~GM’U€¿vfµÈÕ»•Ö7Æåï&9Øì(ý�ÔJ-¬Ü>£_¥ëæRFkÑ®°m¾Ïxß¾mdAtVCÖãxˆ~¿©L>„ÕHfŽt(X^âÀ‚ùR 5×zm{\ùbƵ{kÙbø§|¤1û¥÷ÎŽµQ²øKg:˜À4_ûÁ§õ.·¯ ¼»äÀÓüËa#¦°wÆVÀ$Àh-ÚÍ{ ø:.üV"#ùó3åY�ãU zÆÅ®jaò!¬ÖzÀÌ‘åËK¬öæ£#@͵^é ”/fi~´£(æßôûâ}¤l9E@^x7úPk’¬þÒ™•#Û.ÓaKóa7h} .—ך¹—[6Ëàasî¼¼cc™tTŽŒw £ÚUìe,gDŒ,‚q;sÜ올ÇñŠˆ^p±V-L>‚ÕZ˜9Ò9H¯XžcÔ˜¯�Z¨¹bjô„”/fÐoñô 7Š!έiÍy *XDû5!«þÜ™•#�|2 ÍW»…ÖǸܽ6ðî’[6kî\—¶äª?´Ê…G`ìlµkâ—ªÇhí‚m[$&ˆXø­�óOL³÷Vb²Ç+"zÁÅ Ê`ò¬ÖzÀÌ‘ÎAz`y«äóR 5¯h½Ü-_Ìèh±cÅ0¼Õ¶¶`üÒaô!jBVü¹3+G®vW•æ«ÝBëc\î^hêK±ÙÊ�ÎÒð‘½ò¦`0v`©óà œKæ"´ ¶Í’ "¶Y Æ5Í®!ëq¼"¢\ŒªÁä#Xí%·ÌéìVZ_ƒË·5ýÄnÙl{[KwÿótÓvõ®c;òß1¹F«hç%ßË-"–,Èù[~Ga¶º­†¬ÇñŠˆ^p1ª“¯�Õ’Ì\ÓIyÀòký€ù§·Ô\êE{¤|˜a6ï6»Q _waÃ`õàý-ütO£}ˆš�U�?‹ZèÂ>$4_í­�p9^hâÂ6Kœ—èó÷§u Œe6í1ZA»`ÛòÊYÎÏâåä÷ûb²Ç+"zÁÅÝæ{y«5¹0sM'åËKÚAõyœž©9ê––òavK1öV+i[~‘w‰wk¢&ɪ/Hgn>ÅOw>¥G(­÷¤ÀËMÜËOŸ;Wð 1`ì¤`]a´u· bÉ‚œ×�õ8^Ñ .n€×kê© á …>À|×/‹~½h�”3žfµ/ ¨ ~•èCÔ¤YCìn(úya÷µú¸ï¤ßØÓoìIò$y’¢þ>4ö bäF\P¸N Σvä÷â€É‡}'�ª¤[ýÜ@·�pí�úS¼Ñå%5çCHÞÞ–_›ëŠöúþÚòà ;d{H¹>£ƒö½­3Y‡¬h8: }]‹­­)¾O¸€¨Áõfk*Fn}=à„X(ùçQ;ò;oñ�É}WD§‚t«Ÿ»è¶^ûãþ´ÞèòÌiVòÀœ~brŒ¯�v/üµõ«!;d{(»>£V_qçmM0èŒ^Y=аcÒ(ÚaëÐõ 7ÕpçÙ.\Ú%öhÅ’ÛCÛ;ÄB î,`Öh�ó˜¼Úo�ËÑ© ÝðO÷J·�pí¯éOë�Ž—Äœ&%]ÁÉÝŠúG ·ì…¿6£Ü™sȤ܈QƒA«·µ…ñ@×`ôÊêáÈ-LÚF£>ŠVj™¢>áíPFžíê:nÛ{´b@w}= ·ÆNB ù…Û¡väG\Ãäí‹s9:¤ôÍ•.�@ûãþ„7:^Bp±É#Wp¦4Õ5€Þ²þÚ­L{×À![QvcF­ŽÒž·õ�5=buä“¶‘�¢•G¦>áù¡È³]!¸óÉf/oT¬Ð]ÐvagþÕv“ÏÁt†óÊÛüˆc&/†ûôd+H·ú©£t4í�ûS½Ñå%}W )É#Wp~i� cH &+þÚC-÷.ß±3iXÉ)7fÔê(í¼­¯Ý²£G¬ŽÜJå9òQ´slMq>áôˆñuìÙÃ'›ìÑŠá!´]¬ŽÌåd¦ó¨ò 9çG9µLž ÷<è¹SñÒüÓµt4í�ûS½Ñå%„x�¿£ä¡+8]Ÿ~P\Wnñ×ÞõŒ€DçA8d«çscF�ÁQÚy[;d F�X¹…IKä£h¥Æ‘)Àæâ>y¶‚;˜Ïö¨’[Ñö,¿éÃt.ÁcÖ6?¼Å#&/†;úQ¼@`�”Å?¥k�×ô§óN—w/ܻ͌òÀÜwÔ±oç Î^Òü>Gf'8!‡l‡”0jç(íy[û ÈŒ±¢aË¤ï šöQt€¤=SŸðÊ£?#Ïv@pÀ|±G+tÚæ�ŠbÏ`óе8öl·íR{P±z” ÚæïôZòcT¼Äoq�Ƀ©KŒNéVÿt”žyÞýŒÆëõ'¿Û//!Dƒü�yyè Žß?‰Ã¸2YŒ˜óä[uä(;|ƒÑ+«¿ ñ€�×8¶G¦(6Ÿô£†WB{]Åð(××`YèIÞʇL†Çˆ__x¢z׈Fý oôkuëO¿±§ßØ“äIò$y’<…$y _‚ävêou…ö£+þ|ãJž9I ŒÉá¼ɾkëc]o^s�]৤ö»OqçÌ.�­gVGõñLê˜íÜTçªõÞ¸[‡ÙSKk§Œ�^Ьžu;Ï×¾z€ÃÖ;ŒÝV4€)ßy²yµûí¾èMIn]¡•JŽÑØËs‡ƒ<Û$10f‡sþ}Ðþ˜«X×›×Ó£gø½O|¥µäÐS\ý¯5½±Îáœoz<“ºÌvî¨#ªÓj¡¸°ÿ˜Ùv–ÖL½ Y}ëÔ…Xñ¹¶ÞùƒŠæùW>¸«ÛÉæñõ ¾èÍðr�ú›y°lÅ®Û4«0ȳ$‰€±u8' ù¼èaÝh^ó l‚¿ä"µçØ{Š[ÿkñ|Ÿe]¨ç}žoºåݨ3¤Ûi×9-ªsFÚ/É`ÿ³ÇDó¾[}�׸duÖYGrý6o ÁaÛY`ì¶"wÌúžãM…†¾èÍór�úÛRiÞŠ]·yîpu¿æ$10Ƭî#ðBç߉âyÍ3;=º o¤ö»cOqÛ�¶³p—}ê“Þ-5ÚÒ[ÝoaœÖV§FJ€ýGÌÞN4ºÕ×} àj·f…up$ÛCpØv»­Çà{Ž7ø¢¿/WhåÁŒk#×m3:i9VJ�±½œöì¯0&²X7ž×<³Ó£ òÖÔ`Ú5žâv(¶ÏÊ[,´Sö9ŸtáݨÑÎ�n©5ÒJuˆáö1{«iìV¿`ûYaÉ¥¡0ÄMhŽYHûu\wÌúžãM…¾èïÃË‹¾ä²UãºÍ¦(y†ä!0¶’o›ãAÏk.3' òÖÔpìŽ=Åe�¶·æ]ÏÈ>­^x÷Ÿ¨QçNžz}íªC, nì5ÌÞ:³‡nõñk¶‘U]èáƒn Cj$ÆJn}Ïñ¦BC_ôæy9$?Œò,pÝ–±¦“–Û$10n“Ç7Þr©ƒyÍíÌÉ‚¼‘Z»cOñ ïV’ ¯nÙ窷¼ûOLÄÎ’ µFZ©±tÀ}¸“GÌÞ]¹}·úè5)YaÉ¥¡0ä·Hrø½SE¿ykx�5­¾ûy­/úûðr« ãÁ|D®Û\È3$�€±åÜ¥L|úãyÍeztAÞH­ŽÝ±§¸ø_¶Û‘ë9©ûI}Ò…w£F—vVÓ¢:ÄÒ`ÿ÷Cfo%¯„nõµ¯È|ò’Ö¹Qî¿uPtsسäð{—õ*ì1øžãM…¾èïÅË­‚àÁv+vݶ£\ܯ1WxŒ!yþ;~Á.àѼæ2=º o¤Ö’cOq�¨�a»¼„«Nê¼Ïù¦[Þ�‰ØÅb¦Ö’Õiµ:�º¸±‡ÌÞ¾ÖºÕǯHÚ>Xç9’SC=Cd{~ùÓÑËR%š•}Ͻ7êù¢¿/—©¿ÕI›¶b×m®Nݯ)I Œ±\Ç•ÓjÁºñ¼æþôè]j-9ò‡ÿµx¾ë¬çô…Xö©/¶ðnÔ‹ù‰]`½T§Õ¢vºÉÚ=f¯vß­>~ ïwÃ:ß5ý 3Dç°wKEè‚DpWßs¼©ÐÀý=yy=\Ïu»�¿ G”<ÂÁ@ÞÀãç"Çò8x°]½ºeªïö¹¼#;#š�û¿VÇ�=jOÜ(Bçm�É'ƒæëÏa_©7˜|¾èé7öô{’�C^KT+3Ô0xqâ�^6°g#w†]ÜWa¹Ÿ­ß­ÊÞä(gÿà2ãLù Û Ç ärXQ·pf禭÷ ~—ÖkZL0M'¢$_|¿}@Ÿ Žƒ6�´ä °ó¬<ù¸Ù¾ÎïrVy‘ܶ«™Ãßžâ¨VÚ§¼Þù«‹•Ö-½–Á‹¿yø²s?é {/·‡ÙFݪì;Ìþ0]»IÂ@ ¶­`Zа2iAÝêh 7m»<÷.‘ÜzMÃÙíª´Ô>ôX’ØŠ¤‡š6æÂ£;ÂͲ‚…x—³Êgn”0ÊuÃßžâ¨VÚ‡Þs%ÂJ;g|Ì॔øeK÷ïÚËæ˜së³iŸ7/y0û·ºDK 0j·Ô·€i™�üZP78³ºiÛ *`¯xM‹ Ø� Ô>ôÂÜá� $-y`.<º#ÜŒeÂŻܟU^ïåvFuqWwþæÖS\ªu+�ß^J„•ö…�˜Á£”øe+¹èÁ«¶3,�³éªìMJÏþ¹F+˜�5Ø6²cr9 Ôíb·p9ʯi]eUyUš²”Ú€Ì]Þ&’ü†¹âÑãf7�üøþ,œUÞ¾*€öˆ»:üÍÕS< 8ºöž”¨Vz/ x ^J©yÙ€¿…IgØ »…å‘›:’¼Çã[8ûwì 0j%Æ ¦jAµ_Ê™z°÷Z09vk Ýh¢õ:ìÝÁï3õñs� µÐ;lpu�´–£ßŽ&µ�µ·O)ï¿lÌä¾P7ÛäÓô{ú�=Iž$O’'É“äIò¾ÉÕÍš'='`K¤¶Îˆ<£˜1©ùéhq]¡Ü÷œn¸^yͺåñ ì5 Ÿ—»kœÏC¸îcû�çc|®û׿NEeÊ”è ìenuíG7×z¸<ظ{Ñ z£ îòñLУC ߥ‰ï*9~ÆáIÏ­ëvþÒÝ:[ô!òŒV6­“š[XîV÷<§®W¯[^3{¼ð9;Ÿ‡p=Àö´bxˆÏ}VÛZ§0?˜Tâto§D°ÇÜêèG�k=ZlÜ{Ñ x£ þòñâKÒõÌϺüï*9»Yó�¶„r˜ÔÖnñ‡Ð3ZÐ. ±ÃßË‘:ôœn´^y�uËÃ8^øžßâ|ìÏæB½=lÏŽÞµøànMtϓݛÛ�}ä¸LoJtž¾[çV·ýˆmõA—²”�ãE5Mœìë-ÏÄ% |×&6!ùˆNzÎÀ–Hí“Ú-¸¡g´pn@b�4°©CÏéFë•×Y·<œ�=^øÜ+p Ì]Ìï[ê Kàèãsì÷ÖD÷<ÙË%•�toJt2ÙaÚ‘€2Ã]Ê× Ô4 úë/o zX’®g.MlFrëfM“žc\²Ú-þºÉ ÚÕYÕ1i8`¹Kí»Ñ6Z¯¼fÝòxöxl} �”0w8˜ ƒ¶GïŸëJânMtß“]`¹[oœ}×)ÑØcnuô#¶áƒîMAÏ]ÝóÅ4ýõ—�—÷dÂ’œ—~G³’[7k;7.™Jº:[âã¸ÉZÎ�•Ï�¿ËëKÞh½òšuËkf`o ¹p‹™1¡ºµU-Á2Ä>Ç~‡¿}OvÀò`�boJt– s«;·u» t7½%èpÏw¦1èo°|¼¥@aI¾7-ùY.|’‡žÑ@»‰�¿–ÿh³Òzå5ë–Ç3°Ç ŸCr{Ms×õÖ;xkI°b¸‡Ï±ß­‰î{²–»ÜÚÇ|X–'s««O½lË3ÃM÷Ê"³qoutkš€þËÇ«3¹+ÉóÒŸQŽiVV’<ôŒ´ H ü­°Ü¥ö=§­W^³ny<{¼ðy†õ<Æö×µÂe1Ìk.ã4ÆçêŽ5ÑOv…åÁ(×)Ñ-°ÇÜêèGlÃ^ñÂÆÝÄðži™›>\>ÞÞfÂ’œ—~ó’[7ëUIzF ÚUHŒIÃáîRûžÓ ×+�×-�ãš…Ï­ä­òø ìoÌmÀ8zÇøûuÞóГ]`9RÙ21%º rÌ­Ž~Ķ[Þ–Wt¼hà›6P½Ù`ùxûRkP’óÒoZrq³^•ä¡g´rn6uqMí{N7\¯¼fÝò8Ž>çb…€+öÇZáÖ]–øŽÞ>×ýaa þË]*¬FÎdÞs’7÷fuWÇ\ëXÝ–¥lܹç‹iè¯]>^=ú]IÞ¤íƒÍ}I{ Ä­K¥îí8wÁÇß R¯¸^y¼nù  guð¶:˜GG£ÅÆ�Ï�øÉpn÷ U„ï•ÄK?º¹Ö_Ö}ƒ vÏ诿||½’j'mO¿±§ßØ“äIò$y’<…$y Ÿ±äÌÁA™“c1mⱊ…ÅÁÚM±n§o—9Ì£e¿k–û^}7bé)|ɉƒë²ÝƱ˜6óX`a8XëBÞ k1‡y¼ìw¼Ü÷Šè»KOá#H^.¡_ ÅÓ‰Óöxláàúk�ƒµ2‡yͲߒjÕè»KOZ~É­#³¸p34ïÆâäÊc ÃÁš¯ =núvžÃ¼fÙo¤Z-únÄÒ“–i”Ô…›1¹®ŽñJXØs°–•³™TÙ9Ìk–ýÎÂå¾WDß�XzÒò£ÜËù·sqáæ^ÖÁEr&FžƒµøY±ä2‡y¼ìw.÷½"únÄÒ“–Oò̺pS/{+‚[É™9k,ªÛ!ërð»XѲßÑrß+¢ïF,=iù±$WnëZ¯Þ•,¹øqÃÁZÕ¥éÛeóîxÙïh¹ïÑw#–ž´üh£.ÜP Ñ½v⊠¯’䟫ðÞÆ•7oÞ@ñ$ùg)vIïäVøò/$É?ÇÇ·’Ó=IþE]ØUó+IòÏ:Ð��&’ÿ’ä_€ä™ÓÛ*žm $_N’v’ó4ÔEó§¯É×'É?ËQÎÿd�6¾òÃå$ùçzK4 _fþ£ÿ•zYó§^H¿±naòr&ë§J’q!Iž$O’'ÉEò>›°JÉSø¼C’x»ä£¹ ï"ùз %Ϭ仾}¹Mâ5?%É?�äý¹±bVÌeÙµ—ErÔÏ8ήÝãháåÓ%ÿ*úÒ4ô­|Ø´wÇý'»¥)ŽÛý|Ì\™mšMöëÞ¦½òíkSmq›dw¾J’¯VòY;k?½¿ý—j5¿!=´X­öìÏxsGVØY­šK@“’ï7IÍÇ›&zqü›ÿ²ìÌ_,9�L·h÷ïrìfVà¤Cœã?æø_¿#£MüB‹+Þ£ŒIòf%ï/Šöãw ƒ=ÅÑÜÕîþ¶£Ù‰žý•ŽüP«‘}¶º¦9É×anš¿n#¢‰Š/nïþË�ò›Ù·Çqì&ÿÝÚf.k^˜·¾za|ûÍ^ólj_hqE{4IÞ¬ä=E|¼vî0In†VÇXn[–U¾.v´Ü»|§mÛJ’ÃзuST4ÿ3Wäâ·FÙÌ…�í2{o¾ O|Œ?›Û²oíñM×¼8pó/út ‰Q\Qóz!I¾jÉ{ºå1.W­æÆ‹£‡v‘ä£$¹ ÏÌu=ßy°9ÉIúLäì[V’A6{Ì~.þ~`G�·hV�Ö¼8à'Fq&Y’ü=$ßZ¥¯_£K;ö˜Ç¸ÖHnGù£îŽ–Õ<±ÿúÖQÎÃ;å�\Ž©ä_“Ý"q½Q>�òz’ÿš$_­ä•=ù…;§zºO´tߦ£<ëÈ?YxÖÓÝZ}p zó%ßõí¦ƒ?@7^s¦{õ3v»_ÜÚdîåVò· 9Éoþõû�5ÉÍ]ý…9Hñ·H,Å%Éß÷{yûYsínÙOöü¢“¼r–ŸØ³ÃæèAóUîÝ$çD·¬¡Gk¾x¿0#•½É7ðCø=†Q~—Õéè_ûÍžm|Ñ×ÄR\’ü½p½vî O©5Yv/ØY—*“Åpýõ«áÀ-?úêVã$á&v¸uë-iý�$ÿïþÆÞPòÿ^H’¿Mòsï­ø¹$ù'¦ß˜—§Ã"oýãšÿz+IÞ8\.¿ç8?W.GoÅ ÿúkþë¯ÃIòÆá\où=gÚ*÷Æï¾ ßú¿4Üz‹âIr�fAýº¹@YÏ}Ø"ß34°(Iþ‡$y’<…$y Iò’ä)$ÉSH’§�$O!IžB’<…$y Iò’ä)$ÉSH’§�$O’§�$O!IžB’<…$y Iò’ä)$ÉSH’§ðÃÿ 0‰Ÿ®]ùIEND®B`‚././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1760000640.7860088 trezor-0.20.2/docs/sign_tx-electrum2.png0000644000000000000000000003506415071675201015073 0ustar00‰PNG  IHDRî×Ô^/tEXtSoftwareAdobe ImageReadyqÉe<€PLTE#ŒÿÓÒÓ´´´Xý–ÃõþÿöËÜÚÜØžVkÿgÐWO�N²äñ÷ÑŽð–x¼ @ׯ}àÞà–ˆÏðDKOñæºæäæÆÅÆŽŽŽ ƒÎ‹0óØ¥z°ÔŸ·ÉþýÜYˆ®ÞýÿÁ�_zÊðƒqD¢ÿ¤Õë}mRâáâA‰äâäõõõMµYÙBØ×ØêéèÅäîq¼â[;6k–^Œ&ýÿýþþòñÿÿìÛ»3ŽË‰¼q ©ÊßëíßÞííѼ¦ìAIMÿʸûP£×�}A;".5¨Í¬çæç�ª»µ˜”ÃßDCÿ\þæïöû.ùïßÌ2ƒŽ§ÿ?IÉ®–ôÔÿâçìš©—ëäÞºÕéãѲ½Ë×æÅŽßǹÓÚÞÇïÙHÚ‚ßÙÖæ½|ýõò—ÞùÈÚÉìôûn™ÿj¡ÆÚÔÐÖÔÖòýöâëäÉå¾ÐÖÖ|ʆ­¡¨Öãë]ð{üëÿíèËËËÊäää·(©uDÎíòY {|P9C½þÿÿÿììì­ãóŠ8JIDATxÚì��CI¶ö¡ÈØÓ°&€dà“c¾CÈ*Œ^ÖË*`tÇà:èÌu6¸p™ô¿þžS�¢ò¡» Ï£¤º«ª«««uúT….®´ÜwÝûôÍËu§Æ®ÜìÐeþþ•©^º$r�;ty4u¥÷£çCúïÿþÓÐó|êØíkmíÛíðÇýýÿú×Ä?þþô%Õ�&øêê½òØÖ<Áþ?ÿCÀÏ�yšìëÛmiÙíë›lÄýyâ/ù¯ÿúË_&þ<©ç¿·’~o=ÑAK‘wh¹¯­®x÷èO;ë¿ÿôÜÄuôõµHõõu˜¸¿O쬿Lüíw¤VË‘r9™½qlÔ·ÈÚ<~�–ûêºrCkHÓN¼™¸]M;ñ¾kâþ¡i'Þÿqúˆ–"ôñ¶ãMß�/ûú^Ðö�7}-ªM_¨à-ùr(ñ¶ãƤÙmä…¾´<ÜÿÔÀýO&Ž=¥Ý>7ÑÀ}Í÷qÜ_ÜxyP.—Ÿ­–ùSn—Üx3CÁ-<¸ñr�‚Ä$§Ýš�¼P»/L^è+àÞ¡åÑN¼›¸ÖO­&î_ÿåé_ÐGD¸w¶Ï&_Ž&^¼9HðöË¡ò»%†:ѱyÆYVË·:æég(ÑÑ1ŸÔ»L^´â—pÿЏ'xóM_ãÎD—Ÿ-•÷qäËݾ¥ò³½YÚly§qŸ”»£³“:/Zñ+âîwfLœß™1q~gÍ÷1 îÛIvPØaQ¿YbÇ¥ƒ=œHù™ê÷wrwI…Àýëâ8ÿPÕÄù‡ªh¾�ãþNáþ¼ü€7 îo';ZF#ïf' ùg{œ«õ™Á}/2IyaÝ¿&î“Zþ‰H×Ò˜ˆl1qþ‰ÈIè#"Ü'ÉeŸœÜ-'v—Ê ¹Mï•ûv÷H_+ `çË�)ñÖäP¹õᾪvM^´â——‡ûäªùšiµ‘Úb¾fjiÄ5¾fBë}÷Ùw“oÛIò^"£‰·áç´ûŒ¶ÊåÍ®ÍcN(ßZ¥»&ß÷¯‡û[Oæ—ÞúD¼·¶íþ¸]õK»o¡ã¨¥¹¡vÕn‹IliÎÛ‚ûšº‚&€.î-tiÜ!àAß$î­titÅ… K#àwîÜ!¸Cp‡ àAÀ‚€;wîÜ!àAÀ‚€;wîÜ!¸Cp‡ àAÀ‚>ƒû†Z”ãÙ‰Jê·†�ŠžŸvŸsaÛhkè|âeAÿÇ.¥²ØéÖFGŽH)„SnL”©¼-46t^�™˜S¤Ï÷îK²Êko¶åöÚ[Ž+L¾�9^v¨àEVí‘)·±ëöšT…{ˆÂ%‘BkCç÷¨5*Bî�d裋£B8ÓnÅ"¹ïn¨ Â^®RŽ\”-¼Ü%úg„˜-úqwÝ|²xô‚Î î³Û½QkÙ­Ø�Q+´] ç áœ;g-‚‰b-¼àæ�õž½OÖÝeÜóÎtaÈ·"zšq¯ØÓ±€‡Î/îÙµ·óVJnÇB…`òÙÉñËwùPÍ"¥Ðò„ºã.wé£êìKÎáÞéÞ@ƒCçw2ØÒA"%· Ü9òif§Ùñ­\ÔR¹Æ]îàU:øÜ»©@Ð9ǽjO³Å6¸“6¬…¨5@Þ¸¶î}ŪϺG­#q/„Chmèà~omϳî5+WœcÜ·~ë97F‰yg¿_,÷JßÝ^¯íÙÓàþ®e~†Üû¹ƒe´8tqOú�™ÄŒgÝ»-9é²$Dr4çöÈ©¹ç‚"Ääîˆ{wžÚaÈå!,�?ÜýZ{Ò´;ÖËŸSc:q¬9ïںиCp‡ àAÀ‚€;wîÜ!¸Cp‡€{“Þ’Z èŠ >>îuºàîÐ7«R„T—ÿ#‘p‡¾iEäOÄlwèÛÆ]þÓp‡.�uרŸ÷�›�§ëé7}¬b½¾²ôx� YYºy+Ka|µô`Pž(Ó÷,Ý8m†3“jšë¤J?×…šc–"#‡«?wS�ÏWò^�·ýü`ÀlÖ¸,®Áák{ êý³YSMy�\\éñ ïP¯ÈÚÒÍ{é£.z¥/ÛT7.3³zS&fæo>Ø÷—ªÂø�¾FN—×Þ|öÙÒëiïRÍõ˜Ë_-ÝÊúZB6�)BÊkVy¥:¿w dþ[õ›Á]ùîf㤸Dâ@ôd‚e’®G­ä¨HÕ9,‰d¶Þn•oÎ8m\l^8�{µ(3ƒ!ÃX¨©Jæ L˜WÑkÀ[µoÕ> fGEsgÉ„‡myw™Wä+S�ü5´’ƒ‡BºýáÐ3YÏ.'««©®Q†3v[ãâL‘U1[¡¬W”wÑUa·5Õ�ÊŒ‡í›_\Ð.ÍØ��RuØn© Î…—î?{ŸT7%_ª¹c)‚T|(뵄lS„i Õ¬òJM~s tþZõ[ƒþt33q‹Z:¦¿ßnËCézÀ¤�ï~o×ãa¾]öh’³mÞMYÅ–‚2Ÿ +ÜÝGòNÜçÀ_4°ÈƒÒê–ÈmÊ:õˆoNŠK&(Ò®+-×Ô#‰»Ú­HÚÔú~šÊJ·[Ã&”5n·èÄò"YBSUÓ\#ç¦luïâ¼"sòâ½"MýöŸÛ|5–evQÆxx�š S–fJm„=”‘ûv[=�OfŸ]2Í-ª.Õ»}É|X”ÑÖ-ÁMиI+\²iVy¥&¿¹ÙãL«~“ G<ÏýÄÖ=Ó7Èxf¥Ñà{õŠì¡psŒïqÕa{™b3žâlé€b+Ý/-©"H$î³3B$Òõ~~�;ëԾضò„æƒR^h¯Mm×eÖä ³CE÷èÝz»|=|ؤò}ò€…4ÝúÍÞlÝ«a}óuS(+YχÚéHâÜÜ;U5Í5V*ú0gŠÌ„5î¦HSÿù6&ËWc.så±Pßtåùê¦ÔFé³üں“®ïðÙåcÎñ.Õ»uɲC¤¹×¨dÙ¦ˆxP–¬›U^é¯&¿¾2¿×ªßæP5Ò`þ4CU¶‰Ò|·qKJ ¢v‰±ægëìÓ qÈw�o`—X¦Ÿír�•“a€b7ݺ…´4°ú ¾!"IÏoºGÑIÖ=m¶Û­\v%ŠŠWì[,dò‰,›Ì¼³ŸÙ#ßJïVÈBµ[#ê¹S6÷ZŸ<ý¼u†Ýsrg%뙤�U"AÖ4™mxF\- ¹8S$‘–xjmÕ½"½‹–gójlʬó.;úöœ6¯T¶[t Cv›´Øå ùÏ.=@ê=úRÍõèKVõ%S­“e˜"ªÉýt€ŸªYùJ½üúÈü¦U¿mg&rº™fDy ÊÆqãw g0]¡Vk–É�ݧì”7L>ÿ×^kލí3aã»çCôü¼ïÒóÛD}#ÝæÅÞû!Î*·å}_)fòöƒUK䨷ù�Ms�6KrWÓ±yƒ¬w04È™ò@."f½°*»A‘”’DZïnp—×h€3gЬW,ruy|«‹2õW¸ûk,ˤÆ�¾vwdÆ^?w¶õýdß’òý›Î®�=s©¾ëáKÖø&ã¦%Ôæ&¹SÝäNéfå¼&Vß™¿ÑªßêPµ~ê‰ÈLP=`e»J[C>¡¼ô�—nn†îB0ôz<æì§ó9߀2j¥ÆW©_î±P—\.~öW}PZ�îód�ìò–̦·»ô°7³TŽÜ ¦Øa°­œt:éôzWÖ).×òSfºÿ¦†Ú{ 5Â�ƒò€î²tîê�=ÚƒÑEòY%¥ª¨L£þ|6�å=™¼‘¶3hJ=T: 2÷g7¤ín:»6îæRÍõèKf7‰›Ò$kÜUìïèç 7«Â]å7·@å×­ú-â^–?æß‰qOçíÒPw"ÊOîaé¡êÖtäó“]ïX’ö_>R7´KF jë¤t »l]”:(Ûÿ8+ýT3k ¬{Ýë\+ÛÒ+�[¯$#ùPœO+‡=ž©êrö™ÉxIù£¦†™¥iÖ~Õaöù´2ožu¯z¸ëk”±5häJš"£ÊÀ†¼"Mý�uoÔ¸*³’ö�Çiù44¥6•NÀ>¾tÒ�]÷º¹ÔF‹ËKNçCªn:Y¦Š�ݰ«Ñ¬|m&¿¹ʺëVý6q—ÿH†÷“àžŽ‰å÷7²æ¡I<®½Ó™nr·óÎt½F=as|<£6￲“#9J���ËI†€Œ¥[—{] 缃¢b Ë!=}Ý ƒ½Ï>ªY!²¥ƒ+Af$EäÈc�ŽçE�Ù•¸ÛÓ›Cä·Ùó�32ª†|’9kÁ cvg&À³%r.föQÔóÝÍ5ÒɲңÕgŠäj“sÓcŠòê¯}w]c]f<ìL�u<¢–XN¯ðÌ‹.Õ„ä»wÆ Oj)1/|xv xÝ\ª¹sÉ\l7ùß&™›À‘Qó&³¦YeW6ùõ-PDݪ߮u—ÿË'ŸˆTf›G‚ê�¡G7™SÒà§ßãuðÔ÷Læ‡ÿ¢Á€ov\ùð³Aµdfï n¶ý:Ж]oGÃ2 A£.ŽMîå䑉`�ÙeÇÖDEg¨ž��Ê“�Ãííe]¡9KØ%ƒ»¹Fy²\¶qq¦HvÄVº¹ÈY3T55Öevé'Zf‰Œûu¯T¶/¶Z²T>Œ÷Ÿ= §æºÌõèK–‡-7’ûåÄ¢*Â\•nVu t~s úÕ ªU¿=�EŒaç�ÈØ™‰`ê¾² î” _7 4~¤ÕØ”±dï›’“ë‡2Û*kÚuÕŒê@ëí6ŠæœÙ¦®¨ép/Ÿjœ$=ž>¢’¦:æâL‘i÷P‘Í­k|¸Lõ%ƒï"Mé:£Iÿàìõ¦K5×c.yÓ\Îøõ75h*Éä7íäoÕoNîT¯OS.~gº\îpîÐ%ÇïªB—ç]UÂÂÜ!¸Cp‡ àAÀ‚€;wîÜ!àAÀ‚¾aÜŸß,Ý*»•» }*Se¶ˆæ†Î#îC"2*œ}w(áE†?V†—{ëSgª:À:�¸×,7j¥Ü|è7Ú}ùö áNM¹½œÊku8·ÔËœá¾;õfÛ•e0õöI¸Cç÷¨5@ŸcObüF~�W \æ—Ø�ßÂ)e¥‡ø}·6:âÏM�íÍ1KäÇÊ”À•)¨Èu�;tq/äÅ샴#o¼;9íÆœ"Yw¶ð÷¨Õãv;Ó±p8wÞ™.ì ÂÝ) 9Ū}Ïí#Q+Qœ³€;tN‡ª«£d¥§%î®{c²û0î‰w2ápnéÒðX±;cÉoßX©ªÝ ß:¿¸“Í^µµrÂ&ÜÝùvf>Ì-q¯iÜ£‹�zEI:p‡Î'î¥}ú ‡˜ÚB0TdTî9ƒíT7[ìùkìÆG¸«§ƒ+­{7p‡ÎéPuöÅûUvÁ�i7ŸÜÞ³uϽwcÉé9Ú®ØË.á>w°Üœ›ˆ·�å÷p¯ˆ�ßæEOÍšÝÞ€ï�SgfžWLÝ ËîÜг*CÂ)Ωí¯»8àVxÒÅ—›_²ì[aw·[Ná¸rCà�Sßý¥obý_ü˜Šž;:÷ü=¶ö=�”©1ùš:ÇCÕÓ) foZÉ}´+tpç_Ÿy§º$¸Cp‡ àAÀ‚€;wîÜ!àAÀ‚€;}c¸×Z‹_úTs7K÷o›°°¤~Õ¦¦CwŽÏ_X-=žæ½yη’d„ûœ7·u”ŒäÌ÷pC¡Óà©c_YìüDªo�wÃJŽê_�÷¶MXÛ%+Ä¿_ï”äk ÝÂît A»4cßãõ 3¼å²®WŒ7År!((àÈZXŒ,Ý�÷šU–ïÝõº/·åÚ1®Y2Æ,5óžö‹ü^ÞÈ”:DeÒ×A�Z§FJ®1p¦ýÛ^\€`îÃ… ¡^ã·^í§Ô�*bDf�³õ�[óu-~¤�çž!_ uy ê|Çì¤po2Úμ\=ÀžâAPˆ„Z2&ÑXŒ`qTgºJ‘9Ù?x5š¬«ãf‹j�³M û·M¨–Û †¹ñj'¿ µÖ!cÝngŸ_uݧ8ݧîn,éÜõ²NKpK¡ãž'ô\ùzÞ�Ø"ëK`/»+ÕX{#´] çØºËÎ~a/G¨NòN‘�«ˆµ’�Z�†ù5–Øl›PEÇBlÂiŸm¶L"}�:OŒ_ê®Ø�¼´“H*ß=–lm-És«ƒûíNÜLèt¸³Ù $å dè÷½Eò!ÿÊJLsEc°l³´ðòE·ÝY¥c ú•U½�äQãn¶M¨qO»E¢5(¸wGØw7¸s'š «Å bv„Ò<Ü«À:-î4RŒ°o¸óÁÌI"óœ™Î&Ü C–pîIû[v:ùw݃¤%·RþmÊ' ¯¹çÎÏ”·†wí:ûw¹Ï=É83ÕFŠ.ŽàfB§Â�|é¾¾>vU¸{Ö=ׄ»ÏªÖòNM/Œzî2©_Œø·½¸¼tbrîüºòÖîó�]eÕù§¸‘(6ã.‡ ÷šÅݱ°·…[ �÷~Ñ£Üqî¼dÌ*ùïz©ƒ{¿XîU¾ô4O”ä�õµ=uœÄÝ™võj4nÞ^¯ñÌKwdÚÛ6!»)zšÄì{…!Ù%¢rffÀåäš*nX t®­¢ç̄޽Ýݳ§=) ¶ž¬©c!è$¸ä‚_äžûp7KÆè¥f î… �üÍi¹îÊhîyÖ�ש1«ÑPNÁ“…CrF]m›PÎóï|ø²ñw <D…ò25rF�sée8I$ïy¾»J´pG¡“ÏÌ¥)½ÆÌØ“#“ׯüÁQzÉõ‡¶M¨×�wÇ&ý¥O½y¡ÂÉæðèú½™Äý„¾îÜ!¸Cp‡ àAÀ‚€;wîÜ!àAÀ‚€;}¸?¿YºUtûÕ›ÔGI®ã®–¯ëìz‰— –¾€.îC"2*œ}½ˆÀRëÀäE逗º³£êìà ¾p0Œ6†Î7î5kË[Êâ=‹ÁÕ¿z.¥Ö�‘¯gçù5í×,I@¸ËÅ1Ôr4O á/CÓ´ �+Ü%¿îØ“è¢Zì‚,yE½P4Ÿ�/©u`¢Öˆ\F¾¯ª{GÕåÅ1ä+­sÖŸé(§¨ŸÑKÑ@ÐùÂ�¼”Ù/Ôt½½ùºèÑËË{é7±åË{Cöã’}O½ÚÚ/ß�v+"!ß'å÷ÿèG¾Y§ŸÑKÑ@Ðyª®’�ž�V«_ìirUî½éà5êÌ«yú]ÒÙ{™×r|°j©ÕÄäªUgš,?/§Á¸›ÅgÔR4tîpçu­‰;¯ÔH¼ò¨oÖE¾¬Í tó˜u¨\¾\ð†ªÌ|0'{ánŸQKÑ É¡s†ûF‰=ôpH9èìÇWíýCî=%ÉI£vg�Wž–ãVϺïÓÏR²¨­»·Ni-ߣ—¢A›CçÌ™™gÿ#QôÍÌÈ¥^öå"1¾¡ª�«ÊÈD½TiÕÙ“y%Ž4^U‹Ïè¥h èÜùî/ß^Mæ}¦&õÒ./}K¼è•fò¡¢>± ý'‡ªgÔÆ ¦Ø¡KƒûÜïp[ Kƒ;wîÜ!¸Cp‡ àAÀîÜ!¸CÐ7�û|+©ïcÇ–JŠz{N¯0câ¼´ç·è£æí•T6½ ÍF£üo>ÓQr‹3ß*úÎ÷ü™>—\Ûf¾ôxÚÔ²øÉk+ÌoŸÊ` †.5î…°(ÛâcobÂvÉ ©Ä +9*ÿ ªŽóÂ=á)Õ)Y\L@ÌðB4fAš˜(—˪üª°Ëüžk@¾(z‘›ÆãV ¸zmJM̨Ċ?S³*ò%Û¨Ýéû³Ý�xOý-ºT¸›×íôÊ0毞J’~!—K*ðt8Ó^œ áä^²ÈKð‹ÙêÀ€=í-Hã£P¾í×-¹‹É¢ø)·näп8¯Ö¶™£" 2±f%üðÔŸ\]{Ã5¥sLÑg²H'âK˜â•rÜ÷:¾±dN0€»Á]/#ßZ"—¶<Ä5(òÕ¨5lâ¼ð÷bL¯ºÁo´œâË–"S¨¤¡„5óúˆÄ½ÒÀ]án<.zÆ]-D¦Ö¶évö]õ‘OÖ|¸ó:8É}YÓõÁë"äsnlv†#úùõò€Ó-ãõ’9òÑbOàÞzù– º^ ¦jß#Ob„LvÑë Ê>ËWø(ÂÄùÒ$î!N%ëåë{fAšB°lþ<‘þ õ©%;’Â=|è½G=¨y+fV:¨ˆ‘F ¿K†9j-ËD¹¤Y!¶±Èž¸žµ‘ë@ÕT?ÕËÒêA¢“½ Юz,4–ÌîÀݳ°f�˜CÓù�¥ÌÁޱ‰k¤1—óëʶV5îfAšÚhg3înØë!nžs·Û[©ٙ‘Ùi,B‘ÝІµÀ'â:ÉA¹îô ÑãŒ|Ž{YUZ÷ý#%CU½@LE ü6/z {j›vÝ9Á¼æLÞ^¯ñü‹‰3¡b7fß+ v—s¼;Y�†Ãž&Vìå7o–$· ÷9+9½¶jåó�=>8kV¨H\»÷ÇÞ÷Î-ޏºRtòV÷{k{TV¿Xîe×�|÷­ßºyIÍZr¼Y2G U�;p7¸ëb\žÑØrõPUí¸rÍöò�éFœJ^¿ìª…hœõÆ‚43ª`ÙyØUzàz㙉œý†[òÛâ�ƼŠZ•OÔ-£Ù™I̤¸Zr 476䪻zò’ãÍ’9¾9NèRãÞ�^fj¬Ø뛆ù¶Ø×4EïŽMêùÆ—:ô¦)~ü¬/'ý‹Ü2ÁSj‚ý�ÉupÖ¼#«ºsö>ñ;fRfɜƃîçD…½�Ó–÷y»­£¾#îNàþ êù­"î5„߈„€;wîÜ!¸Cp‡ àAÀ‚€;wúîóÇ~c¹Öêª`°f tAqÿà}ц†‡ræô0x˺À¸ßw§ä’-½î ù+ê½ê'úÍõ–Ÿáw‘¦õ0X³ºÀ¸ÇÊ¿—TµGå.U‡—KÅøOhËågÔÊ^ü:�Zk¶@w{¤0ä+"Qœ³BwùšvÀÙ/ìåTF¹ª€ÄÞ t�qÉUä{ûÝN± wûÁv““/qÇ[ýÐÅÆ�®Êu]œ}?î…!K8÷€;ôíáÎÖ= ¬;¿Þ¬×œ©åå"z…;à}¸WÄìö†•ãå`Ö†E;ÓnŒ—ŽT¯:‹‰aÍèpfFåº.¼dÌìLÊݰìι Éu™S®Å«pÇš-ÐÅÄÝ'rbôZ3½½�Xå_¾k¶@ßîŸLï6Ë}aÍèâã¾Ö‚6‚. îÜ!¸Cp‡ àAÀ‚€;w:#î7!èÂëØ¸·Ö!è‚«¸CÀ¸CÀ‚€ûÒUH ¸wàÜ�Â}œ•þ ¸M/>3þ‰lGic�Ó·ÍÛ™7}E©JñDñ/²¼‘?ªˆµ¾'ÂýçŸæ`â®Þ¿vûS|è܇µ#£w&w®Ëì&»/í³ÚùÈY>�WiÜáuA�ó›ƒøÀýø¸·[‚4|¸4ÍñV2ûÑlG*ª„]¡l=–¨›RRDéÖ|0§LtªÞO,çCD¯.…¬üz€Lw,T�ÜJ3ØœÅ;9?H±9Ê>„Ù?wâZ231aiw‚ »“¼vÛ"܉³Ûw˜¾ †_‚a`g”dòí ö ®)§åšmÝž�Ù'&“w$k×Äí ÆkÆþùŽf•ñãÒÙ;êèë;;œ­á/IÜgì»?ß¹kJ¹fOðÇu> UZ¹BüÄ™l÷w¬{‚M^8¡º w Úm\éŒM5îŸÇ=Î6˜Œÿþô@8ìvd ¶é~Ä-湪y“ 6²™ä#ÕÏ=!ÆxG—o·Ñÿ Ké�õz8” –Eb‰2�•§ôº99u—çëÜ)rq+ÕlÜgÊÌóm³kÌàµò�»3wÙNÞ–¾.›M‰û5åM8œDz•ÃÎŽ°t¼o›‚”o3“œ°ÊÊcº¦�ó㵈ë×&îXúÙ¡b”Ïã1ªÊqñJ±¯[wµ3#Ï¥­;»úw9›òuLhÜzòXÉ«WWz‡ŸÀýó¸3fÚà s™ =:z †ãáT]‘×n¥ê Üu¶FòGÜvÎ˸·[¡4Ÿäoá2ái]J@DFGE(“'Ë_¯:ÿ+¶Æyu2sr㨜®cã~ M÷aÜ …;· w[!7“ÜÙ™¹»ÃVxB({ÍÇ0Ó2?™m˸#wôÈñ®¢Ÿ6äè‘M½ G4œtÝ]3®õEK‡Åà~'©Ÿ× îöD3î¾GÁŽc˜ÐÃ]ö¤îtâ;ª÷ª"9LÒÿVÒ¾&�m´ñ¯=Ü)O#ù¸çCõx8”Uó;Î`&ì931‡Oò,�}Íþ³z†;¿ê“{¸'ÉáñüûÏ;3bM¸³Ùž ×@ÄŽ¼Ò]v\& w…”ôÛå`³|µwfV›bÆÝž`é^Qö�ro_mÆÝBKÜËWýÉZâã¸/ªl&ôp·#~ÜeO½ó9³Ü5îq=;˜aÿ"¤ÇŽdwcä’dÂff¤�{8ä%7&Ì3zb`ÓàÞ¯¼é1…‰[õ˜�¥Tô­!“.k0>þkÅîÜ4'7¥Å¨„t>™>îPU|÷kä¶Ü)+òØW`gFfb@Åmö? îê!�T`5p—Hцrb¨¸šgΧf ›p7ó¢lÙM²¯”‰fܯÆ�ç|MŸ2ÎŒr™ÌAªêÀýó¸GE¢.;ƒs·^o‘Ñ%~]YÉ„�é!A<¾ö¾ÛÙËêl^2 dYîªËTäÄaU lXì…Þíîî>ªìNÊØfJ!çÑæü»:ÙviôµS¥NnJë§²ªŸ�äçïXfnÿü³bÙR¾»þjGÒÁþ:Eß±Þ™1ª!ª´îÒ�¿íá>!îê©ÄîÊzª¹AqûçÁîômù%¡61ÃÓ†?ó€Q&ó÷JžùžP4N¨ê±7þó΄WŠê,‡È½ös÷»;wä � ¹H¾23TÕW*K¾c÷ÏÏ̵¹ Jòž¿êæ!Vg½Ÿü�¿…‡ î™°ôzL6“L‡šŸ‘s)<íÈCSŽ�ò[)òÒ…=â•RŸãïER ´Ð�jDªOnJãÝ…ÏM'ëùŒ²*„ž‘ÉŒsòAfÔ8sW7s[9ûĸòÝËWM¾&g†�*”'r&è 9Ù.¿Ú‘çä©Ì525CÔÆD¤ ¡a¡ ƒ{”Èu™çÎ*YìB8UB䢋7…°ï¹þ8wˆ>·”±wöÝÕÎ(ã^µ§Ñ²ÐEÁ]{#Q«G£Í–œv“Ó…=g¿9®Çív¦�/CÇ0îðf  „{Õàž2hW(&j 7u—x§ŠIFâ]îÐÅqfG8˜[iB›cuw~Æ83Àº˜¸×¬œX9.<­JKžò¬»‰#Mu«0Öpf€;t�pw»Eb{mI,�_^)·_,÷F-g½töýq´íjÜ«4TÕ¤Wá»Cw·ÛB ¸naOˆÙ™”[ŠPtñ©4<õÇñ¶= ™£Q«Æ=�‰Hè"áîN½Ñóé½½ �¾Ó;GÇÌ–yT‚A÷£°âÓ.J4¢gÛ»hWè¢ã^Ø-¢½ Ë‚;wîÜ!¸Cp‡ àAÀ‚NƒûMºð:6îøSdþòwîÜ!¸CÐ÷Í7}/²õúxš¶Óãôñ²o›·x“÷WvŸ=ª×3ã,ŠW)Y“,•~¾n6k7K�Óã*»§ôê²<™:ú°Vn©ØÍ´úÐuò”y¹û.+�þÕ˳õ´?ŠKÏÈÓ¦'÷Nºé;yz~ýpÕ¿ªVúv›.éM_Ñêä´l}¯®™µÝw�|Ù65+tBÜ3aN[»•£�ªÝ–É‹‘«ÇÃÉl½_¤ê™!Q.Ûmõ˜ 9Ù.¶Ò™p¨.“ÍÍã}©~‘|Zj“ÙæeRyõv~7vvðƒ:w9Y¯”LxX×ÉKî¢Lû™ W¡³qÎ> ò•Ã5ª ÎpÌiäI´G—’óñ¦«Ü¨úWU¿°ý— K 4B�L»e±P÷ê£]±ìe“- œ,(?-îl‰õv‹ðÈí¶.b´B?DN†‘Ø�›e|Òét�’ÓÑ™ æêª‡šÍv^“™rÝñ|òð}i·†ë5ßa‡qçRw]§†a,òþB&ªoy}ˆvãV2ëÇ=&è”íVŠKÉùNš®Ñ¥´[³3~܃¡CUÿš¢ê“ ñ@M穹¢Ó„&9Ÿ$ò{ꦮãYΚ5Ù2áÔ¸ë¾ägòÝ 2�ÜÈv›ì£Ÿ·KDºdG’¤n÷†¨Ä]u†­z×ì`ûA3S‰ŒdV¡qWÝÔŠÝÙŸ¨ˆTE dö"‘y¢ b$¨W…‘ÈJÜÛw]§ô=â{[Ú:öèdúè¶Äì>Ùõ¨°Ã"mí�õ¡¦DÕ“’¨xUïNÔ䃫§^�Ú�™×iùôØ»œ­Y¡_ƒ ý–= p§ªÝ»Re+"¨R�~OMž3¡Nák�[¡¬®«ìŽyî©*›nèô¸Ç_¢öm·fBõ@r±-=$FÙ ×£?U£Ô ¤Èº�“­!ÜãAºÁ÷‰z• Ù¦ÿ$SY¥üʉ1¼ÒnyTØTòó§ÒXyéÝÙÚï¿·ÎÐÃ9@®ÍæP’ƒîªN”�|eÍÛ-yRe”»ÅÀ› 3HVf­ÎðÀ"ùNä×ôÔûí¿qïdvÒRé¶Â��ÑO� (Yt�mälí‘÷¦«þuEÖ"n=°zŒkCU̇‚!šäðW•ŸŠê¡“žJO\/;Õ½œ˜ãgÀ½ý`F$÷Û[ÉPÞZ”FF9!y¦ž­ùJ__–Ù"¤xî”NdJz!ƒa‘êJ’©ìbdÖ]ÚØ.1LV™m·ò�¥­ÈŠZ¡4š“»rK=gF׉Œ®(©î– :&9˜‹[Š….gh+¸µø7«' ’qªz ™R©Q+%=.½ËýÇÃ�| eÊçÙpFWý«ãžOÆ=Ü»¤×pLh’óöH-(¸ÓcQØË^ö_WŸŽjk�Þ™ &Û‰š’ó·Å¶¨•«²¬lÝC<øë¡i.‹SS¯©áï=²IÌåÙì¶/þïÿ …ª9Æ?×ä ³‰åÞ ÿgu|»5ðfHö6æz<à0êMÎŒÛÆt©yåܺáu½W±Û‹máÔÁSûÿo0þƒNËÝ"$³pé7}غ‡‡Û­Wí„{Hö¯ê_÷$¹€~Üÿ汈 Mrf�FÕCNÖ×�™!»ÓdãÉšö°3ÊÏ4ï^µ ô¼`›Çƒ¥*1žÎ'—„öÝÙÄû|÷87}N>sãÖh®ßÙ#kšdï£q—âr¨H «ÿî=jÀƒb3 ȇÒ]ΨÝÖŒ»ì/i{ò½U�NÜy¨QN66ûÅp)™�Z³OåÓ à<åt•5î�>ÜÛ÷œÆ]Wý«*À}*êáN�9gP^‚ É™l=ŸôãÎ=ÕdÓc¢6P~&Ül×É�Œ)[¡¨¦g~:eãNíÎ7£B.™ÆTÜ’£È~ÁÆÇÜ¥.9øQÜcrx 7yR‚œ™°Ó¦2I;¬g«¶ôù£jˆ'“É9’]0®f“úéÉß-’õ<áÒm�ŽŽZ2�¬‹w9Ò�ÃÜq×UÿÊó�òrÔMi è’è:LèKÖ³�©%j“Ík蔸Ç[_³M·Ÿ[– pöɺ¿âù¾"nsÙ&ÜGÖ†ô$IŒ’‰Ût^:7j¼çá.o�÷ÐûGì̬­R'ªŠÐ»ÝÝmºsûµ qî UéäÝ4Vu¢ŸªC{P-”�Êx·ÊÏUÐ#¾�½~ž¯d×›úžšYdˆŽT݇ûyPÔ5¨…C¿=9÷ÃP5N¶ópEZ‰:ÏïfØÔ¡I^ÙNǹAL]ß®ÇÙ‘ÓÙÚ/f*ÖWï›ß0îú›÷¨üR&Í“¿uiÚ»Õ÷E5~塪™½‹óì[%§MÚ¢ ¢ŽÄ=™­+Ù|ã#ǽ44à0Ù©æÝû‰o™ž2u’£]vÛÕ|OH~É"¿/âZGäð—�¦¨Å¦¯GZq2£¯Œó£«Ì¥Ù[YUªp~ ÷4ãnªþuÅí*³€)dòò¼P'wé/ÒL]ùŠùA¨³}ìk:à~ü_"ø¡ãQ“úaìQ³aûZ_l�‹Ñü�xfMžëp�>�ë^¸o3/ÕïEdnÈ ½ÖñÚªäôJGÓoOPêvÚ—-³ö™†îçøWÄbø>º<¸w'€;tip‡ àAÀ‚€;Ü�;Ü�;Ü!¸Cp‡ àAÀ‚€;wîÜ!àÜ!àÜ!àAÀ‚€;wîÜ!¸Cp‡ àAÀîÀîÀîÜ!¸Cp‡ àAÀ‚€;wîpîpîp‡ àAÀ‚€;wîÜ!¸Cp‡€;p‡€;p‡€;wîÜ!¸CÐ9À‚.¼Ž�;}›îp‡ àAÀ‚€;wîÜ!¸Cp‡ àAÀîÜ!¸Cp‡ àAç÷û-»»»}'ÒÒqÿôe�õøÏ•tY5õÃ�Ž“êÆS_ŠÓܨõÔ÷WN«ïSë'Åý~K‹{º÷aÝ––ûg)ë¬Çª¤KKû�îøIåÞ¸1õ¥ 8é�ZÿþlZ?!î-§¯}KÇÙÊ:ëñ/é²ê‡ã§Ñ�¾'»Q©3âž:!îgéÆtðgÊ*EHuù?)�üøÓÖä²ê¶]Ù÷/ÅÉnÔ÷gÕ qï;Kåû>WVDþDÌÆ‰�?mM.«&ÇO§É/ʼnnÔ•3Ò~嬸gæo>^ÿr¸Ë:8ññsK7oe�ûpÙúû³×ããK[gÁ=ýœFšï>q#úg³_ ÷áýâú/ßÿÇë_þ¸·‡Eé@Ìf¿¤uרŸ÷€˜- g¸Ÿ÷ùÒã§¥Ç�ÆW—Ï‚{&l—ËŸº]ÎGx ,|æF}w˜ßWõÍGõú�ßÿQ?îß� ÷tÞi£Þ*†ÙÏzÂ1^ß¼Oáfš¶7³'Å]ùîfãd¸Ç­u?‹ª’və̌sýÆeÅÒÀý8¸¯”–ùcDíÝ2®\ûÞG'Å}X݈ôxÚÍ0ˆ‹×2õ~Vâž™z$ r¥ã/÷Ò±P6}"Üÿ Ò¿ÿ~ðŸ÷”bþ¤~ùÒ¸KºêéÕåz<(„=Ro_|Êa&¼À‰¯Nå{úqŽogÜëãÙz¿%Dr0*:ëõª3Èã> Ü��û=ˆ¾ï_Y*•ùÝ%Ò½“ãÎ]öŒÖ`¤Bˆ…4ß{4in’? Æ(gÛ§q?4•ÞöOþüc›q¿Â´ýõû+P_úç/&hÖq�zÕË;û™!»­ÝJîgbÎ`•:pÕ9¹u¯G<Ïý¤Ö=“³·Š&²ñð÷8þÉ'3ùÏÔ¸+-•?{B!á¾ôx|Uâ>=¾úøõ‰p&úZâ.10žõÀ©÷s�È#ô“Ë®„C¾{Õnõ�uO×O†û_õÆõ‡d鯤Ò?ʸÁ¯dÿzåûÁ¿~YÜ» îq«‡?†Û9$³ÞnuJ â¡j¤ÁüI}÷ôü¨³ƒüdü-âÞÖnw’‹SxRùŒÑîZÏɦ?.îÒ¥á"|®´2Ü“‘ˆåLKÝ€ÁÎ̆Õ#�¡x®õ½¢#ÖÙ ÅBõâþc÷Wléé£msù!GüøË/�õ‡_÷öÅ6Ÿ'A°öÅNé⤃9/í4ÎL$rª‰ÈLÅZàǦmå¨�U6#ô-;Àý¸‘ÏÉ�7¸ßT¸¯œ÷p�ê’ÒG7`°O#D�tÛwõ¼5÷jEªÏâþÓ'¬»Ü~õχWöÙ‹ù£ÎŠÂý§³áçøúö¶dÿ•Ö}X9í§;™­Ÿj¨zJg&ú˜ {:’²îõüB0¥ ffŽ…{íw” HÜiÔZ+�wnòªbÚ€Ñåì³¥—V½j¬û¶w¯ê騵prÜ_Ió=üχƺwJþÉ‹ùã°aÿ¸×«bàו!Æœéøž3ØN±•¼3H—&R'¶Îeùcþ�x¨š{4^)²'¿VuÃ.9D¥ŠmžîGUT?¥u—ÿ˧øš*íê©Ýñ¦èÍq83ÇõÝïÿ 'ÙŸ¿o/­‰_"Ðí¯¿…ÑxÔëãã¾{•?ÎÜó¸÷Ý/¿4˜~øðˆàËâ~È£ª{Fg>°¨ŸÇu,b ;DÆð;3ÿ�¡ªV¥ô µtxò?þ;3Gà~"�÷Ý©OW/sCõá•ÖíÒ¦v?S–;ÕëÓ”{Òã�­Ã%]Vu|â7"õ¯Ïù‘_êFœôFý»q»{úºï¾=[Yg=þã%]V�uœê";ƾ'»QÏÆûOOˆ{o_ß)»òT__ïYÊ:ëñŸ*é²jj²cêİOuLN})(Nz£~üé,¼ÿôÓ�'Äݽ±{Ú¿î·{ãle�õøO•tY¥^2=™ŽxƒôôPœôFýøðÿ�^?AûGW"¸¿·÷ý ÕÛ{ÿþYÊ:ëñŸ/éÒø“ëKAñïºåÇ»ïXxºDîp‡ àAÀ‚€;wîÜ!¸Cp‡ àAÀîÜ!¸Cp‡ àAÀ‚€;wîô9õ^ÁŸ–†.�v¯`ÝPèÒè÷+­X8º$j-ýÓº˜ŸÅXÔšIEND®B`‚././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1760000640.7861156 trezor-0.20.2/docs/sign_tx-trezor.io.png0000644000000000000000000004730015071675201015120 0ustar00‰PNG  IHDRžûRyoÕtEXtSoftwareAdobe ImageReadyqÉe<PLTEÔöÿÿùÕ†¯Ùÿ­­îî�×Öëêɗׯ†ÿvuvÿnnÿÑѳ­Ý˜™¦êÈâØ°ÿÿô¶âûýäºøÙ©­‚vÕ¨}YëÝtw…T”Ëôÿÿ|¨ÔÃìý¥Õôx™ÓÍ›vY`nÏ`YÏJsНˆuuÿíÆ“é¬Ó²ßÿçéÌóþÿLLš–œ—ÚJ˜³Ýš ®ÿ––lâ•äãäË–Tz‚�Ù·¢Fr§¶Øôµ·»‹šÞ–ÄçÜÜÜBCn«\4yBBúúú3J§l´æBBBÌÌÌÔë÷ÔDzåëô²ÄÑæçè·¹äBI–ªtEøÜµÿõÑ–I=àûÿÿþëòòòïð𢤩㼎úë×ÿýàìþÿÐÑÓ™‚u³¤ŽXeœ©Áäÿÿú33_Q±êÿôôùÿÿÿüý5â±:ŽÉšÔõuy¥åŸ_33—ÎóÅñÒµÆå…‹”ç×Ç¢wuºÒíÕàïá´z›lHÒÃ伇RšãŸ©¾ƒ{Ÿ[CB«îÆÿñêåãí¦öõahuïáÔÅÕâBBXKƒ»§è_¢ÕóóüÙÍɇ‡…çúð5®êïëÅÿ&&éÔ·Äãóõôõ33�ÞñþÙ£]øîëÙï�Àè€ÄÆËíÒ¦†ÈðæÞÔ|cE­Ðê¾·«P™Þ왃½æ×Ó¿‹”�ßçóìòñïîßÿòÝåðñìä寠ÞîõÓÛøçÿÅÅ­°·òðåÕÖ×iq~÷ðöçòü¢Ìšññìõÿöåʬ@T|{N?„33YZZ…òêúôø ŸŸmqj¨´ªœ�~hbh–ßÀоÆËÏ5˜ßf›ÜÖØÛ¾¿ÀÜÖÛ±¬«~aqÝÔÐ3�¸ÿøñòáÁŽÑõd3YûÚâììíÿùûËÅÆ®“{ßÚÑÏÁŸ ºÓÞúó�…¡îýôöðòêêê�~öüìYeT“«±äì圙Þ÷úßúýùõùþðï÷BXbóæçÆ9òïòõöºôÓŸÐÀ»ÔßÑîíé434›YA¹y=ñöðòô÷ñññ>\�ùôñ‚ž¹óÔ¸âÏ¿dXAêíæ�zdÍHõõõÿÿÿ£ßaKVIDATxÚì� \”Uþÿ‡‹Š„ ·Æá6—�•À´FLJp@p�Q†¬ 5/.Šim*••ŠD›i+Éj›]6·b½�ö×ͽØþúÕºYÑîØo%jwóü¿ßsžç™á¢*~?/�gžsÎsÎy8ïùžï9ç¹hÎ�H}Vú�O‰ð$ž$ÒåÀ3³;G&gÕœ5îtó8}1NaíZjÆ�gf}B­¡4¡fZW�ÜgЩ߽¸æeíã»õï.eqÎt5óâÏ$Êùz'â/'>ÁYõøY¿a_¼2€��‰©â+¦ë˜=W­!ÇÏ3:õWãÀÓ½%´Ìgf©!™Út âYê.ӓɇJ¹'yœ[ÖyǹsY-pMĨÚ}�â™j0f5€x�ð º}µø-AtäbGÇw0]‡ìÅ´§­ žõð$S•Üu:U“÷90;wÃHçYrÌË�¯6ãJ«G‚ŸÇíêH€Ë»ºÖàݞ 'BÊœ,�!!+« !„àh´«bŽ6l�ÓµÏ^¶‹ÏCiS<½Ux�|‚jÓ8r:j³rN«ÆË€SD`Õ¼9ººTáé`; Ü@5ÁÎxÖ¤¦¦&ï«6ÔÆ+Ø)¾g²|Ä­Å9s¤¡¶IÅÓ9û¶~+x�o|NVi龎ÎëèÜÆÔ¦ÏÓ|Ц´zÃ4ç†OÆÞyƒÌÍ´RDkžl䎗v6±4/õL{<•RKÁ�œ'¼µ:ŒTðtÊ^%¯F6âò¼ÒÁN d­Úá;MGh’~≳<²Z4SêCVtƒb‘8´¥|ÌÂ;yg ²Hà;M|˜~vë)séÀ³¾“ÎGNòˆÞ=AÔ¸þ™�ú-ž †jlþ¦,n‘RK Þî@T¢Õ–ˆÂÙ£œÚÒŽxNKö擜ϼŒƒÏ@Á™9 ˆîç#¦gÇsR®â™_SªNÚ;áÙTk(Mä—*%È z;åA8¾'®AêæéJÅ%G|Mçsðòºvü`°YÛvhÄÇR81£N,A?_š,îð(±S+.�;Gç>MLme9òÕu\5Â+@1k]*¼‘ZÃ>jÓ�84Ê™Çç¿ä ƒâqá±6ëø™Žü$Ï8«ãvœ–/ÕU税%lJÅ8:Uä%øâ;º¬igΉ§<6R¦åuóêÕá›uËÌ~�jiVª<P:�Út`ŽÜ§%ç$;7nÓÙ[º©‹¹75u–—{îáÈ1Ôvq~†\kUÏ7‹št@O,õÍë¸$t^¥Ji͈ðì %Ë3ÝÑH§U{áy)51±Ûë?õõt=áI"ž$áI"ÆÒÅ·¥zÆFóoÞåLûªø¦·Š \Ʀïå!ë»…§ö‘Ä Ü †Ä# dù·úå9z …ë�‰ðû‡;A9&ö\Î΃ø«ØŠ)¶N¼Mͪ¢E¯|Í6�ÃKÁ#xžª¶&bõ¦çìÜùBguó§‘k…Éî‡C§oNl“»?±ãNB«�3ÎÑÃAâ8§0Ìê5C¡åpJM·é;+}ʪKNçu?]w‰ñtG0åîOÄm,lÓbböîåà¹Èß–Ú ÒûP0h<½÷îÝ»T3rÃ̘˜rë–˜˜ÄÍ…)‚ F?ÖâÆ•zÖlŒbæñFžw(m�^ܲâ‘ÍüãÝÎ…1~ Ÿ£0üuMǺ5—E‰ 0™vêÝœs£,ÚÅ¢z"‹0\P?ã=.<{E_aåÌÅcx¹ÏªYðpÅþé“�ƨNJמ~ééü©-Ÿ—À÷ä|v�ήã™1AäxŽ´±éƒÀ”ž–ô•žÇ¸]�<Çòô?ðÈW½ÇBH,ìî]ªïžÆ$–V<œ¹çhO.Åc,ã[ôÚSã4æñw˜€ƒ$öŒqŒÍ¥xåß233¡íVþí•QÐÚИÚ)Æ{X'x6ç óóõ×_ŸÈ6·1ÖïëyJÓ÷£�ÃÏŽ§Kñ=œ—â“vqY”Þ� «Ç*Ê‚JB�+}Žqü˜Ò�ë¿{1üðØWãÔƒöÔ–éSŒUœÓ²¶xjz O¤ó§/õÈ]ðÙ:»ŽçᘑÏóÞðÔãnÌXŽ'3ÇšO°«Aã}qw_�;#W`‹Ýýdî«vÏÂV³Nåx�(†æL/²FhiÆUÐØæñˆÀ¨;,.Å«mçDCcVpëz ]Åš[Lˆgv±+óCëô–0ŽÖ)-zóÆß_×x§ÉºøË÷Þ«€|ªEŸVüÖ[o½gÐh§”n4¾>Và™öï•6Oó»>"pHY°Y\€˜UpÖ(0�Z0÷w¦@�‚+Œ+›ËîU«ƒõ@wcüVÌãÇ`ŸÝ i«´P0ËF­ß®ç?‡ì/7çï°Ù˜Ul¼s=?EøQøô"�ýÏÑ1±æA1›<]T<¹u3²¾�SÙ÷ŒeæAŠ‹ºGx¨Ýó=ÁÈeo…ÖýŸ×�–tæñ-ë(nºÑ16ÀUî‘H�çÊ×^ô›Ø\öŽq¥ lP%68]q‡m¡qŒžEdÍ0Ž9´Ô‚©ÓÀ̦¿~Ôÿîa[æmäæ ¬ç¯툘½YÇ™Àn‡Í4y€|n<±zÓO�§Ê¢Ò‹ïàyfL…êq<}!·Åư-Åã¢Ìã§[ž)‹R«¿©O°wÇŠ§�±„üŒÆO?æx²…Ünr<+ŒÕáßzðF>; Y{ª²u½`ÞûPçtö—Îh;?ȳàÉ5÷¼³²öˆHûm–bËÅÄtÓ÷ämMéRüØÎ†£±qR4î=lúĉ9z—báâ.öàFîÐ�ãR\¦™2†FŸ �8Æà�;ê;@Ë¥ø€¹ø31OÌû\(ÿ´€§îÆ‚«Xó¸ß£}tà©”Œo, âyŽÂÜ9ž�,½x%æºJ{*lüÞ²wèÕêdLn.Ä:À/Sƒ¿ÅÏñlv³ ¿­ñô᩵§V-F×ûÐùÓOuJg¥ þ¼52ž`Ëž8J³ôƒ0Bõ='ü ºçûÁŽZ×BÇ^²…§í†õ¼¿þàÂ¥xÓãØ›Áz¾1îØ´ŠF0‡!eQ.ůÃÏa´î˜äý%1¨bÙ`¤ŒISŸEèdç­Yq#°•Á-Ž8qrLŸƒïÏ䎣u1tªNä9‡9ã™ñû™Å¯›ø‘r¦ ¹GÉ�K/¾‡g¨÷ä»/Ëþ1þß-zµ:ir?ë ›¡P\ÊNðÔÈxò=Ä~²—d2‰ƒÙ�—lbÉýâN,m‰™ˆãïMˆ§eÂ�àYZÏ” Ë¡�â¾ç xnúÛÚµ|,oÂñÔ±t¹‡÷îžù¼³Û8§bÜk§Ê”á üõ�`ÈÒÑå´ŽB<�|Olb°5~ˆ˜¯qãðŵÅ>Ü&o‹ç(a ;à‰¾'� ଵÁ³Å"~PƒáX=0«ÂîŠL‡ˆñÇbø( �¯0Žûã)(¿MuŒâ„â*ÖÏQçÁ5_7Ê·nÜØ{ÓòîsZÞŒè1ë«ÐEËvŒ¤‹ü-—{¦¼_·È¾çH=N�bï^Ž!Þ{»Ù¹ h9ž÷hÿ®åxúǬÂx�/´¶=?„Áá{®BrO0•hû`€üñìª+î°,FƒëÀ3�㌧èö�Qƒ¯)Xãàø� Ül ZˆAü@_ã*_ìØyn.ã¿Üˆ¶Ú�[vÎ8¤ãLÈ7~,4¶Ø¾3W«“1u̾ Ÿ`}¬SŒÜ-pàic¾ÅhOÏŠçÝæ7Œ>—ŽÏ{sQÓý".j¦ ã‡6Pà¹4…ÉxŽ\ÁNbbi“Š'û‘;ó�´ÔÔ�¡ÑBcØÄ™|>IîM}�¯ïû¤š½ÜÈÅÐFÍÆ Ð8ðl©?ôvîÜÄŽÓX§”Eà( Ö<•·ª‚gwbáHÏý�a‰÷A瞸ùÀ0¢Øxì÷¿¯_æêؤñ�æ¹0µ~gl�ôF xÊ&ãFÝFŸˆâ½rd}l ޶�=×ûßàõÎ§É”êøŠÑR¸��àxŽ›¦Çx–·ÃóÏò¶x¦�WùâÎxŽèiªY>þ|xþs™¸¼í?ËlgÇs1ö Ê)9��|®Æ2ï�¼Âè°”÷Ð÷/Y–*Xm6ŽÛèÜ)Ÿ{ûiç.Fèø¶aÀ_L¼Ô,:wdï�g.­6·žñ^íK‹§`8ãùëo7ÿ›[O%‹ø—` ÕÆ…ë2žãaîh*�{ ïÖ·Ýv~ßsÎYñ 0w:%§3�Ͼ¿Ì+ü\â»ÆžZOå]¸_ÛÄpž>æñø~ïsð¹·Ÿúžƒb–‚1‰‰ Â×·Ã^ŒB_¼SØôñ2÷‘ëÙý8ˆÇ>²¿<Ûá™-ãy}OŠ/†ÐW¶<ºT ¢ž_ŸÆÃÛeÑÖ…ë&žÃC£Å¼«æ¬C#ó_¾%4Ëçlxf‹i唜ÎÀ©®ø�§²¸¬¼gxjOqÂÐÈEŒ’øÐ¬jË€¹æn§{wÀýO‹ !ôâ1›ð}ïB�§2?Ú}<ŸÁ9¢ltÊNÿ:^hªq)Jį@2Ç�ᩯ<­àùâø•øm¸# ‚ðä=Àóõšš™ÅÆÝ<?Ë™YÌÇï=ô=÷ÈQ9%§38ÿ |úõ-ÄŽ½ÇxbO>ùGÆÅưÄÄÄšùâEÜÆáÏÑØ­3ëØ@çÎJ~?=LÞ�Dz¯À4?ò¯)LŽÉàóô=Àó•©ã&O*æH-æ^Øáâ–}[Àê¨Ùư$ð×[þkW®âyzбµþ¿`4Õ”CŒcöåÝi÷ñÄ /�9†FÀçFz}~χFø±úúÄê)9�A6'÷ñâq“ýá¬ýŒ¯OÞRÜÓ‰%Æø pÁz&¿¯¨lÆ’vŠ1øŠZs·žüÏm6åkêmcÍýðA¹(ðQM!ü­Ç¼ä p�¿rʶà´Ï�'ôÕ”phÁK=À³s=—œ|!#÷BQP•ã”g wû{ " "FÃöÎòž/jZ·5­¦KB.Í%!ÛR•›åmêmm#ÜSÝ;o§¯›ÚgÑÔtö5w Úà­ËtIˆrJŽ#åíä#þÙ�Õzº$d@^±DÔž„'áIxž„'áIxž„'áIxž„'áIxž„'áy‰”“:`Ö+§6-5'çôEo•ÓôE!zü,=~¶ãI"ž$“D"ž.pw÷0nš}üË€çábp6Ñõ¼âðl3ï9²[óžö1 þ0Æï0$:¸Å$Ú]ãìÁ°?|eüÃb{ëÇxfã¤ÒB£O¯ãùÏSeÇž ¬|±ñ³o7ÁzŽ}òKèzBçÞzèÐ�-MÏùNxz÷ O6 ��‡Ý>kf‹Íìû®6–1žN¯ …k-TñléoxšÇ�[Qhľ·­ç�ƲcîËaSûÆpw÷P£±]Oyh–Bkî]h↦¯rGÞfòÖ Á6;—]ÝÅ©ô-6_çÀÞö=Ý·Å‹Íquåhê*º$䂚¸O«GkîÚÔÔÞ©Ýù×Üwž„çåQ. ‰§ êϾ‹']ïIxž„'áIxž„'áIxž„'áIxž„'áÙ'ëžsšðì÷xÒãgéñ³}O‰ð$ž$áI"®6Ußý#̓ÊÏ�`ëæ‘&?Éç<Ùx˜z‰Êø}â>¹îƒ6u¹îâ)Ÿ[ë;{èîùëLxö–Ò%®9çM8:·Ã‘Áç<@ë/%h Ï•(Âà Õiº©Èë® ’ëØÕ“þDÂ|ùÁ�<,­³:gœï·Hx^¹„ûçñãç·žÖ¢ö�ïr<]“Γ§ß¹àó;™\Guåìpxˆ\žk×N9ã¨ô)džQ¤ Ò•‚ºög:ÏÉž—Oùï^˜Ä´ƒZõ¯-éðqbÚ-’ô™El«×›ß•tŸŽe[‰ÈéïJ ¿ —[lϧҼrÇvt+§¥zßpéÓy&ß?™¬¯~6S ݺYJØtx†Ô y>‡ç‚•’>mµíiÕËe0ë«KgJº\Ù„É‘ª×›~TJHqTjúÙ@‡Á§˜^àÙ:SJ˜ï¨Ha« ²ŒeÚ<#L�U>ffvSàé+ÁÏ']fÚ¹^g¹&râdÔÓb†(ˆð¼ôÖS@–^ /”vC�¬{ç]É•Y�JÞ3¥0=l[Iº?n‘²RÌáRFº„KŸ•d°³¥„wÂÁ]۱̃ç;}�T�ejÖi0˽å.I#gÂá¾RBÍ»R0@:ò˜- @)ƒ§|g†ðüÔH?ò]I ;$…Ù”Ji‹$aZtó'ì‘\å3áR+3-}È¡z©9\—xTâöܺš›f?]"û›ŽRš�j"ç1}¦T]cQNßW KœÑE³Kx^ žÜ}ƒÖ’> o…æÂ>5Tgâ¶¥Yë‹ÞY4” ’„Hh²¡ÑOsx˜ ;r¾5…Ù< ˜5›Á÷æÆñ�xˆ�—lÝô z–ÈÒtð2|%WHiÛ&hS"ý "�-ä Q*Ŷ´Šˆ›±ö:‹|&`J#¤`µ"-Äͤ´›±GÊ�<‡l›>óSe¾€ðì<#¤yЙñ^ ;0? ·¦‚eƒNqëÞ Ohè†e°ž†(x†à�å>N#ŽgÀ¹ðËÖ,�´l=wcïëÚÏæNñ•bù6y^ yËn�§Z‹ð=y­ãöøNxF á+Ï,�O‘GºÀSœþ“/(¿ ³W:÷ÄõÈe€äÝeØŠ-RN»Lþüÿ iòó3tQÖ£ºÉ–)aŤðØêV|¢ �¤Ïþp¾‡BG‹ƒÏô³â {~tî¾RëÜDz ¨ žJ¤38J¥„‡Œ¼é&ÿï$´úÜ»xªÉ–ZÿqTñ!ü¤ÖøIêÌ(Á8+÷¹"yúêlx*y˜ÃVè•Ó÷�ŽÅox3M}wh$gÀ¬Ëkþ­8€…öÞ:›`û®Ø>ƒ8þ©q‚v¤wäÒγÛ|{L8—¼sÇN6M§±rÞ<œ|O̺<ÅŒ£ºªzQÆXfP¸*³“<2Í ¥R€§XMšû¼BN¾§ZÈA ;Š#0@кÃLΓªæ¼Ty æ(E©3ÖDÉüNI£œ¾¥¥6³ׅMô¶üV$u»Ö)ÁÚ|“ïüøú#òΑµ]m²·ÛߌަŒsÙî•MOºÿ½c"¥"mçËUwn�ãún(çÑõ3%ãH9]AÆ/9æ—}ìv\ñ)îpäלóÃÂxîæ¢�we$áÙÛx*÷Ñ(ÛtI\FίE<ÓÃ?{÷Ój§;2ä Í• ?ùµ‘ #üª‰ŒxQ‘‹´É_çC-Oxö¸sOx÷ÑG[mŽÛˆÄÖW5¹8ñ„¹�&÷“ð¼`)÷ât¼'G–ûyoÍy²É�š™ð$‘OáI"ž$áI"¶E×ja‡—Ú0 > kéFê# ºò�å{bŸl}ù¡ky§ër­è½¯á£“ß\° cv€¸ ž¿áãeÈó4Ç-Ÿ#‘<‚Bì”Tú…\s[?÷.îÉr ?ŽköÄø�ŠœýÏ€1�¢˜Õß°Ôßp§>ÍvÈ :÷PCÁUæîÜüÁ�_CØæÆØB‡Càø¦o¾Sa[  6�[ý Õ)lbé7™1 ñé#F`—}�ðyg+wæÎH zч|êÚk8¹Ü…uÆóê(]ÀÓ寻~¦ŽÇ¯i×}ƒKñ�b½Y'£ö�…çAžN4ãƒgYQ syo,c‹ïÔ‡‚%õ•ñ\ÉX³Áæ5˜‡ŽÔ#ž<>¨Y¤bÐ`*øïg0uVh�(¯¦NËß…£hë W[ä4ækAˆ›Ì¥3yhí¾“—O+Þ+*9'úÓ>}-2yN€ŽPFS�YÏŸ)û€§9H¶¤W˜õô3èbÞ»SÏ}Ç€;_+: úž#óàÉwc¨ ñÍ�’Gi0ø¬Ígñ=kÚÐÙÿV�p¸ÿÿúKÐ_qN<Û�^Fh€lûâÞ{¡súåSªE¼A ÷”Ãä*ó£6e¨4bWöh©Á«Í¸áÊó=Cï<”5Ó06:xÄ isyOÅsÈ�¦·'üʆ&R»Œã¹ãÇ¢õ\i[;áWìcö�&ß †™côÖPƒ!,<˜ã‰=z!ôͱÐíÃf>P éÆ2ÀSbØ]éÍEΓ¥ab zí/ÿ,VplÌús:<‘íÏK#pÈcûàƒZiqÐ$ð~aóÌö�LLË3ðlŽN[”iáy\£Öìi§Eͧ¯ÜU£ bs¤í’‘u­ØÈ J@ãÛJÔ‘ÕxÕHbóÙË»ð7¬}ZíÜù4»˜–·8V�”ñ·ÎCm‘hüFžÍsürN«úò¬ÓËÂVÊzJ>3è0»4°ð¼`a_~…ö«¡ÑÕ×]wݵêJæ�Ÿ ÓI˜å8´³8åÀ»_;–IÔu[GlWžt½g¿Ãó %< O“ð$< O“ð$< O“ð$< O“ð$<ûžô0“Ô3ž„'áIx’O“ð$< Ï+Ozí©ãI/-$õa‹ôÄ7LÉx`#?€gÉ=!?þ?Räï†ÄeÄsì¶ø]Ö¯Yþjë¶]�ÿw]‡†1bn|ž\Æx°úæ4ûÿž ícÓßn½yÖ\Ož.Ûm€õÔ»áðQYoþèϽùÑâÙè5Ô«ÑËñôôÂÑ<Æ3Î+NAˆ¡×7¯h7ˆöŠD2£½ lh#Ïc¨›—W?€gɇ®ÉóZãÉvD»‰üá(¯Fâ²ïá9ËÄ!Õ4£ueÙð¹Jà™>×n¯4ŸâFƒ“˜ïÿC#›6?m–ÆzóÝŒU¬{íÐk7Wb>æ©vû:“/$k±À×[lÚ7«¬7¹_](ž|à¹yr6�4ç¹CJÁ3:Î ÈD�AÑnÜ>F <Ñ`Ê EÎÙPÏ`0Á¼ ÖäëæE\öAëÙz(«Üo–ÆÏ^eýê–×^ÍeÙëLëY±Îd~óÖô¹U,{–)Í>VfZÃÑk+Ê¿ÀW{�yPyáR›¯Ý'ãæá6–nÓúÛâvnÃâÉ€ª5y”çæ $FFªxFºÅ�1xzE{­Á0O7OùOLë™·Æ+º‘ðìÓxÖJïù ž€Ú�[l[gJÿ†ާËÜ`$ì·öJ?{)€¦q˜\�çž`7ÃÊ™vsø{ö`�î:‹õæ16¿Ñ¢¿xª�;ËÃn:w7‰\űhÚ¸=SϸhÏè€g^4ÇÉ“�ñlŒ^ìBª8äIPöáÎ]àé·î‹7?ÊñhƒçGÉ;“_ð³Oþ0ù}}ç»u“'ÉxŽúHDù9¨¾xæyǃ£‡®£=Øä¡nÑCÁr<óÀÂq`m…õ¹ÉÈx²5`Z=w°È5"“x£}OM<çVýu±ž¬bVùÖ\ÍsWý­ðSÄAêAÙöM‡ç‚Û)ãYز>bnÕÍwŸð°k§~´K;µ ¢>úßç¦Ì2](ž¤+ÜzÂX' ñ¼ÅjÇq9|‘ñÔ.æC£æâÐÈϬâi…ˆ1&Ï­§p÷»ýKHãa¿åå¹A…KóáIx^,åç· 8r‚oÞî�òûÕmv'`º|›:sj¹ðºž„ç¥ÑKáIxhÉxºíÀOO\‚O¾)Öƒ@|±(®‘/þÄÉkFü\ rã«H<Æu& ÚÁ׊ÜpùhkŒc;0ˆÔñ|׃³u)¯«óNþ[ÿß&�¼6ŸŸŸo»txæát¥[ô·5y^qq^yŠ«= ¼|±ÈÓ«Ñ 7|f^9wø*öŠöòBv!x_tòŠÄ!|tž—çŽè;¢iÚ³â™1†/�8ûÞI¤¼®ÎA|†<oð}\N²óÁ“X›çûcL— O·¸èH´r¬1ç„0”¯öÈxòÅ"O€+.Ž¡EŒTqã;8[ăU<ÁšF‹ Ä€ç¦32’°ì{xfÏ*Ï_hjø;;’™™‰ƒ±ÆÎ%ÖÕñ›y.ŽÈ¿»#eúÔ�`D_þõvñ!<àùý¿\æVeî±W)G툾¸xNn8…ÉQåxŠÕO¾X„3œ ‡Ê!íñ\ãé9”wînnÑ‘*žyp0=t¨aÙ÷ð\8+ˆÔW¬Ó�ÂE÷(±Æn>…ƒ¨Sï`<¯2Ï ¶N]¬3ùÎ*—¯´ó[g[hv™ëÃÌoV)pzQñŒ¬¢ª¼È5‘2žbµGéÜq±WãóøÊ�Ó!|‡ãé¦|ñâ„çEs;*æç[È<Ï“ðìƒxF̵ùÙzVq‹-ÿÄÖ7?²‰5vøÇä)ÍæYbÕ‡/!µX2nž%®¹•ãÙ2ɾ¢Ê~k—'’<‡^L‰¾:ðƼ8¾æ#ð«=r¾Xäé…{òå'<1˜Ù!ˆâDÇ“á¥!C×Äž}qh¤ýv†ÝT�®äW¸LÎרE”º®.ãÉ|ÑÉœ¥9콬._mÂË› ªõ÷[”Ë>/ºõ$]Áx._CûÄsá¬(&¯±+xª�»ÀóûÆï2Ë4}�ºjßa箦»ø¾'éÊÅsÔ¬ùß�¶ûžiöÀ_/³ÉkìE»ù¸I¬«ó¥vÄó«u)‡çgCì›Jó¡¾ß-Ú©·X\æºnûñÍ–‹?·Dx^éxn}'–l o±UðŽ[¬±»ˆKàåuu¾ÔŽxâÂúG¾?k÷=o±EÌîÂ'–¢.ÙÄ’g\ccœ|÷ŽÏãÄô|£§˜L‡8p6Ý F¾Ïƒ+'áÝÄ4ýe"žÇGò»;âòð‘<å�}Ö÷dß}¢ÍþçÝvëêÊþ÷™¶Þ¨šá¨Æ5Ñn^qž0°ÁI&~w†W´×Ž5�<ŒÓ!PÌ>É&×Ó Fç83ÝÈgÝw@²-fôq ”_?çææFc¢¾Œg–ÀïßðòlD�Ö‹O¸‰xù»¸Il\ƒÑíðôbqÏH´±;øýnqÊŒ¾›[ôqeht4OÂó:w¼cÎ ¹ ŠÖγ=žnq¸¬ÞÏ¡C£#q‚4š{!žqÑÊŒ¾®Šëêé;Œ'¿Ï½Ó+Þu)Ô¿Ëi£Dð{ØŸŒç΀|'gžH¡ªý�îùŽ<»Þ¹óitàŠy!žÌs�¿;ðŠÄ[…Xc4.»w´žÊ4©˜u‡€H§}7O�'õí}OqŸ{§ƒ¦7íöáÂÅü�ß§©lä¾ ož£¤ ÆïäteÖ‘GYüÊeqAryº�KÞÀáWy÷ðäwjJ�ÑCÅRPãP/~w†×PqccÑ;ò†F"žxG†<[¯â¹&�ÅÉñkÜ3úÑ�^|ŸðìÛxâ}îh‘Ä|'ã÷ݺõ?ØïÁoæ7?z-À%oä± Ÿm«]Œ7»²…ö(Øü-ÛîÃ*îÎlâ—:Éwº[ãÿwÔºñ¶ûG»^<Õõ •ibéŠÇ“ßÌaÅ­® ·‰»Ù]æÞ#æåá(fž{�¼‘#ø*<«hÁ›4}*nù¿G’ÿÅš!3óÜ*ëwß[Á'éwºóe)~]Tă&“ðìªõÄûÜ›í>Ö¯Z^›z7Þ¦.îfÇyN6ê=+DÚ©•òF�wÊY+ìÁØ©ÛWÚüì»Ù3öU¼K_§áx*wº <»9uOxžxŸ{…ý·¿µ¯{yî—¿ÝhŸ#":à¹JÞ´Ánf ˆˆ/ƽUÖ-¹à¬âx*wºž„g�;÷Šu+v&/HŸøþûïËÞ§yî³@¿8$Í»sä��xùuü йƒ? Qù_ÇÇñæ­Ö÷-Ì:µRéÜù�îO~Iºw÷:w§›/_ïqƒá ¿3£Ññð.ŒÞÁ“Äs¿øMÄÙÀSÃÜݺòo7·ì:üÿ|ä»Ù¿Z—²Lé�Œ‰~:+JÞ(Ïlû¦’›×é#ì®ÿj�а6TØ£´oŽÙõÄÜ*14’ïtçx¦Û[^XÞÝ¡‘ÓÍŒ¯÷D»¹¹á¥ï�üC<¼ËÓÍkÎ7yy‰ç~EâÓÀˆ³b=™ �|ØÖ7 k¶Éw³ã{pü¦Á�i7S6r„zü: ytêÇx6J•ub ïtý:FŒëæÄ’ÓÍL~bâ ÿù‡x:âí5”ßÜ&žûåIt<å‹ûØßvv3Õ÷|±./oœ"Ôå÷<±9’ÉSX3ÿÕy1Ö¯Ww×÷tºùâxâl»Œ§xîá9�ðì“x:n¾àAyx0_ñ×tp`ô‹BøWþÜ/“ðì<7_0þ4/ϼ6xòU"€±1ÚK<ÇK<÷‹ð$�§´éþðsxëŽê4éRì‰Â‚õáIæws©½ÏËè{Êx&„Kë ”ªuíQ)0}†$…™È÷$<û€Ð÷œ€_œž±4á5áÙGð$+Iê³x’H„'‰ð$‘OáI"ž$áI"<»¯“ƒv~l±ö¿ÀXä ̺ ¾¶yv‚uðíø �m·Ïo›‰vQ.>Ÿ©1wcypl´ø”Ï’ÛçÃç°X“ó!y·ï–p|³ÎMQ>A‘.®æã•X ”Yr_®…·žG6ä ð2 (Å©fÖëñ (Û^P«¬(r7Ö�Ÿqäf]$âˆÊ)EÝùž¼ª\ÎnXìÏÅŸj¹@-½ñöÁ˜•(v›úÇÚ–+®¨Á¨jXtŸ�ðìž®¯ <ð¬óßð¦�•Kl‹êcÚÏ—Vú8S¸½.¶.˜-ª‹=0» �7=[ĆñØÆºUne%7ÕE±Èº[oª³dTn²AÔ�‡•Kɨ߬ۗÄÖ�Ÿ˜¤ñ1Ö¸d°ÈûªU«ÔiD��á[IÃùl¨Äœozªú0ª£ý< r©{X©²ªÆÇ„“c êlÚÏ?æ�ûëlX‘Dd"êný¼jµÈÎâ{ñ§¹ r|ÖQzå­�Öµr6Ô´N~ÄfQ‰õÀ8þ²!³¡ò„g¥]äš Äïèh¸Ýuš¹*4‚Öís—,šÍJÄ O^q˜;œgI�æúÇ®šƒÁ›XFH˜V›¨�8 íßùA7ž]µ›Kßt«vûªý•뵟ߺ¨Î§±nþUâ7oËg�³Á:ÖÝjk¨LZTgቱ­#ë¢n ‚?üœ’ýU·×i¶Ï¼ß]„JŸ’J m»~å’rvÄúy”v»keÝXí¢ýЧ5,»ê1QâÉÏo]pýì�º*æøÆ�~V|f„Ì^´vÉUûç—T&Ý^L”ìS(2xyŒ#½Ä¶}ÉŠ�%¶aKæßކ¾jð9Õ°ºMÛë4@0œƒ\e^M‘3ÇOòÿØÀ¶æn¯³ägTÚ°2ðØþ°œ ³.[´Ä2ì@Õ.ž] ? üÓ@}–Ýô¬U”Ž™=¬ýÜíëüe^ÿðà�ª†ÊØýKR˜\~Ãà·çÉ»„gWdmZvûlh×ï¯z8²nÅ20��ßüçØGñ?ìØ'oªbyˈ’/¹¯ÌD]îMuÁà ·ÙN.ƒäÚ«*ë‚M ZsýìÎØ^Ú›–¼4¬ºEÌî@ÝlQ"»~xå'C>vúÞ¶5~F¢ù{ ˶dÁàÊ A“È`X]ÕUu³K*gß^·ä¯!¹Ä¾DåcÈY`��HeÝþ1ÓˆŠ¬³@r•y5åœ9îÚ¨ž*ØHüUAe¬Ûg/Àªó¢ÀË©\b²~®‘³ãg!þ4‹*ëvgˆÒ±× =Õ~Œðe„ì^výÃ%ûgŸYTg5gÖΖ]?›ðì"�××¹Þ4Ûú+h®ºÆºØØÜùÃêcá/Î-â¡=ýÇJ*ÁDñÄÐuÅ.¨ÔX‡Å.ø|‡Z?6d¾!f4 o±<Æ[ñ„Æ„¾Ûž‰LÐÆ<Æ»gÇ7ÀÔÂÄ'vÝP8ü»k•"Œ§È€�Œ�-\r{îûK¾‡âJ*_,´7ÍáÉe—#sŸGm_rßUKæ‹*ÿ‘WSΙ—9¬.÷öýIZ‘Tàù±vûÃP IÕ€=ù³òYÀ“ð?�œÑȺ_óÒñ�ÄÑÄS†,J*o��½¯"Á�5�ÏB ¹�¬gW]ÏÏŽ û [ÒÎØ¢rÀúLhl&ðl¬3�AiD3Å7@ÿyýÃèR6‚a¨³4„,دA8€*ìã>æ±8T@seJ*ѪbÏ ßx&å°%-äâø¶¨n}~¾ø,Ù¤Ýέ'ð¦½ÝÄi’3@Ï´œ8æV,nÑ’×à³!$k°h‰’ Ž®‹Z”›»d¾¨r ¯¦œsI›rssO,¨N#㉕ä:Š‚oȮȓð?MÃ~þ™—n;Yl="RXOd¹q·ö&8±:‹¨�8‹’ùp:–’Ê Â³‹VWClø¬+ÇÏ%¦ÈʺÊý¶F1ºläCQm¸©ne”#1˜ÈÊ:%ƒõ­»“˜]køZ‘û1ö$Ä>+ÆÎÚÏ!‰02U%—�û°Åñ­Ž©›->­‹êê*g+壋¡ƒkÈêŸþ0Ï«»a  s©JB°ÆâD•E5圕;w<,‰É�;Ï>É‘IÝcnZyvü,øŸrÁ ,ý5<~‰ �ÃÈÿ6>üs·Ó_Ý~©¢‰¥nªáWøÙö nêå¯:Mlý•xàl~»„à`ñXõRfÇW§@®_½Ýñ›"Ç«êœJ�3X»ÚQœ5ß)B;G:T¹}Îg :┉£bG:ý#8hý‹ã”ybí¯œbÕ³øÕjFx’H„'‰ð$‘O‰ð$ž$áI"NOE¶þ��¼�±#øÄälˆT6þ6j4³÷å�Ï–7‡:=Ùíi (Ðk‹›á{p|„é LÔr„g¯ ŸžÈ´þ!NOEö“m£%ÄÓ?�=#A"K„·É£ó·$�ÏK‹§ðt<_Ö[OÜ+”tŸÑ›:ÏËѹG1€Ñ5ÝñTd?)Jài³Êx²é›g`:áÙÛC£‚Óý¥ §§"ûIaÿ;S ÊÖ­x\Ðfi“-´U}üžjò= Ï^VZ¸$éÆ2§§"ûI�JÒ1–.éÞ déERð04rµ‘ïIx^¹»‹ëŠ•‹iñM\<ÄéºÙ·mÔh„gŸPYI“ÖÜI„'‰Dx’O‰ð$ž„'‰ð$‘ú5žß&*W{ü˜¸Â o–××ãåÈ'ÂçòÄz|ÒæòÄÉ6øLNN~ö¬Ï%'CdÉû°ÿþ.f}>q]|Ox^$™‹$Iâ#¶†âÒ¥ o²á³À¤Ý"IÁ¬¾ë¢ø&LŸ�ñxµS:^ª ÂëB%)$ßïQ žEÙÒ&—ð0´w¾’«ö¨N#ˆÍ_‹Â,¾R`³´W Öú‡éý¤`3DzHÁéÒ¦#«ñ±A.áxMhpþ¿ ¥Üµ'²¥XÛ3R µ0áyQ Ó°P¾Š è±!R° 6¿, ³¥‡‡M_ï ‘LûÈQ]Pz¸+‹�]Â?•tó9ža;g¢½Äãµþ:c. &Ù%] Y´˜íïf ‹(.yx�ãIx^òµÍ lþâ¸(Ùúµxðñ×üÂå÷N/Q>òõ j_“D"­NŠÕâ%Æc]Â}TŠÅG1ífÌüà/gè‚ü} : 0–ûnà¹9Ø}­(ØO‚äó‘í$4gÌ?˜§å–ˆŲl‰wß¡azŽ§Ëƒ/CÏ ÐEsyðñ½RÚWàìiD�E[äÃäô&dÝ�(V4 €=èzèƒ'¾›Ô?)ýA—Ÿ/lB�$ø!íÏœ8í¿<­Õ?ЦdE±EïëÙº¨|xù‡Ã«2ŠrYv��@¸޵ä‚ü€à�ï1 âhÊéY'x>CO‰ x¦ãeHh`_� 𜎻&„*ºw¼­pâxò+“rÑ@jýC 6*£h7PcóÓEaXú+Ö“wå’®œûÁó0‘ËKH‘‹]ƒsžq Oy gx×Ü 8ú"drA¡®ø gøx„éeuÚZÏ3™ÓšŽ“H}FMÓ„ñxžY›I"õ! Û©àI"õIž$“D"=0.20", "shamir-mnemonic>=0.3.0", "slip10>=1.0.1", "requests>=2.4.0", "click>=8,<9", "libusb1>=1.6.4", "construct>=2.9,!=2.10.55", "typing_extensions>=4.7.1", "construct-classes>=0.1.2", "cryptography>=47", "noiseprotocol>=0.3.1,<0.4.0", "platformdirs>=4.4.0", "keyring>=25.7.0", ] [project.optional-dependencies] hidapi = ["hidapi>=0.7.99.post20"] ethereum = ["web3>=5"] qt-widgets = ["PyQt5"] extra = ["Pillow>=10"] stellar = [ "stellar-sdk>=13; python_version < '3.10'", # Protocol 27 support (SOROBAN_CREDENTIALS_ADDRESS_V2 etc.) requires # stellar-sdk 15, which dropped Python 3.9. stellar-sdk is exempted from # the `exclude-newer = "30 days"` uv policy below (see # `exclude-newer-package`) so the 15.0.0 final can be used right away. "stellar-sdk>=15; python_version >= '3.10'", ] ble = ["bleak>=1.1.0"] full = [ "hidapi>=0.7.99.post20", "web3>=5", "PyQt5", "Pillow>=10", "stellar-sdk>=13; python_version < '3.10'", # stellar-sdk>=15 floor: see the stellar extra above "stellar-sdk>=15; python_version >= '3.10'", "bleak>=1.1.0", ] [project.urls] Homepage = "https://github.com/trezor/trezor-firmware/tree/main/python" Repository = "https://github.com/trezor/trezor-firmware" Documentation = "https://github.com/trezor/trezor-firmware/tree/main/python" [project.scripts] trezorctl = "trezorlib.cli.trezorctl:cli" [build-system] requires = ["flit_core >= 3.11,<5"] build-backend = "flit_core.buildapi" [tool.uv] package = true exclude-newer = "30 days" # Exempt stellar-sdk from the 30-day rule so the freshly released 15.0.0 # final (needed for Protocol 27 support) can be resolved. # TODO: remove after 2026-08-04 exclude-newer-package = { stellar-sdk = "2026-07-05T00:00:00Z" } [tool.flit.module] name = "trezorlib" [tool.flit.sdist] include = [ "bash_completion.d", "docs", "stubs", "tests", "tools", "AUTHORS", "CHANGELOG.md", "setup.cfg", "pyrightconfig.json", "tox.ini", ] exclude = [ "tests/*.bin", "src/trezorlib/_proto_messages.mako", ] [dependency-groups] dev = [ "autoflake>=2.3.1", "black>=25", "flake8>=2.3.0", "isort>=5.13.2", "pytest>=8.3.5", "pytest-random-order>=1.2.0", "tox>=4.25.0", "tox-uv>=1.13.1", ] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1774956357.3029993 trezor-0.20.2/pyrightconfig.json0000644000000000000000000000064315162727505013632 0ustar00{ "include": [ "src/trezorlib", "tools", "helper-scripts" ], "stubPath": "./stubs", "pythonVersion": "3.9", "typeCheckingMode": "basic", "reportMissingImports": false, "reportUntypedFunctionDecorator": true, "reportUntypedClassDecorator": true, "reportMissingParameterType": true, "useLibraryCodeForTypes": false, "reportMissingModuleSource": false } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1770727810.2852411 trezor-0.20.2/setup.cfg0000644000000000000000000000175615142624602011702 0ustar00[flake8] filename = *.py exclude = .tox/, .venv/, build/, dist/, vendor/, src/trezorlib/messages/__init__.py ignore = # E203 whitespace before ':' E203, # E221: multiple spaces before operator E221, # E241: multiple spaces after ':' E241, # E402: module level import not at top of file E402, # E501: line too long E501, # E704: multiple statements on one line (def) E704, # E741: ambiguous variable name E741, # W503: line break before binary operator W503, # Annotations plugin: type annotation for self and cls ANN101, ANN102, # Annotations plugin: opinionated warnings ANN4, per-file-ignores = helper-scripts/*:I tools/*:I,A tests/*:I,A known-modules = libusb1:[usb1],hidapi:[hid],PyQt5:[PyQt5.QtWidgets,PyQt5.QtGui,PyQt5.QtCore],noiseprotocol:[noise] [isort] profile = black [mypy] check_untyped_defs = True show_error_codes = True warn_unreachable = True disable_error_code = import ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1770638540.7578576 trezor-0.20.2/src/trezorlib/__init__.py0000644000000000000000000000210115142346315014760 0ustar00# This file is part of the Trezor project. # # Copyright (C) SatoshiLabs and contributors # # This library is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 # as published by the Free Software Foundation. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the License along with this library. # If not, see . import importlib.metadata import warnings def __getattr__(name: str) -> str: if name == "__version__": warnings.warn( "__version__ is deprecated and will be removed in 0.15.0, use importlib.metadata.version('trezor') instead", DeprecationWarning, ) return importlib.metadata.version("trezor") raise AttributeError(f"module {__name__} has no attribute {name}") ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1782395835.339361 trezor-0.20.2/src/trezorlib/_ed25519.py0000644000000000000000000001663415217231673014401 0ustar00# ed25519.py - Optimized version of the reference implementation of Ed25519 # downloaded from https://github.com/pyca/ed25519 # # Written in 2011? by Daniel J. Bernstein # 2013 by Donald Stufft # 2013 by Alex Gaynor # 2013 by Greg Price # # To the extent possible under law, the author(s) have dedicated all copyright # and related and neighboring rights to this software to the public domain # worldwide. This software is distributed without any warranty. # # You should have received a copy of the CC0 Public Domain Dedication along # with this software. If not, see # . """ NB: This code is not safe for use with secret keys or secret data. The only safe use of this code is for verifying signatures on public messages. Functions for computing the public key of a secret key and for signing a message are included, namely publickey_unsafe and signature_unsafe, for testing purposes only. The root of the problem is that Python's long-integer arithmetic is not designed for use in cryptography. Specifically, it may take more or less time to execute an operation depending on the values of the inputs, and its memory access patterns may also depend on the inputs. This opens it to timing and cache side-channel attacks which can disclose data to an attacker. We rely on Python's long-integer arithmetic, so we cannot handle secrets without risking their disclosure. """ import hashlib from typing import List, NewType, Tuple Point = NewType("Point", Tuple[int, int, int, int]) __version__ = "1.0.dev1" b = 256 q: int = 2**255 - 19 l: int = 2**252 + 27742317777372353535851937790883648493 COORD_MASK = ~(1 + 2 + 4 + (1 << b - 1)) COORD_HIGH_BIT = 1 << b - 2 def H(m: bytes) -> bytes: return hashlib.sha512(m).digest() def pow2(x: int, p: int) -> int: """== pow(x, 2**p, q)""" while p > 0: x = x * x % q p -= 1 return x def inv(z: int) -> int: """$= z^{-1} mod q$, for z != 0""" # Adapted from curve25519_athlon.c in djb's Curve25519. z2 = z * z % q # 2 z9 = pow2(z2, 2) * z % q # 9 z11 = z9 * z2 % q # 11 z2_5_0 = (z11 * z11) % q * z9 % q # 31 == 2^5 - 2^0 z2_10_0 = pow2(z2_5_0, 5) * z2_5_0 % q # 2^10 - 2^0 z2_20_0 = pow2(z2_10_0, 10) * z2_10_0 % q # ... z2_40_0 = pow2(z2_20_0, 20) * z2_20_0 % q z2_50_0 = pow2(z2_40_0, 10) * z2_10_0 % q z2_100_0 = pow2(z2_50_0, 50) * z2_50_0 % q z2_200_0 = pow2(z2_100_0, 100) * z2_100_0 % q z2_250_0 = pow2(z2_200_0, 50) * z2_50_0 % q # 2^250 - 2^0 return pow2(z2_250_0, 5) * z11 % q # 2^255 - 2^5 + 11 = q - 2 d = -121665 * inv(121666) % q I = pow(2, (q - 1) // 4, q) def xrecover(y: int) -> int: xx = (y * y - 1) * inv(d * y * y + 1) x = pow(xx, (q + 3) // 8, q) if (x * x - xx) % q != 0: x = (x * I) % q if x % 2 != 0: x = q - x return x By = 4 * inv(5) Bx = xrecover(By) B = Point((Bx % q, By % q, 1, (Bx * By) % q)) ident = Point((0, 1, 1, 0)) def edwards_add(P: Point, Q: Point) -> Point: # This is formula sequence 'addition-add-2008-hwcd-3' from # http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html x1, y1, z1, t1 = P x2, y2, z2, t2 = Q a = (y1 - x1) * (y2 - x2) % q b = (y1 + x1) * (y2 + x2) % q c = t1 * 2 * d * t2 % q dd = z1 * 2 * z2 % q e = b - a f = dd - c g = dd + c h = b + a x3 = e * f y3 = g * h t3 = e * h z3 = f * g return Point((x3 % q, y3 % q, z3 % q, t3 % q)) def edwards_double(P: Point) -> Point: # This is formula sequence 'dbl-2008-hwcd' from # http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html x1, y1, z1, _ = P a = x1 * x1 % q b = y1 * y1 % q c = 2 * z1 * z1 % q # dd = -a e = ((x1 + y1) * (x1 + y1) - a - b) % q g = -a + b # dd + b f = g - c h = -a - b # dd - b x3 = e * f y3 = g * h t3 = e * h z3 = f * g return Point((x3 % q, y3 % q, z3 % q, t3 % q)) def scalarmult(P: Point, e: int) -> Point: if e == 0: return ident Q = scalarmult(P, e // 2) Q = edwards_double(Q) if e & 1: Q = edwards_add(Q, P) return Q # Bpow[i] == scalarmult(B, 2**i) Bpow: List[Point] = [] def make_Bpow() -> None: P = B for _ in range(253): Bpow.append(P) P = edwards_double(P) make_Bpow() def scalarmult_B(e: int) -> Point: """ Implements scalarmult(B, e) more efficiently. """ # scalarmult(B, l) is the identity e = e % l P = ident for i in range(253): if e & 1: P = edwards_add(P, Bpow[i]) e = e // 2 assert e == 0, e return P def encodeint(y: int) -> bytes: return y.to_bytes(b // 8, "little") def encodepoint(P: Point) -> bytes: x, y, z, _ = P zi = inv(z) x = (x * zi) % q y = (y * zi) % q xbit = (x & 1) << (b - 1) y_result = y & ~xbit # clear x bit y_result |= xbit # set corret x bit value return encodeint(y_result) def decodeint(s: bytes) -> int: return int.from_bytes(s, "little") def decodepoint(s: bytes) -> Point: y = decodeint(s) & ~(1 << b - 1) # y without the highest bit x = xrecover(y) if x & 1 != bit(s, b - 1): x = q - x P = Point((x, y, 1, (x * y) % q)) if not isoncurve(P): raise ValueError("decoding point that is not on curve") return P def decodecoord(s: bytes) -> int: a = decodeint(s[: b // 8]) # clear mask bits a &= COORD_MASK # set high bit a |= COORD_HIGH_BIT return a def bit(h: bytes, i: int) -> int: return (h[i // 8] >> (i % 8)) & 1 def publickey_unsafe(sk: bytes) -> bytes: """ Not safe to use with secret keys or secret data. See module docstring. This function should be used for testing only. """ h = H(sk) a = decodecoord(h) A = scalarmult_B(a) return encodepoint(A) def Hint(m: bytes) -> int: return decodeint(H(m)) def signature_unsafe(m: bytes, sk: bytes, pk: bytes) -> bytes: """ Not safe to use with secret keys or secret data. See module docstring. This function should be used for testing only. """ h = H(sk) a = decodecoord(h) r = Hint(h[b // 8 : b // 4] + m) R = scalarmult_B(r) S = (r + Hint(encodepoint(R) + pk + m) * a) % l return encodepoint(R) + encodeint(S) def isoncurve(P: Point) -> bool: x, y, z, t = P return ( z % q != 0 and x * y % q == z * t % q and (y * y - x * x - z * z - d * t * t) % q == 0 ) class SignatureMismatch(Exception): pass def checkvalid(s: bytes, m: bytes, pk: bytes) -> None: """ Not safe to use when any argument is secret. See module docstring. This function should be used only for verifying public signatures of public messages. """ if len(s) != b // 4: raise ValueError("signature length is wrong") if len(pk) != b // 8: raise ValueError("public-key length is wrong") R = decodepoint(s[: b // 8]) A = decodepoint(pk) S = decodeint(s[b // 8 : b // 4]) h = Hint(encodepoint(R) + pk + m) x1, y1, z1, _ = P = scalarmult_B(S) x2, y2, z2, _ = Q = edwards_add(R, scalarmult(A, h)) if ( not isoncurve(P) or not isoncurve(Q) or (x1 * z2 - x2 * z1) % q != 0 or (y1 * z2 - y2 * z1) % q != 0 ): raise SignatureMismatch("signature does not pass verification") ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1760000640.786997 trezor-0.20.2/src/trezorlib/_internal/__init__.py0000644000000000000000000000000015071675201016727 0ustar00././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1784031395.874937 trezor-0.20.2/src/trezorlib/_internal/emu_ble.py0000644000000000000000000002061615225424244016617 0ustar00# This file is part of the Trezor project. # # Copyright (C) 2025 SatoshiLabs and contributors # # This library is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 # as published by the Free Software Foundation. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the License along with this library. # If not, see . from __future__ import annotations import logging import socket import time from enum import Enum from typing import TYPE_CHECKING, Iterable, Tuple import construct as c from construct_classes import Struct from ..construct_helpers import EnumAdapter from ..log import DUMP_PACKETS from ..transport import Timeout, Transport, TransportException from ..transport.udp import UdpTransport if TYPE_CHECKING: from ..models import TrezorModel SOCKET_TIMEOUT = 0.1 LOG = logging.getLogger(__name__) class EventType(Enum): NONE = 0 CONNECTED = 1 DISCONNECTED = 2 PAIRING_REQUEST = 3 PAIRING_CANCELLED = 4 PAIRING_COMPLETED = 5 CONNECTION_CHANGED = 6 EMULATOR_PING = 255 class ModeType(Enum): OFF = 0 KEEP_CONNECTION = 1 CONNECTABLE = 2 PAIRING = 3 DFU = 4 class CommandType(Enum): STATUS = ord(" ") PAIRING_MODE = ord("p") DISCONNECT = ord("d") ALLOW_PAIRING = ord("a") REJECT_PAIRING = ord("r") class Event(Struct): event_type: EventType connection_id: int data: bytes # fmt: off SUBCON = c.Struct( "event_type" / EnumAdapter(c.Int32ul, EventType), "connection_id" / c.Int32ul, "data" / c.Prefixed(c.Int8ul, c.GreedyBytes), ) # fmt: on @staticmethod def new( event_type: EventType, connection_id: int = 0, data: bytes | None = None ) -> Event: return Event( event_type=event_type, connection_id=connection_id, data=data or bytes() ) @staticmethod def ping() -> Event: return Event.new(EventType.EMULATOR_PING) BLE_ADV_NAME_LEN = 20 class Command(Struct): command_type: CommandType mode: ModeType connected: int adv_name: bytes bonds: list[bytes] # fmt: off SUBCON = c.Struct( "command_type" / EnumAdapter(c.Int8ul, CommandType), "mode" / EnumAdapter(c.Int8ul, ModeType), "connected" / c.Int8ul, "adv_name" / c.Bytes(20), "bonds" / c.PrefixedArray(c.Int8ul, c.Bytes(6)), ) # fmt: on # You should probably use bluez-emu-bridge instead of this transport directly # as it does not implement any BLE connection management logic. class EmuBleTransport(Transport): DEFAULT_HOST = "127.0.0.1" DEFAULT_PORT = 21328 PATH_PREFIX = "emuble" ENABLED: bool = False CHUNK_SIZE = 244 def __init__(self, device: str | None = None) -> None: if not device: host = EmuBleTransport.DEFAULT_HOST port = EmuBleTransport.DEFAULT_PORT else: devparts = device.split(":") host = devparts[0] port = ( int(devparts[1]) if len(devparts) > 1 else EmuBleTransport.DEFAULT_PORT ) self.device: Tuple[str, int] = (host, port) self.data_socket: socket.socket | None = None self.event_socket: socket.socket | None = None super().__init__() @classmethod def _try_path(cls, path: str) -> "EmuBleTransport": d = cls(path) try: d.open() if d.ping(): return d else: raise TransportException( f"No Trezor device found at address {d.get_path()}" ) except Exception as e: raise TransportException(f"Error opening {d.get_path()}") from e finally: d.close() @classmethod def enumerate( cls, _models: Iterable["TrezorModel"] | None = None ) -> Iterable["EmuBleTransport"]: default_path = f"{cls.DEFAULT_HOST}:{cls.DEFAULT_PORT}" try: return [cls._try_path(default_path)] except TransportException: return [] @classmethod def find_by_path(cls, path: str, prefix_search: bool = False) -> "EmuBleTransport": try: address = path.replace(f"{cls.PATH_PREFIX}:", "") return cls._try_path(address) except TransportException: if not prefix_search: raise assert prefix_search # otherwise we would have raised above return super().find_by_path(path, prefix_search) def get_path(self) -> str: return "{}:{}:{}".format(self.PATH_PREFIX, *self.device) def open(self) -> None: try: self.data_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.data_socket.connect(self.device) self.data_socket.settimeout(SOCKET_TIMEOUT) self.event_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.event_socket.connect((self.device[0], self.device[1] + 1)) self.event_socket.settimeout(SOCKET_TIMEOUT) except Exception: self.close() raise def close(self) -> None: if self.data_socket is not None: self.data_socket.close() self.data_socket = None if self.event_socket is not None: self.event_socket.close() self.event_socket = None def write_chunk(self, chunk: bytes) -> None: assert self.data_socket is not None if len(chunk) != self.CHUNK_SIZE: raise TransportException("Unexpected data length") LOG.log(DUMP_PACKETS, f"sending packet: {chunk.hex()}") self.data_socket.sendall(chunk) def read_chunk(self, timeout: float | None = None) -> bytes: assert self.data_socket is not None start = time.time() while True: try: chunk = self.data_socket.recv(self.CHUNK_SIZE or 1) break except socket.timeout: if timeout is not None and time.time() - start > timeout: raise Timeout(f"Timeout reading UDP packet ({timeout}s)") LOG.log(DUMP_PACKETS, f"received packet: {chunk.hex()}") if len(chunk) != self.CHUNK_SIZE: raise TransportException(f"Unexpected chunk size: {len(chunk)}") return chunk def find_debug(self) -> "UdpTransport": host, port = self.device return UdpTransport(f"{host}:{port - 3}") def wait_until_ready(self, timeout: float = 10) -> None: with self: start = time.monotonic() while True: if self.ping(): break elapsed = time.monotonic() - start if elapsed >= timeout: raise Timeout("Timed out waiting for connection.") time.sleep(0.05) def ping(self) -> bool: """Test if the device is listening.""" assert self.event_socket is not None resp = None try: self.event_socket.sendall(Event.ping().build()) resp = self.read_command() except Exception: pass return (resp is not None) and (resp.command_type == CommandType.STATUS) def ble_connected(self) -> None: assert self.event_socket is not None self.event_socket.sendall(Event.new(EventType.CONNECTED).build()) def ble_disconnected(self) -> None: assert self.event_socket is not None self.event_socket.sendall(Event.new(EventType.DISCONNECTED).build()) def ble_pairing_request(self, pairing_code: bytes) -> None: assert self.event_socket is not None assert len(pairing_code) == 6 self.event_socket.sendall( Event.new(EventType.PAIRING_REQUEST, data=pairing_code).build() ) def ble_pairing_cancel(self) -> None: assert self.event_socket is not None self.event_socket.sendall(Event.new(EventType.PAIRING_CANCELLED).build()) def read_command(self) -> Command | None: assert self.event_socket is not None try: data = self.event_socket.recv(64) except TimeoutError: return None return Command.parse(data) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1784290267.7147136 trezor-0.20.2/src/trezorlib/_internal/emulator.py0000644000000000000000000003565315226415734017053 0ustar00# This file is part of the Trezor project. # # Copyright (C) SatoshiLabs and contributors # # This library is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 # as published by the Free Software Foundation. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the License along with this library. # If not, see . from __future__ import annotations import atexit import json import logging import os import signal import socket import subprocess import time from pathlib import Path from typing import Any, Dict, Iterable, List, Optional, Sequence, TextIO, Union, cast from ..debuglink import DebugLinkNotFound, TrezorTestContext from ..transport import Transport from ..transport.udp import UdpTransport LOG = logging.getLogger(__name__) TROPIC_MODEL_WAIT_TIME = 10 EMULATOR_WAIT_TIME = 30 _RUNNING_PIDS = set() def _cleanup_pids() -> None: for process in _RUNNING_PIDS: process.kill() atexit.register(_cleanup_pids) def _rm_f(path: Path) -> None: try: path.unlink() except FileNotFoundError: pass class TropicModel: DEFAULT_PORT = 28992 def __init__( self, profile_dir: str, configfile: Path, port: int = DEFAULT_PORT, logfile: TextIO | str | Path | None = None, configfile_output: Path | None = None, ) -> None: self.profile_dir = Path(profile_dir).resolve() self.port = port self.configfile = configfile.resolve() self.configfile_output = ( configfile_output or self.profile_dir / "tropic_model_config_output.yml" ) self.logfile = logfile or self.profile_dir / "trezor-tropic-model.log" self.process: Optional[subprocess.Popen] = None def start(self) -> None: self.process = self._launch_process() _RUNNING_PIDS.add(self.process) try: self._wait_until_ready() except TimeoutError: # Assuming that after the default, the process is stuck LOG.warning( f"Tropic model did not come up after {TROPIC_MODEL_WAIT_TIME} seconds" ) self.process.kill() raise def stop(self) -> None: if self.process: LOG.info("Terminating Tropic model...") start = time.monotonic() self.process.send_signal(signal.SIGINT) try: self.process.wait(TROPIC_MODEL_WAIT_TIME) end = time.monotonic() LOG.info(f"Tropic model shut down after {end - start:.3f} seconds") except subprocess.TimeoutExpired: LOG.info("Tropic model seems stuck. Sending kill signal.") self.process.kill() _RUNNING_PIDS.remove(self.process) def _launch_process(self) -> subprocess.Popen: # Opening the file if it is not already opened if hasattr(self.logfile, "write"): output = self.logfile else: assert isinstance(self.logfile, (str, Path)) output = open(self.logfile, "a") return subprocess.Popen( [ "model_server", "tcp", "-c", str(self.configfile), "-p", str(self.port), "-o", str(self.configfile_output), ], cwd=self.profile_dir, stdout=cast(TextIO, output), stderr=subprocess.STDOUT, ) def _wait_until_ready(self, timeout: float = TROPIC_MODEL_WAIT_TIME) -> None: assert self.process is not None, "Tropic model not started" LOG.info(f"Waiting for Tropic model to come up on port {self.port}...") start = time.monotonic() while True: try: with socket.create_connection(("127.0.0.1", self.port), timeout=1): # seems that even if the model is listening for connections # it sometimes needs up to 2 seconds more # before it actually correctly processes requests # TODO: https://github.com/trezor/trezor-firmware/pull/6128 time.sleep(2) break except OSError: pass if self.process.poll() is not None: raise RuntimeError("Tropic model process died") elapsed = time.monotonic() - start if elapsed >= timeout: raise TimeoutError("Can't connect to Tropic model") time.sleep(0.1) LOG.info(f"Tropic model ready after {time.monotonic() - start:.3f} seconds") def __enter__(self) -> "TropicModel": return self def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None: self.stop() class Emulator: STORAGE_FILENAME: str def __init__( self, executable: Path, profile_dir: str, *, logfile: Union[TextIO, str, Path, None] = None, storage: Optional[bytes] = None, headless: bool = False, debug: bool = True, auto_interact: bool = True, extra_args: Iterable[str] = (), ) -> None: self.executable = Path(executable).resolve() if not executable.exists(): raise ValueError(f"emulator executable not found: {self.executable}") self.profile_dir = Path(profile_dir).resolve() if not self.profile_dir.exists(): self.profile_dir.mkdir(parents=True) elif not self.profile_dir.is_dir(): raise ValueError("profile_dir is not a directory") self.workdir = self.profile_dir self.storage = self.profile_dir / self.STORAGE_FILENAME if storage: self.storage.write_bytes(storage) if logfile: self.logfile = logfile else: self.logfile = self.profile_dir / "trezor.log" # Using `client` property instead to assert `not None` self._client: TrezorTestContext | None = None self.process: subprocess.Popen | None = None self.port = 21324 self.headless = headless self.debug = debug self.auto_interact = auto_interact self.extra_args = list(extra_args) # To save all screenshots properly in one directory between restarts self.restart_amount = 0 @property def client(self) -> TrezorTestContext: """So that type-checkers do not see `client` as `Optional`. (it is not None between `start()` and `stop()` calls) """ if self._client is None: raise RuntimeError return self._client def make_args(self) -> List[str]: return [] def make_env(self) -> Dict[str, str]: return os.environ.copy() def _get_transport(self) -> UdpTransport: return UdpTransport(f"127.0.0.1:{self.port}") def _wait_until_ready(self, timeout: float = EMULATOR_WAIT_TIME) -> None: assert self.process is not None, "Emulator not started" self.transport.open() LOG.info("Waiting for emulator to come up...") start = time.monotonic() try: while True: if self.transport.is_ready(): break if self.process.poll() is not None: raise RuntimeError("Emulator process died") elapsed = time.monotonic() - start if elapsed >= timeout: raise TimeoutError("Can't connect to emulator") time.sleep(0.1) finally: self.transport.close() LOG.info(f"Emulator ready after {time.monotonic() - start:.3f} seconds") def wait(self, timeout: Optional[float] = None) -> int: assert self.process is not None, "Emulator not started" ret = self.process.wait(timeout=timeout) _RUNNING_PIDS.remove(self.process) self.process = None self.stop() return ret def _launch_process(self) -> subprocess.Popen: args = self.make_args() env = self.make_env() # Opening the file if it is not already opened if hasattr(self.logfile, "write"): output = self.logfile else: assert isinstance(self.logfile, (str, Path)) output = open(self.logfile, "a") return subprocess.Popen( [str(self.executable)] + args + self.extra_args, cwd=self.workdir, stdout=cast(TextIO, output), stderr=subprocess.STDOUT, env=env, ) def start( self, transport: Optional[UdpTransport] = None, debug_transport: Optional[Transport] = None, ) -> None: if self.process: if self.process.poll() is not None: # process has died, stop and start again LOG.info("Starting from a stopped process.") self.stop() else: # process is running, no need to start again return self.transport = transport or self._get_transport() self.process = self._launch_process() _RUNNING_PIDS.add(self.process) try: self._wait_until_ready() except TimeoutError: # Assuming that after the default 60-second timeout, the process is stuck LOG.warning(f"Emulator did not come up after {EMULATOR_WAIT_TIME} seconds") self.process.kill() raise (self.profile_dir / "trezor.pid").write_text(str(self.process.pid) + "\n") (self.profile_dir / "trezor.port").write_text(str(self.port) + "\n") try: self._client = TrezorTestContext( transport=self.transport, auto_interact=self.auto_interact, debug_transport=debug_transport, ) except DebugLinkNotFound as e: # Don't fail `start()` to allow non-debug emulator sanity test. LOG.warning("DebugLink not found: %s", e) def stop(self) -> None: if self._client: self._client.transport.close() self._client = None if self.process: LOG.info("Terminating emulator...") start = time.monotonic() self.process.terminate() try: self.process.wait(EMULATOR_WAIT_TIME) end = time.monotonic() LOG.info(f"Emulator shut down after {end - start:.3f} seconds") except subprocess.TimeoutExpired: LOG.info("Emulator seems stuck. Sending kill signal.") self.process.kill() _RUNNING_PIDS.remove(self.process) _rm_f(self.profile_dir / "trezor.pid") _rm_f(self.profile_dir / "trezor.port") self.process = None def restart(self) -> None: # preserving the recording directory between restarts self.restart_amount += 1 prev_screenshot_dir = self.client.debug.screenshot_recording_dir debug_transport = self.client.debug.transport self.stop() self.start(transport=self.transport, debug_transport=debug_transport) if prev_screenshot_dir: self.client.debug.start_recording( prev_screenshot_dir, refresh_index=self.restart_amount ) def __enter__(self) -> "Emulator": return self def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None: self.stop() def get_storage(self) -> bytes: return self.storage.read_bytes() def properties(self) -> dict: return {} class CoreEmulator(Emulator): STORAGE_FILENAME = "trezor.flash" def __init__( self, *args: Any, tropic_model_port: Optional[int] = None, port: Optional[int] = None, main_args: Sequence[str] = ("-m", "main"), workdir: Optional[Path] = None, sdcard: Optional[bytes] = None, disable_animation: bool = True, heap_size: str = "20M", **kwargs: Any, ) -> None: super().__init__(*args, **kwargs) if workdir is not None: self.workdir = Path(workdir).resolve() self.sdcard = self.profile_dir / "trezor.sdcard" if sdcard is not None: self.sdcard.write_bytes(sdcard) if port: self.port = port self.tropic_model_port = tropic_model_port self.disable_animation = disable_animation self.main_args = list(main_args) self.heap_size = heap_size def make_env(self) -> Dict[str, str]: env = super().make_env() env.update( TREZOR_PROFILE_DIR=str(self.profile_dir), TREZOR_PROFILE=str(self.profile_dir), TREZOR_UDP_PORT=str(self.port), ) if self.headless: env["SDL_VIDEODRIVER"] = "dummy" if self.headless or self.disable_animation: env["TREZOR_DISABLE_FADE"] = "1" env["TREZOR_DISABLE_ANIMATION"] = "1" env["TROPIC_MODEL_PORT"] = str(self.tropic_port()) return env def make_args(self) -> List[str]: pyopt = "-O0" if self.debug else "-O1" return ( [pyopt, "-X", f"heapsize={self.heap_size}"] + self.main_args + self.extra_args ) # UDP ports are hardcoded as offsets to the base wirelink port def debuglink_port(self) -> int: return self.port + 1 def fido2_port(self) -> int: return self.port + 2 def vcp_port(self) -> int: return self.port + 3 def ble_port(self) -> tuple[int, int]: return (self.port + 4, self.port + 5) # Tropic model can be managed externally, return configured port if set. # Also TCP instead of UDP. def tropic_port(self) -> int: return self.tropic_model_port or (self.port + 6) def properties(self) -> dict[str, Any]: args = [str(self.executable), "--emulator-properties"] try: stdout = subprocess.check_output( args, cwd=self.workdir, env=self.make_env(), stderr=subprocess.PIPE, text=True, timeout=5, ) props = json.loads(stdout) assert isinstance(props, dict) return props except subprocess.CalledProcessError as exc: LOG.warning( f"{' '.join(args)} failed: {exc}\nstdout: {exc.stdout}\nstderr: {exc.stderr}" ) except Exception as exc: LOG.warning(f"{' '.join(args)} failed: {exc}") return {} class LegacyEmulator(Emulator): STORAGE_FILENAME = "emulator.img" def make_env(self) -> Dict[str, str]: env = super().make_env() if self.headless: env["SDL_VIDEODRIVER"] = "dummy" return env ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1785245699.2991316 trezor-0.20.2/src/trezorlib/_internal/firmware_headers.py0000644000000000000000000006021115232130003020472 0ustar00# This file is part of the Trezor project. # # Copyright (C) SatoshiLabs and contributors # # This library is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 # as published by the Free Software Foundation. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the License along with this library. # If not, see . from __future__ import annotations import typing as t from copy import copy from dataclasses import asdict from enum import Enum import click import construct as c from construct_classes import Struct from slhdsa import PublicKey, SecretKey, sha2_128s # noqa: I900 from typing_extensions import Protocol, Self, runtime_checkable from .. import _ed25519, cosi, firmware from ..firmware import models as fw_models from ..firmware import nrf from ..firmware.sanity_struct import STRICT_SANITY_CHECK_DEFAULT SYM_OK = click.style("\u2714", fg="green") SYM_FAIL = click.style("\u274c", fg="red") class Status(Enum): VALID = click.style("VALID", fg="green", bold=True) INVALID = click.style("INVALID", fg="red", bold=True) MISSING = click.style("MISSING", fg="blue", bold=True) DEVEL = click.style("DEVEL", fg="red", bold=True) def is_ok(self) -> bool: return self is Status.VALID or self is Status.DEVEL VHASH_DEVEL = bytes.fromhex( "c5b4d40cb76911392122c8d1c277937e49c69b2aaf818001ec5c7663fcce258f" ) def _make_dev_keys(*key_bytes: bytes) -> t.Sequence[bytes]: return [k * 32 for k in key_bytes] def all_zero(data: bytes) -> bool: return all(b == 0 for b in data) def check_signature_any( fw: SignableImageProto | BootloaderV2Image, is_devel: bool = False ) -> Status: if not fw.signature_present(): return Status.MISSING try: fw.verify() return Status.VALID if not is_devel else Status.DEVEL except Exception: pass try: fw.verify(dev_keys=True) return Status.DEVEL except Exception: return Status.INVALID # ====================== formatting functions ==================== class LiteralStr(str): pass def chunkify(data: bytes) -> str: s = data.hex() return " ".join(s[i : i + 4] for i in range(0, len(s), 4)) def format_container( pb: t.Union[c.Container, Struct, dict], indent: int = 0, sep: str = " " * 4, truncate_after: t.Optional[int] = 64, truncate_to: t.Optional[int] = 32, ) -> str: def mostly_printable(bytes: bytes | bytearray) -> bool: if not bytes: return True printable = sum(1 for byte in bytes if 0x20 <= byte <= 0x7E) return printable / len(bytes) > 0.8 def pformat(value: t.Any, indent: int) -> str: level = sep * indent leadin = sep * (indent + 1) if isinstance(value, LiteralStr): return value if isinstance(value, list): # short list of simple values if not value or isinstance(value[0], (int, bool, Enum)): return repr(value) # long list, one line per entry lines = ["[", level + "]"] lines[1:1] = [leadin + pformat(x, indent + 1) for x in value] return "\n".join(lines) if isinstance(value, Struct): value = asdict(value) if isinstance(value, dict): lines = ["{"] for key, val in value.items(): if key.startswith("_"): continue if val is None or val == []: continue lines.append(leadin + key + ": " + pformat(val, indent + 1)) lines.append(level + "}") return "\n".join(lines) if isinstance(value, (bytes, bytearray)): length = len(value) suffix = "" if truncate_after and length > truncate_after: suffix = "..." value = value[: truncate_to or 0] if mostly_printable(value): output = repr(value) else: output = value.hex() return f"{length} bytes {output}{suffix}" if isinstance(value, Enum): return str(value) return repr(value) return pformat(pb, indent) def _format_version(version: t.Tuple[int, ...]) -> str: return ".".join(str(i) for i in version) def format_header( header: firmware.core.FirmwareHeader, code_hashes: t.Sequence[bytes], digest: bytes, sig_status: Status, ) -> str: header_dict = asdict(header) header_out = header_dict.copy() for key, val in header_out.items(): if "version" in key: header_out[key] = LiteralStr(_format_version(val)) hashes_out = [] for expected, actual in zip(header.hashes, code_hashes): status = SYM_OK if expected == actual else SYM_FAIL hashes_out.append(LiteralStr(f"{status} {expected.hex()}")) if all(all_zero(h) for h in header.hashes): hash_status = Status.MISSING elif header.hashes != code_hashes: hash_status = Status.INVALID else: hash_status = Status.VALID header_out["hashes"] = hashes_out all_ok = SYM_OK if hash_status.is_ok() and sig_status.is_ok() else SYM_FAIL output = [ "Firmware Header " + format_container(header_out), f"Fingerprint: {click.style(chunkify(digest), bold=True)}", f"{all_ok} Signature is {sig_status.value}, hashes are {hash_status.value}", ] return "\n".join(output) def format_secmon_header( header: firmware.secmon.SecmonHeader, code_hash: bytes, digest: bytes, sig_status: Status, ) -> str: header_dict = asdict(header) header_out = header_dict.copy() for key, val in header_out.items(): if "version" in key: header_out[key] = LiteralStr(_format_version(val)) # status = SYM_OK if header.hash == code_hash else SYM_FAIL if all_zero(header.hash): hash_status = Status.MISSING elif header.hash != code_hash: hash_status = Status.INVALID else: hash_status = Status.VALID # # header_out["hashes"] = hashes_out all_ok = SYM_OK if hash_status.is_ok() and sig_status.is_ok() else SYM_FAIL output = [ "SECMON Header " + format_container(header_out), f"Code hash: {click.style(chunkify(code_hash), bold=True)}", f"Fingerprint: {click.style(chunkify(digest), bold=True)}", f"{all_ok} Signature is {sig_status.value}, hash is {hash_status.value}", ] return "\n".join(output) # =========================== functionality implementations =============== class SignableImageProto(Protocol): NAME: t.ClassVar[str] @classmethod def parse(cls, data: bytes) -> Self: """Parse binary data into an image of this type.""" ... def digest(self) -> bytes: """Calculate digest that will be signed / verified.""" ... def verify(self, dev_keys: bool = False) -> None: """Verify signature of the image. If dev_keys is True, verify using development keys. If selected, a production image will fail verification. """ ... def build(self) -> bytes: """Reconstruct binary representation of the image.""" ... def format(self, verbose: bool = False) -> str: """Generate printable information about the image.""" ... def signature_present(self) -> bool: """Check if the image has a signature.""" ... @runtime_checkable class CosiSignedImage(SignableImageProto, Protocol): DEV_KEYS: t.ClassVar[t.Sequence[bytes]] = [] def insert_signature(self, signature: bytes, sigmask: int) -> None: ... def public_keys(self, dev_keys: bool = False) -> t.Sequence[bytes]: ... @runtime_checkable class LegacySignedImage(SignableImageProto, Protocol): def slots(self) -> t.Iterable[int]: ... def insert_signature(self, slot: int, key_index: int, signature: bytes) -> None: ... class CosiSignatureHeaderProto(Protocol): hw_model: t.Union[fw_models.Model, bytes] signature: bytes sigmask: int class CosiSignedMixin: def signature_present(self) -> bool: header = self.get_header() return not all_zero(header.signature) or header.sigmask != 0 def insert_signature(self, signature: bytes, sigmask: int) -> None: self.get_header().signature = signature self.get_header().sigmask = sigmask def get_header(self) -> CosiSignatureHeaderProto: raise NotImplementedError def get_model_keys(self, dev_keys: bool) -> fw_models.ModelKeys: hw_model = self.get_header().hw_model model = fw_models.Model.from_hw_model(hw_model) return model.model_keys(dev_keys) class VendorHeader(firmware.VendorHeader, CosiSignedMixin): NAME: t.ClassVar[str] = "vendorheader" DEV_KEYS: t.ClassVar[t.Sequence[bytes]] = _make_dev_keys(b"\x44", b"\x45") SUBCON = c.Struct( *firmware.VendorHeader.SUBCON.subcons, # type: ignore [Cannot access attribute] c.Terminated, ) def get_header(self) -> CosiSignatureHeaderProto: return self def _format(self, terse: bool) -> str: if not terse: output = [ "Vendor Header " + format_container(self), f"Pubkey bundle hash: {self.vhash().hex()}", ] else: output = [ "Vendor Header for {vendor} version {version} ({size} bytes)".format( vendor=click.style(self.text, bold=True), version=_format_version(self.version), size=self.header_len, ), ] if not terse: output.append( f"Fingerprint: {click.style(chunkify(self.digest()), bold=True)}" ) sig_status = check_signature_any(self) sym = SYM_OK if sig_status.is_ok() else SYM_FAIL output.append(f"{sym} Signature is {sig_status.value}") return "\n".join(output) def format(self, verbose: bool = False) -> str: return self._format(terse=False) def public_keys(self, dev_keys: bool = False) -> t.Sequence[bytes]: return self.get_model_keys(dev_keys).bootloader_keys class VendorFirmware(firmware.VendorFirmware, CosiSignedMixin): NAME: t.ClassVar[str] = "firmware" DEV_KEYS: t.ClassVar[t.Sequence[bytes]] = _make_dev_keys(b"\x47", b"\x48") def get_header(self) -> CosiSignatureHeaderProto: return self.firmware.header def format(self, verbose: bool = False) -> str: vh = copy(self.vendor_header) vh.__class__ = VendorHeader assert isinstance(vh, VendorHeader) is_devel = self.vendor_header.vhash() == VHASH_DEVEL return ( vh._format(terse=not verbose) + "\n" + format_header( self.firmware.header, self.firmware.code_hashes(), self.digest(), check_signature_any(self, is_devel), ) ) def public_keys(self, dev_keys: bool = False) -> t.Sequence[bytes]: """Return public keys that should be used to sign the image. In vendor firmware, the public keys are stored in the vendor header. There is no choice of development keys. If that is required, you need to create an image with a development vendor header. """ return self.vendor_header.pubkeys class BootloaderImage(firmware.FirmwareImage, CosiSignedMixin): NAME: t.ClassVar[str] = "bootloader" DEV_KEYS: t.ClassVar[t.Sequence[bytes]] = _make_dev_keys(b"\x41", b"\x42") def get_header(self) -> CosiSignatureHeaderProto: return self.header def format(self, verbose: bool = False) -> str: return format_header( self.header, self.code_hashes(), self.digest(), check_signature_any(self), ) def verify(self, dev_keys: bool = False) -> None: self.validate_code_hashes() public_keys = self.public_keys(dev_keys) try: cosi.verify( self.header.signature, self.digest(), self.get_model_keys(dev_keys).boardloader_sigs_needed, public_keys, self.header.sigmask, ) except Exception: raise firmware.InvalidSignatureError("Invalid bootloader signature") def public_keys(self, dev_keys: bool = False) -> t.Sequence[bytes]: return self.get_model_keys(dev_keys).boardloader_keys class SecmonImage(firmware.SecmonImage, CosiSignedMixin): NAME: t.ClassVar[str] = "secmon" DEV_KEYS: t.ClassVar[t.Sequence[bytes]] = _make_dev_keys(b"\x41", b"\x42") def get_header(self) -> CosiSignatureHeaderProto: return self.header def format(self, verbose: bool = False) -> str: return format_secmon_header( self.header, self.code_hash(), self.digest(), check_signature_any(self), ) def verify(self, dev_keys: bool = False) -> None: self.validate_code_hash() public_keys = self.public_keys(dev_keys) try: cosi.verify( self.header.signature, self.digest(), self.get_model_keys(dev_keys).boardloader_sigs_needed, public_keys, self.header.sigmask, ) except Exception: raise firmware.InvalidSignatureError("Invalid bootloader signature") def public_keys(self, dev_keys: bool = False) -> t.Sequence[bytes]: return self.get_model_keys(dev_keys).secmon_keys class BootloaderV2Image(firmware.BootableImage): NAME: t.ClassVar[str] = "bootloader" DEV_ED25519_KEYS_PRIVATE = _make_dev_keys(b"\x41", b"\x42") def signature_present(self) -> bool: return any(not all_zero(sig) for sig in self.unauth.slh_signatures) or any( not all_zero(sig) for sig in self.unauth.ec_signatures ) def sign_with_devkeys(self) -> None: # sigmask is a part of the signed part of the header the # digest is calculated from self.header.sigmask = (1 << 0) | (1 << 1) digest = self.merkle_root() # SLH signature signs the image digest for idx, key in enumerate(fw_models.ROOT_SLH_DSA_KEYS_DEV_PRIVATE): key = SecretKey.from_digest(key, sha2_128s) self.unauth.slh_signatures[idx] = key.sign(digest) hash_params = self.get_hash_params() hash_fn = hash_params.hash_function for idx, key in enumerate(self.DEV_ED25519_KEYS_PRIVATE): # The EC signature signs both the image digest and the SLH signature ext_digest = hash_fn(digest + self.unauth.slh_signatures[idx]).digest() self.unauth.ec_signatures[idx] = _ed25519.signature_unsafe( ext_digest, key, fw_models.ROOT_ED25519_KEYS_DEV[idx] ) def format(self, verbose: bool = False) -> str: header_dict = asdict(self) header_out = header_dict.copy() for key, val in header_out.items(): if "version" in key: header_out[key] = LiteralStr(_format_version(val)) sig_status = check_signature_any(self) all_ok = SYM_OK if sig_status.is_ok() else SYM_FAIL output = [ "Firmware Header " + format_container(header_out), f"Leaf hash: {click.style(chunkify(self.leaf_hash()), bold=True)}", f"Merkle root: {click.style(chunkify(self.merkle_root()), bold=True)}", f"{all_ok} Signature is {sig_status.value}", ] return "\n".join(output) def verify(self, dev_keys: bool = False) -> None: digest = self.merkle_root() hash_fn = self.get_hash_params().hash_function mask = self.header.sigmask if (mask.bit_length() > len(self.public_ec_keys(dev_keys))) or ( mask.bit_length() > len(self.public_pq_keys(dev_keys)) ): raise ValueError("Sigmask specifies more public keys than provided.") # Verify ed25519 signatures if mask.bit_count() != len(self.unauth.ec_signatures): raise ValueError("Sigmask does not specify valid number of ed25519 keys.") sig_idx = 0 for pubkey_idx, key in enumerate(self.public_ec_keys(dev_keys)): if not (mask & (1 << pubkey_idx)): continue ext_digest = hash_fn(digest + self.unauth.slh_signatures[sig_idx]).digest() try: _ed25519.checkvalid(self.unauth.ec_signatures[sig_idx], ext_digest, key) except _ed25519.SignatureMismatch: raise firmware.InvalidSignatureError("Invalid bootloader signature") sig_idx += 1 # Verify slh-dsa signatures if mask.bit_count() != len(self.unauth.slh_signatures): raise ValueError("Sigmask does not specify valid number of slh-dsa keys.") sig_idx = 0 for pubkey_idx, key in enumerate(self.public_pq_keys(dev_keys)): if not (mask & (1 << pubkey_idx)): continue pq_key = PublicKey.from_digest(key, sha2_128s) if not pq_key.verify(digest, self.unauth.slh_signatures[sig_idx]): raise firmware.InvalidSignatureError("Invalid bootloader signature") sig_idx += 1 class LegacyFirmware(firmware.LegacyFirmware): NAME: t.ClassVar[str] = "legacy_firmware_v1" def signature_present(self) -> bool: return any(i != 0 for i in self.key_indexes) or any( not all_zero(sig) for sig in self.signatures ) def insert_signature(self, slot: int, key_index: int, signature: bytes) -> None: if not 0 <= slot < firmware.V1_SIGNATURE_SLOTS: raise ValueError("Invalid slot number") if not 0 < key_index <= len(fw_models.LEGACY_V1V2.firmware_keys): raise ValueError("Invalid key index") self.key_indexes[slot] = key_index self.signatures[slot] = signature def format(self, verbose: bool = False) -> str: contents = asdict(self).copy() del contents["embedded_v2"] if self.embedded_v2: em = copy(self.embedded_v2) em.__class__ = LegacyV2Firmware assert isinstance(em, LegacyV2Firmware) embedded_content = "\nEmbedded V2 header: " + em.format(verbose=verbose) else: embedded_content = "" return format_container(contents) + embedded_content def public_keys( self, dev_keys: bool = False, signature_version: int = 2 ) -> t.Sequence[bytes]: if dev_keys: return fw_models.LEGACY_V1V2_DEV.firmware_keys else: return fw_models.LEGACY_V1V2.firmware_keys def slots(self) -> t.Iterable[int]: return self.key_indexes class LegacyV2Firmware(firmware.LegacyV2Firmware): NAME: t.ClassVar[str] = "legacy_firmware_v2" def signature_present(self) -> bool: return any(i != 0 for i in self.header.v1_key_indexes) or any( not all_zero(sig) for sig in self.header.v1_signatures ) def insert_signature(self, slot: int, key_index: int, signature: bytes) -> None: if not 0 <= slot < firmware.V1_SIGNATURE_SLOTS: raise ValueError("Invalid slot number") if not 0 < key_index <= len(firmware.V1_BOOTLOADER_KEYS): raise ValueError("Invalid key index") if not isinstance(self.header.v1_key_indexes, list): self.header.v1_key_indexes = list(self.header.v1_key_indexes) if not isinstance(self.header.v1_signatures, list): self.header.v1_signatures = list(self.header.v1_signatures) self.header.v1_key_indexes[slot] = key_index self.header.v1_signatures[slot] = signature def format(self, verbose: bool = False) -> str: return format_header( self.header, self.code_hashes(), self.digest(), check_signature_any(self), ) def public_keys( self, dev_keys: bool = False, signature_version: int = 3 ) -> t.Sequence[bytes]: keymap: t.Dict[t.Tuple[int, bool], fw_models.ModelKeys] = { (3, False): fw_models.LEGACY_V3, (3, True): fw_models.LEGACY_V3_DEV, (2, False): fw_models.LEGACY_V1V2, (2, True): fw_models.LEGACY_V1V2_DEV, } if not (signature_version, dev_keys) in keymap: raise ValueError("Unsupported signature version") return keymap[signature_version, dev_keys].firmware_keys def slots(self) -> t.Iterable[int]: return self.header.v1_key_indexes class NrfImage(nrf.NrfImage): NAME: t.ClassVar[str] = "nrf" def signature_present(self) -> bool: return ( nrf.TlvType.SIGNATURE1 in self.unprotected_tlv and nrf.TlvType.SIGNATURE2 in self.unprotected_tlv ) def format(self, verbose: bool = False) -> str: header_str = _format_header(self.header) image_str = f"Image data: {len(self.img_data)} bytes" tlvs_str = _format_tlvs(self.protected_tlv, self.unprotected_tlv) fingerprint_str = ( f"Calculated fingerprint: {click.style(chunkify(self.digest()), bold=True)}" ) sig_result = check_signature_any(self) sig_ok = SYM_OK if sig_result.is_ok() else SYM_FAIL sig_str = f"{sig_ok} Signature is {sig_result.value}" return "\n".join( [ header_str, image_str, tlvs_str, fingerprint_str, sig_str, ] ) def _format_header(header: nrf.NrfHeader) -> str: header_dict = asdict(header) header_out = header_dict.copy() for key, val in header_out.items(): if "version" in key: header_out[key] = LiteralStr(_format_version_nRF(val)) return "NrfHeader " + format_container(header_out) def _format_version_nRF(version: tuple[int, int, int, int]) -> str: return "{}.{}.{}+{}".format(*version) def _format_tlvs( *tlv_tables: nrf.TlvTable, padding: str = " " * 4, ) -> str: total_size = 0 for table in tlv_tables: total_size += table.length output = [f"TLVs (count: {len(tlv_tables)}, total_size: {total_size} bytes) {{"] def _add(s: str, depth: int = 1) -> None: output.append(padding * depth + s) for tlv in tlv_tables: type_name = tlv.magic.name _add(f"{type_name} ({tlv.length} bytes) {{") for entry in tlv.entries: if isinstance(entry.id, nrf.TlvType): name = entry.id.name else: name = f"unrecognized {entry.id}" if len(entry.data) > 64: data = entry.data[:64].hex() + "..." elif isinstance(entry.id, nrf.TlvType) and entry.id.name == "MODEL": data = f"{entry.data.decode()} ({entry.data.hex()})" else: data = entry.data.hex() _add(f"{name}: ({len(entry.data)} bytes) {data}", depth=2) _add("}") return "\n".join(output) + "\n}" def parse_image( image: bytes, strict: bool = STRICT_SANITY_CHECK_DEFAULT ) -> SignableImageProto: try: return VendorFirmware.parse(image, strict=strict) except c.ConstructError: pass try: return VendorHeader.parse(image, strict=strict) except c.ConstructError: pass try: return SecmonImage.parse(image, strict=strict) except c.ConstructError: pass try: firmware_img = firmware.core.FirmwareImage.parse(image, strict=strict) if firmware_img.header.magic == firmware.core.HeaderType.BOOTLOADER: return BootloaderImage.parse(image, strict=strict) if firmware_img.header.magic == firmware.core.HeaderType.FIRMWARE: return LegacyV2Firmware.parse(image, strict=strict) raise ValueError("Unrecognized firmware header magic") except c.ConstructError: pass try: return LegacyFirmware.parse(image, strict=strict) except c.ConstructError: pass raise ValueError("Unrecognized firmware type") ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1785245699.299195 trezor-0.20.2/src/trezorlib/_internal/master_fingerprint.py0000644000000000000000000000520415232130003021066 0ustar00# This file is part of the Trezor project. # # Copyright (C) SatoshiLabs and contributors # # This library is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 # as published by the Free Software Foundation. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the License along with this library. # If not, see . from __future__ import annotations import hashlib from typing import TextIO from .slip26 import parse_label # Artefact info and fingerprint: (model integer, purpose, 32-byte fingerprint). ArtefactFingerprint = tuple[int, int, bytes] def parse_fingerprints_file(f: TextIO) -> set[ArtefactFingerprint]: """Parse ``