forked from trezor/trezor-core
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
30 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,9 @@ MAINTAINER = ... | |
|
||
AUTHOR = Dusan Klinec <[email protected]> | ||
|
||
REVIEWER = ... | ||
REVIEWER = Tomas Susanka <[email protected]>, | ||
Jan Pochyla <[email protected]>, | ||
Ondrej Vejpustek <[email protected]> | ||
|
||
ADVISORS = | ||
|
||
|
@@ -96,21 +98,16 @@ Main high level protocol logic is implemented in `apps/monero/protocol/` directo | |
The serialization in `apps/monero/xmr/serialize` is the cryptonote serialization format used to serialize data to blockchain. | ||
The serialization was ported from Monero C++. Source comes from the library [monero-serialize]. | ||
|
||
Serialization scheme was inspired by protobuf serialization scheme. Later it was subject to optimizations as | ||
scheme definition with `FIELDS` attribute was quite memory hungry. Serialization was refactred to specify | ||
fields as a classmethod which is easier to `gc.collect()` after serialization is done compared to static `FIELDS` | ||
which are not easy to deallocate. | ||
Serialization scheme was inspired by protobuf serialization scheme. | ||
Fields are specified as a classmethod which is easier to `gc.collect()` after serialization is done. | ||
|
||
```python | ||
@classmethod | ||
def f_specs(cls): | ||
return (("size", SizeT),) | ||
``` | ||
|
||
Serialization works in `async/wait` manner, uses `reader/writer` interface as protobuf uses. | ||
|
||
Moreover the serialization funtionality is encapsulated in so-called Archive object which encapsulates serialization logic. | ||
Archive works in a symmetric way, i.e., the same API is used for serialization and deserialization. | ||
Serialization is synchronous. | ||
|
||
|
||
### Protocols | ||
|
@@ -125,16 +122,20 @@ with Chacha20Poly1305 with unique key (derived from the protocol step, message, | |
|
||
TREZOR builds the signed Monero transaction incrementally, i.e., one UTXO per round trip, one transaction output per roundtrip. | ||
|
||
### Protocol wrapping messages | ||
### Protocol workflow | ||
|
||
Key image sync and transaction signing protocols are stateful. | ||
Both protocols implement custom workflow managing the protocol state and state transitions explicitly. | ||
|
||
Due to the dispatcher design we decided to use wrapping message for the multi-step protocols. | ||
The top wrapping message contains sub-message field for each possible message in the protocol. In this way we can register | ||
one simple dispatcher on the wrapping message and do the sub-message multiplexing in the code, hidden in the abstraction. | ||
Entry to the protocol workflow is passed on the initial protocol message, i.e., only the initial protocol message | ||
is registered via `wire.add()`. The workflow internally manages receiving / sending protocol messages. | ||
|
||
Without wrapping message we would have to register each sub-message to the same handler and then de-multiplex it again | ||
in the protocol logic which is error prone and duplicates the code. When changing the flow later it would be prone to errors. | ||
Each finished protocol step specifies the next expected message set which helps to govern protocol state transitions, | ||
i.e., exception is thrown if another message is received as expected. | ||
|
||
Responses are not wrapped and each response has own wire ID. Response messages are not registered so we don't need wrapping. | ||
As the protocols implement custom workflow the general package unimport in `wire` is not called which | ||
could lead to memory problems as locally imported packages are not freed from memory on `gc.collect()`. | ||
Thus protocols call unimport manually after processing the protocol messages. | ||
|
||
Protobuf messages are following the convention `MoneroXRequest`, `MoneroXAck`. | ||
|
||
|
@@ -147,7 +148,7 @@ generated by the cold wallet (KI proof). | |
KI sync is mainly needed to recover from some problem or when using a new hot-wallet (corruption of a wallet file or | ||
using TREZOR on a different host). | ||
|
||
The KI protocol has 3 steps. Wrapping message `MoneroKeyImageSyncRequest`. | ||
The KI protocol has 3 steps. | ||
|
||
### Init step | ||
|
||
|
@@ -172,15 +173,8 @@ to the agent/hot-wallet so it can decrypt computed KIs and import it | |
|
||
For detailed description and rationale please refer to the [monero-doc]. | ||
|
||
TODO | ||
|
||
- The wrapping message: `MoneroTransactionSignRequest`. | ||
- The main multiplexor: `apps/monero/protocol/tsx_sign.py` | ||
- The main signing logic is implemented in `apps/monero/protocol/tsx_sign_builder.py` | ||
- State automaton watching correct state transitions: `apps/monero/protocol/tsx_sign_state.py` | ||
- State hold between protocol messages: `apps/monero/protocol/tsx_sign_state_holder.py`. The state is externalized in the | ||
dedicated class so the memory consumption is minimal between round trips. | ||
|
||
- The protocol workflow `apps/monero/sign_tx.py` | ||
- The protocol is implemented in `apps/monero/protocol/signing/` | ||
|
||
### `MoneroTransactionInitRequest`: | ||
|
||
|
@@ -191,7 +185,7 @@ After receiving this message: | |
- The TREZOR prompts user for verification of the destination addresses and amounts. | ||
- Commitments are computed thus later potential deviations from transaction destinations are detected and signing aborts. | ||
- Secrets for HMACs / encryption are computed, TX key is computed. | ||
- Precomputes sub-addresses if needed. | ||
- Precomputes required sub-addresses (init message indicates which sub-addresses are needed). | ||
|
||
### `MoneroTransactionSetInputRequest` | ||
|
||
|
@@ -207,16 +201,16 @@ This message caries permutation on the key images so they are sorted in the desi | |
|
||
### `MoneroTransactionInputViniRequest` | ||
|
||
- Step needed to correctly hash all transaction inputs, in the right order computed in the previous step. | ||
- Step needed to correctly hash all transaction inputs, in the right order (permutation computed in the previous step). | ||
- Contains `MoneroTransactionSourceEntry` and `TxinToKey` computed in the previous step. | ||
- TREZOR Computes `tx_prefix_hash` is part of the signed data. | ||
|
||
|
||
### `MoneroTransactionAllInputsSetRequest` | ||
|
||
- Sent after all inputs have been processed. | ||
- Mainly used in the range proof offloading to the host. E.g., in case of batched Bulletproofs with more than 2 transaction outputs. | ||
The message response can carry commitment masks so host can compute range proof correctly. | ||
- Used in the range proof offloading to the host. E.g., in case of batched Bulletproofs with more than 2 transaction outputs. | ||
The message response contains TREZOR-generated commitment masks so host can compute range proof correctly. | ||
|
||
### `MoneroTransactionSetOutputRequest` | ||
|
||
|
@@ -225,11 +219,6 @@ The message response can carry commitment masks so host can compute range proof | |
- TREZOR computes data related to transaction output, e.g., range proofs, ECDH info for the receiver, output public key. | ||
- In case offloaded range proof is used the request can carry computed range proof. | ||
|
||
### `MoneroTransactionRangeSigRequest` | ||
|
||
- Optional protocol message that supports more complicated, several round-trips range proof offloading proposals as described in the [monero-doc]. | ||
- Not used with the basic range proof offloading where the whole range proof is computed on the host. | ||
|
||
### `MoneroTransactionAllOutSetRequest` | ||
|
||
Sent after all transaction outputs have been sent to the TREZOR for processing. | ||
|
@@ -290,26 +279,6 @@ API provides basic functions for work with scalars and points and Monero specifi | |
The API is designed in such a way it is easy to work with Ed25519 as there is only one point format which is always | ||
normed to avoid complications when chaining operations such as `scalarmult`s. | ||
|
||
### Point normalization | ||
|
||
Points in [trezor-core] are normed, i.e., `z=1`. | ||
|
||
Normalization is mainly needed after `ge25519_scalarmult`, `ge25519_scalarmult_base_niels`, | ||
which is already done in Monero code in [trezor-crypto]. | ||
|
||
if the norming is not performed, the operations could not be chained arbitrarily as the result is invalid. | ||
|
||
Note: | ||
Point normalization operation is typically performed when compressing coordinate point representation to the 32 B array | ||
as `z` needs to be 1. It requires to compute inversion which is not for free. | ||
|
||
On the other hand, the original Monero C++ code typically operates on 32 B keys by | ||
decompressing and compressing it after each result so they are doing normalization in each step, basically. | ||
|
||
There are some optimized chunks, e.g., range sig verification, which improves blockchain scanning | ||
(still takes 3 days to verify the blockchain). | ||
Optimized chunks are using different point representations to avoid redundant normalizations but in general cases, | ||
it is not a performance issue for the sake of correct computation, easy development and maintenance. | ||
|
||
### Range signatures | ||
|
||
|
@@ -331,12 +300,17 @@ Using small and easily auditable & testable building blocks, such as ge25519_add | |
schemes in high level language is, in my opinion, a scalable and secure way to build the system. | ||
Porting all Monero crypto schemes to C would be very time consuming and prone to errors. | ||
|
||
Having access to low-level features also speeds up development of new features, such as multisigs / bulletproofs. | ||
Having access to low-level features also speeds up development of new features, such as multisigs. | ||
|
||
MLSAG may need to be slightly changed when implementing multisigs | ||
(some preparations have been made already but we will see after this phase starts). | ||
|
||
Bulletproof generation and verification is implemented, however the device can handle maximum 2 batched outputs | ||
in the bulletproof due to high memory requirements (more on that in [monero-doc]). If number of outputs is larger | ||
than 2 the offloading to host is required. | ||
|
||
Bulletproof implementation is covered by unit tests, the proofs in unittest were generated by the Monero C++ | ||
implementation. | ||
|
||
|
||
|
||
|