1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-04-18 08:09:03 +00:00

fixup! feat(python): implement session based trezorlib

This commit is contained in:
M1nd3r 2025-03-27 12:42:50 +01:00
parent 7ac0bb8888
commit dfaba33aae
3 changed files with 5 additions and 123 deletions

View File

@ -53,9 +53,6 @@ class ProtocolVersion(IntEnum):
class TrezorClient:
button_callback: t.Callable[[messages.ButtonRequest], None] | None = None
passphrase_callback: (
t.Callable[[Session, messages.PassphraseRequest], t.Any] | None
) = None
pin_callback: t.Callable[[messages.PinMatrixRequest], str] | None = None
_model: models.TrezorModel

View File

@ -33,15 +33,12 @@ from mnemonic import Mnemonic
from . import btc, mapping, messages, models, protobuf
from .client import (
MAX_PASSPHRASE_LENGTH,
PASSPHRASE_ON_DEVICE,
ProtocolVersion,
TrezorClient,
)
from .exceptions import Cancelled, TrezorFailure, UnexpectedMessageError
from .log import DUMP_BYTES
from .messages import Capability, DebugWaitType
from .protobuf import MessageType
from .messages import DebugWaitType
from .tools import parse_path
from .transport import Timeout
from .transport.session import Session
@ -1282,62 +1279,6 @@ class TrezorClientDebugLink(TrezorClient):
new_client.debug.t1_screenshot_counter = self.debug.t1_screenshot_counter
return new_client
def passphrase_callback(
self, session: Session, msg: messages.PassphraseRequest
) -> t.Any:
available_on_device = (
Capability.PassphraseEntry in session.features.capabilities
)
def send_passphrase(
passphrase: str | None = None, on_device: bool | None = None
) -> MessageType:
msg = messages.PassphraseAck(passphrase=passphrase, on_device=on_device)
resp = session.call_raw(msg)
if isinstance(resp, messages.Deprecated_PassphraseStateRequest):
if resp.state is not None:
session.id = resp.state
else:
raise RuntimeError("Object resp.state is None")
resp = session.call_raw(messages.Deprecated_PassphraseStateAck())
return resp
# short-circuit old style entry
if msg._on_device is True:
return send_passphrase(None, None)
try:
if isinstance(session, SessionDebugWrapper):
passphrase = self.ui.get_passphrase(
available_on_device=available_on_device
)
if passphrase is None:
passphrase = session.passphrase
else:
raise NotImplementedError
except Cancelled:
session.call_raw(messages.Cancel())
raise
if passphrase is PASSPHRASE_ON_DEVICE:
if not available_on_device:
session.call_raw(messages.Cancel())
raise RuntimeError("Device is not capable of entering passphrase")
else:
return send_passphrase(on_device=True)
# else process host-entered passphrase
if passphrase is None:
passphrase = ""
if not isinstance(passphrase, str):
raise RuntimeError(f"Passphrase must be a str {type(passphrase)}")
passphrase = Mnemonic.normalize_string(passphrase)
if len(passphrase) > MAX_PASSPHRASE_LENGTH:
session.call_raw(messages.Cancel())
raise ValueError("Passphrase too long")
return send_passphrase(passphrase, on_device=False)
def close_transport(self) -> None:
self.transport.close()
self.debug.close()
@ -1359,7 +1300,6 @@ class TrezorClientDebugLink(TrezorClient):
derive_cardano,
)
)
session.passphrase = passphrase
return session
def get_seedless_session(

View File

@ -14,7 +14,6 @@
# You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import os
import sys
import typing as t
@ -22,7 +21,7 @@ import click
from mnemonic import Mnemonic
from . import device, messages
from .client import MAX_PIN_LENGTH
from .client import MAX_PIN_LENGTH, PASSPHRASE_ON_DEVICE
from .exceptions import Cancelled
from .messages import Capability, PinMatrixRequestType, WordRequestType
from .transport.session import Session
@ -137,52 +136,6 @@ class ClickUI:
else:
return pin
def get_passphrase(
self, session: Session, request: messages.PassphraseRequest
) -> t.Any:
available_on_device = (
Capability.PassphraseEntry in session.features.capabilities
)
if available_on_device and not self.passphrase_on_host:
return session.call_raw(
messages.PassphraseAck(passphrase=None, on_device=True)
)
env_passphrase = os.getenv("PASSPHRASE")
if env_passphrase is not None:
echo("Passphrase required. Using PASSPHRASE environment variable.")
return session.call_raw(
messages.PassphraseAck(passphrase=env_passphrase, on_device=False)
)
while True:
try:
passphrase = prompt(
"Passphrase required",
hide_input=True,
default="",
show_default=False,
)
# In case user sees the input on the screen, we do not need confirmation
if not CAN_HANDLE_HIDDEN_INPUT:
break
second = prompt(
"Confirm your passphrase",
hide_input=True,
default="",
show_default=False,
)
if passphrase == second:
break
else:
echo("Passphrase did not match. Please try again.")
except click.Abort:
raise Cancelled from None
return session.call_raw(
messages.PassphraseAck(passphrase=passphrase, on_device=False)
)
class ScriptUI:
"""Interface to be used by scripts, not directly by user.
@ -218,10 +171,7 @@ class ScriptUI:
return pin
@staticmethod
def get_passphrase(session: Session, request: messages.PassphraseRequest) -> t.Any:
available_on_device = (
Capability.PassphraseEntry in session.features.capabilities
)
def get_passphrase(available_on_device: bool) -> str | object:
if available_on_device:
print("?PASSPHRASE available_on_device")
else:
@ -231,16 +181,11 @@ class ScriptUI:
if passphrase == "CANCEL":
raise Cancelled from None
elif passphrase == "ON_DEVICE":
return session.call_raw(
messages.PassphraseAck(passphrase=None, on_device=True)
)
return PASSPHRASE_ON_DEVICE
elif not passphrase.startswith(":"):
raise RuntimeError("Sent passphrase must start with ':'")
else:
passphrase = passphrase[1:]
return session.call_raw(
messages.PassphraseAck(passphrase=passphrase, on_device=False)
)
return passphrase[1:]
def mnemonic_words(