1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-22 22:38:08 +00:00

core/sign_tx: improve documentation on MatchCheckers

This commit is contained in:
matejcik 2020-04-30 16:36:38 +02:00 committed by Andrew Kozlik
parent 0209768ff2
commit 9005093435

View File

@ -9,7 +9,7 @@ from apps.wallet.sign_tx import multisig
from apps.wallet.sign_tx.common import SigningError
if False:
from typing import Union
from typing import Any, Union
# the number of bip32 levels used in a wallet (chain and address)
_BIP32_WALLET_DEPTH = const(2)
@ -17,21 +17,34 @@ _BIP32_WALLET_DEPTH = const(2)
class MatchChecker:
"""
MatchCheckers are used to identify the change-output in a transaction. An output is a change-output
if it has certain matching attributes with all inputs.
1. When inputs are first processed, add_input() is called on each one to determine if they all match.
2. Outputs are tested using output_matches() to tell whether they are admissible as a change-output.
3. Before signing each input, check_input() is used to ensure that the attribute has not changed.
MatchCheckers are used to identify the change-output in a transaction. An output is
a change-output if it has a certain matching attribute with all inputs.
1. When inputs are first processed, add_input() is called on each one to determine
if they all match.
2. Outputs are tested using output_matches() to tell whether they are admissible as
a change-output.
3. Before signing each input, check_input() is used to ensure that the attribute has
not changed.
There are two possible paths:
(a) If all inputs match on the attribute, the matching value is stored. Every output
that matches the stored value is admissible as a change-output.
(b) If some inputs do not match, a special value MISMATCH is stored. When the
matcher is in this state, _no outputs_ are admissible as change-outputs.
check_input() is a no-op in this case: if there is no matching attribute to
check against, we cannot detect modifications.
"""
MISMATCH = object()
UNDEFINED = object()
def __init__(self) -> None:
self.attribute = self.UNDEFINED # type: object
self.attribute = self.UNDEFINED # type: Any
self.read_only = False # Failsafe to ensure that add_input() is not accidentally called after output_matches().
def attribute_from_tx(self, txio: Union[TxInputType, TxOutputType]) -> object:
def attribute_from_tx(self, txio: Union[TxInputType, TxOutputType]) -> Any:
# Return the attribute from the txio, which is to be used for matching.
# If the txio is invalid for matching, then return an object which
# evaluates as a boolean False.
@ -72,14 +85,14 @@ class MatchChecker:
class WalletPathChecker(MatchChecker):
def attribute_from_tx(self, txio: Union[TxInputType, TxOutputType]) -> object:
def attribute_from_tx(self, txio: Union[TxInputType, TxOutputType]) -> Any:
if not txio.address_n:
return None
return txio.address_n[:-_BIP32_WALLET_DEPTH]
class MultisigFingerprintChecker(MatchChecker):
def attribute_from_tx(self, txio: Union[TxInputType, TxOutputType]) -> object:
def attribute_from_tx(self, txio: Union[TxInputType, TxOutputType]) -> Any:
if not txio.multisig:
return None
return multisig.multisig_fingerprint(txio.multisig)