mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-22 15:38:11 +00:00
docs: improve documentation for core
[no changelog]
This commit is contained in:
parent
6142a39f20
commit
8c5f73c413
@ -10,22 +10,10 @@ Handles on-the-wire communication with a host computer. The communication is:
|
|||||||
|
|
||||||
This module:
|
This module:
|
||||||
|
|
||||||
1. Provides API for registering messages. In other words binds what functions are invoked
|
1. Runs workflows, also called `handlers`, to process the message.
|
||||||
when some particular message is received. See the `add` function.
|
2. Creates and passes the `Context` object to the handlers. This provides an interface to
|
||||||
2. Runs workflows, also called `handlers`, to process the message.
|
|
||||||
3. Creates and passes the `Context` object to the handlers. This provides an interface to
|
|
||||||
wait, read, write etc. on the wire.
|
wait, read, write etc. on the wire.
|
||||||
|
|
||||||
## `add` function
|
|
||||||
|
|
||||||
The `add` function registers what function is invoked when some particular `message_type`
|
|
||||||
is received. The following example binds the `apps.wallet.get_address` function with
|
|
||||||
the `GetAddress` message:
|
|
||||||
|
|
||||||
```python
|
|
||||||
wire.add(MessageType.GetAddress, "apps.wallet", "get_address")
|
|
||||||
```
|
|
||||||
|
|
||||||
## Session handler
|
## Session handler
|
||||||
|
|
||||||
When the `wire.setup` is called the `handle_session` coroutine is scheduled. The
|
When the `wire.setup` is called the `handle_session` coroutine is scheduled. The
|
||||||
|
@ -52,3 +52,4 @@
|
|||||||
- [TOIF Image Format](misc/toif.md)
|
- [TOIF Image Format](misc/toif.md)
|
||||||
- [Developers guide](developers/index.md)
|
- [Developers guide](developers/index.md)
|
||||||
- [Libraries](developers/libraries.md)
|
- [Libraries](developers/libraries.md)
|
||||||
|
- [Hello World in Core](developers/hello_world_feature_TT.md)
|
||||||
|
@ -55,7 +55,10 @@ make vendor build_boardloader build_bootloader build_firmware
|
|||||||
|
|
||||||
## Uploading
|
## Uploading
|
||||||
|
|
||||||
Use `make upload` to upload the firmware to a production device. Do not forget to [enter bootloader](https://wiki.trezor.io/User_manual:Updating_the_Trezor_device_firmware) on the device beforehand.
|
Use `make upload` to upload the firmware to a production device.
|
||||||
|
|
||||||
|
* For TT: Do not forget to [enter bootloader](https://www.youtube.com/watch?v=3hes1H4qRbw) on the device beforehand.
|
||||||
|
* For TS3: You will have to [unlock bootloader] (https://trezor.io/learn/a/unlocking-the-bootloader-on-trezor-safe-3) first. Make sure to read the link in completeness for potentially unwanted effects.
|
||||||
|
|
||||||
## Flashing
|
## Flashing
|
||||||
|
|
||||||
|
@ -96,5 +96,5 @@ Beware that this will significantly bloat the final binary
|
|||||||
and the firmware runtime memory limit HEAPSIZE may have to be increased.
|
and the firmware runtime memory limit HEAPSIZE may have to be increased.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
DEBUG_BUILD=1 make build_unix
|
make build_unix_debug
|
||||||
```
|
```
|
||||||
|
@ -61,13 +61,16 @@ To use the "all all all" seed defined in [SLIP-14](https://github.com/satoshilab
|
|||||||
|
|
||||||
```sh
|
```sh
|
||||||
./emu.py --slip0014
|
./emu.py --slip0014
|
||||||
|
./emu.py -s
|
||||||
```
|
```
|
||||||
|
|
||||||
### Storage and Profiles
|
### Storage and Profiles
|
||||||
|
|
||||||
Internal Trezor's storage is emulated and stored in the `/var/tmp/trezor.flash` file by
|
Internal Trezor's storage is emulated and stored in the `/var/tmp/trezor.flash` file by
|
||||||
default. Deleting this file is similar to calling _wipe device_. You can also find
|
default. Deleting this file is similar to calling _wipe device_. You can also find
|
||||||
`/var/tmp/trezor.sdcard` for SD card.
|
`/var/tmp/trezor.sdcard` for SD card. Starting the emulator with `-e` / `--erase` will
|
||||||
|
delete the files beforehand.
|
||||||
|
|
||||||
|
|
||||||
You can specify a different location for the storage and log files via the `-p` /
|
You can specify a different location for the storage and log files via the `-p` /
|
||||||
`--profile` option:
|
`--profile` option:
|
||||||
|
@ -1,5 +1,15 @@
|
|||||||
# Trezor Core
|
# Trezor Core
|
||||||
|
|
||||||
Trezor Core is the second-gen firmware running on Trezor devices. It currently runs on Trezor T only, but it will probably be used on Trezor One in future as well (see issue [#24](https://github.com/trezor/trezor-firmware/issues/24)).
|
Trezor Core is the second-gen firmware running on Trezor devices. It currently runs on Trezor T and Trezor Safe 3, but it might be used on Trezor One in the future as well (see issue [#24](https://github.com/trezor/trezor-firmware/issues/24)).
|
||||||
|
|
||||||
Trezor Core is part of the trezor-firmware monorepo to be found on [GitHub](https://github.com/trezor/trezor-firmware), in the `core` subdirectory.
|
Trezor Core is part of the trezor-firmware monorepo to be found on [GitHub](https://github.com/trezor/trezor-firmware), in the `core` subdirectory.
|
||||||
|
|
||||||
|
Trezor Core uses [MicroPython](https://github.com/micropython/micropython), it is a Python implementation for embedded systems, which allows us to have an application layer in Python, which makes the code significantly more readable and sustainable. This is what you find in the `src` folder.
|
||||||
|
|
||||||
|
Not everything is in Python though, we need to use C occasionally, usually for performance reasons. That is what `embed/extmod` is for. It extends MicroPython's modules with a number of our owns and serves as a bridge between C and Python codebase. Related to that, `mocks` contain Python mocks of those functions to improve readability and IDE functioning.
|
||||||
|
|
||||||
|
Where appropriate, we also use Rust. For example, all UI components and animations are implemented in `embed/rust`. Similarly to C bindings, you can find Python mocks for the Rust functions in `mocks` directory. Developing new features in Rust is preferred in the future.
|
||||||
|
|
||||||
|
## Boot
|
||||||
|
|
||||||
|
Module `src/main.py` is the first one to be invoked in MicroPython. It starts the USB, initializes the wire codec and boots applications (see [Apps](apps.md)).
|
||||||
|
@ -2,15 +2,34 @@
|
|||||||
|
|
||||||
The folder `src/apps/` is the place where all the user-facing features are implemented.
|
The folder `src/apps/` is the place where all the user-facing features are implemented.
|
||||||
|
|
||||||
Each app has a `boot()` function in the module's \_\_init\_\_ file. This functions assigns what function should be called if some specific message was received. In other words, it is a link between the MicroPython functions and the Protobuf messages.
|
Each app must be registered by the `register` function inside the file `workflow_handlers.py`. This functions assigns what function should be called if some specific message was received. In other words, it is a link between the MicroPython functions and the Protobuf messages.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
This binds the message GetAddress to function `get_address` inside the `apps.bitcoin` module.
|
For a user facing application you would assign the message to the module in `_find_message_handler_module`. This binds the message `GetAddress` to function `get_address` inside the `apps.bitcoin.get_address` module.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from trezor import wire
|
# in core/src/apps/workflow_handlers.py
|
||||||
from trezor.messages import MessageType
|
|
||||||
|
# ...
|
||||||
|
|
||||||
|
def _find_message_handler_module(msg_type: int) -> str:
|
||||||
|
from trezor.enums import MessageType
|
||||||
|
|
||||||
|
# ...
|
||||||
|
|
||||||
|
if msg_type == MessageType.GetAddress:
|
||||||
|
return "apps.bitcoin.get_address"
|
||||||
|
|
||||||
|
# ...
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
# in core/src/apps/bitcoin/get_address.py
|
||||||
|
|
||||||
|
# ...
|
||||||
|
|
||||||
|
async def get_address(msg: GetAddress, keychain: Keychain, coin: CoinInfo) -> Address:
|
||||||
|
# ...
|
||||||
|
|
||||||
wire.add(MessageType.GetAddress, apps.bitcoin, "get_address")
|
|
||||||
```
|
```
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
# Trezor Core
|
|
||||||
|
|
||||||
Trezor Core uses [MicroPython](https://github.com/micropython/micropython), it is a Python implementation for embedded systems, which allows us to have an application layer in Python, which makes the code significantly more readable and sustainable. This is what you find in the `src` folder.
|
|
||||||
|
|
||||||
Not everything is in Python though, we need to use C occasionally, usually for performance reasons. That is what `embed/extmod` is for. It extends MicroPython's modules with a number of our owns and serves as a bridge between C and Python codebase. Related to that, `mocks` contain Python mocks of those functions to improve readability and IDE functioning.
|
|
||||||
|
|
||||||
## Boot
|
|
||||||
|
|
||||||
Module `src/main.py` is the first one to be invoked in MicroPython. It starts the USB, initializes the wire codec and boots applications (see [Apps](apps.md)).
|
|
@ -3,11 +3,18 @@
|
|||||||
We have two types of tests in Core:
|
We have two types of tests in Core:
|
||||||
|
|
||||||
1. Unit tests that are specific to Trezor Core.
|
1. Unit tests that are specific to Trezor Core.
|
||||||
2. Common tests, which are common to both Trezor Core (Model T) and Legacy (Model one). Device tests belong to this category.
|
2. Common tests, which are common to both Trezor Core (Model T, Safe 3) and Legacy (Model one). Device tests belong to this category.
|
||||||
|
|
||||||
## Core tests
|
## Core unit tests
|
||||||
|
|
||||||
See the `core/tests/` directory.
|
Unit tests are placed in the `core/tests/` directory.
|
||||||
|
|
||||||
|
To start them, [build unix port](../build/emulator.md) and run the following command from `core/`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make test # run all unit test
|
||||||
|
make test TESTOPTS=test_apps.bitcoin.address.py # run a specific test
|
||||||
|
```
|
||||||
|
|
||||||
## Common tests
|
## Common tests
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ We will implement a simple hello-world feature where Trezor gets some informatio
|
|||||||
|
|
||||||
As already mentioned, to get something useful from Trezor, writing device logic is not enough. We need to have a specific communication channel between the computer and Trezor, and also the computer needs to know how to speak to the device to trigger wanted action.
|
As already mentioned, to get something useful from Trezor, writing device logic is not enough. We need to have a specific communication channel between the computer and Trezor, and also the computer needs to know how to speak to the device to trigger wanted action.
|
||||||
|
|
||||||
### TLDR: [implementation in a single commit](https://github.com/trezor/trezor-firmware/commit/8a855b38e69bea64ba79ca704876cf4862a9ff79)
|
### TLDR: [implementation in a single commit](https://github.com/trezor/trezor-firmware/commit/e1cbb8a97018ec3ea39e759bbdc9a5311f992dc5)
|
||||||
|
|
||||||
### 1. Communication part (protobuf)
|
### 1. Communication part (protobuf)
|
||||||
Communication between Trezor and the computer is handled by a protocol called `protobuf`. It allows for the creation of specific messages (containing clearly defined data) that will be exchanged. More details about this can be seen in [docs](../common/communication/index.md).
|
Communication between Trezor and the computer is handled by a protocol called `protobuf`. It allows for the creation of specific messages (containing clearly defined data) that will be exchanged. More details about this can be seen in [docs](../common/communication/index.md).
|
||||||
@ -90,18 +90,16 @@ from trezor.messages import HelloWorldResponse
|
|||||||
from trezor.ui.layouts import confirm_text
|
from trezor.ui.layouts import confirm_text
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from trezor.wire import Context
|
|
||||||
from trezor.messages import HelloWorldRequest
|
from trezor.messages import HelloWorldRequest
|
||||||
|
|
||||||
|
|
||||||
async def hello_world(ctx: Context, msg: HelloWorldRequest) -> HelloWorldResponse:
|
async def hello_world(msg: HelloWorldRequest) -> HelloWorldResponse:
|
||||||
text = _get_text_from_msg(msg)
|
text = _get_text_from_msg(msg)
|
||||||
if msg.show_display:
|
if msg.show_display:
|
||||||
await confirm_text(
|
await confirm_text(
|
||||||
ctx,
|
|
||||||
"confirm_hello_world",
|
"confirm_hello_world",
|
||||||
title="Hello world",
|
"Hello world",
|
||||||
data=text,
|
text,
|
||||||
description="Hello world example",
|
description="Hello world example",
|
||||||
)
|
)
|
||||||
return HelloWorldResponse(text=text)
|
return HelloWorldResponse(text=text)
|
||||||
@ -129,7 +127,7 @@ if msg_type == MessageType.HelloWorldRequest:
|
|||||||
return "apps.misc.hello_world"
|
return "apps.misc.hello_world"
|
||||||
```
|
```
|
||||||
|
|
||||||
The above will make sure the `ctx` and `msg` (of type `HelloWorldRequest`) arguments will be supplied into the `hello_world` function we created.
|
The above will make sure that the `msg` (of type `HelloWorldRequest`) will be supplied into the `hello_world` function we created.
|
||||||
|
|
||||||
Lastly, running `make gen` in the root directory makes sure the new `misc/hello_world.py` module will be discovered. `core/src/all_modules.py` should be modified as a result.
|
Lastly, running `make gen` in the root directory makes sure the new `misc/hello_world.py` module will be discovered. `core/src/all_modules.py` should be modified as a result.
|
||||||
|
|
||||||
@ -339,6 +337,6 @@ Note the usage of `trezorlib.hello_world.say_hello`, which we defined earlier, s
|
|||||||
If we want to be fully compatible with `CI`, we need to create expected `UI-test` results. The most straightforward way to do it is to run `make test_emu_ui_record` in `core` directory.
|
If we want to be fully compatible with `CI`, we need to create expected `UI-test` results. The most straightforward way to do it is to run `make test_emu_ui_record` in `core` directory.
|
||||||
|
|
||||||
## Conclusion
|
## Conclusion
|
||||||
All changes in one commit can be seen [here](https://github.com/trezor/trezor-firmware/commit/8a855b38e69bea64ba79ca704876cf4862a9ff79).
|
All changes in one commit can be seen [here](https://github.com/trezor/trezor-firmware/commit/e1cbb8a97018ec3ea39e759bbdc9a5311f992dc5).
|
||||||
|
|
||||||
Ideas for potentially useful Trezor features are welcome. Feel free to submit issues and open PRs, even if incomplete.
|
Ideas for potentially useful Trezor features are welcome. Feel free to submit issues and open PRs, even if incomplete.
|
@ -78,7 +78,7 @@ The script `tests/show_results.py` starts a local HTTP server that serves this p
|
|||||||
this is necessary for access to browser local storage, which enables a simple reviewer
|
this is necessary for access to browser local storage, which enables a simple reviewer
|
||||||
UI.
|
UI.
|
||||||
|
|
||||||
On CI this report is published as an artifact. You can see the latest master report [here](https://gitlab.com/satoshilabs/trezor/trezor-firmware/-/jobs/artifacts/master/file/test_ui_report/index.html?job=core%20device%20test). The reviewer features work directly here.
|
On CI this report is published as an artifact. You can see the latest `main` branch report [here](https://gitlab.com/satoshilabs/trezor/trezor-firmware/-/jobs/artifacts/main/file/test_ui_report/index.html?job=core%20device%20test). The reviewer features work directly here.
|
||||||
|
|
||||||
If needed, you can use `python3 -m tests.ui_tests` to regenerate the report from local
|
If needed, you can use `python3 -m tests.ui_tests` to regenerate the report from local
|
||||||
recorded screens.
|
recorded screens.
|
||||||
|
Loading…
Reference in New Issue
Block a user