mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-26 09:28:13 +00:00
refactor(core): generate trezorproto module straight from Rust
This commit is contained in:
parent
69bea5cff4
commit
78a8b48f1e
@ -206,8 +206,7 @@ SOURCE_MOD += [
|
||||
|
||||
# rust mods
|
||||
SOURCE_MOD += [
|
||||
'embed/extmod/rustmods/modtrezorproto.c',
|
||||
'embed/extmod/rustmods/modtrezorui2.c',
|
||||
'embed/extmod/rustmods.c',
|
||||
]
|
||||
|
||||
# modutime
|
||||
|
@ -215,8 +215,7 @@ SOURCE_MOD += [
|
||||
|
||||
# rust mods
|
||||
SOURCE_MOD += [
|
||||
'embed/extmod/rustmods/modtrezorproto.c',
|
||||
'embed/extmod/rustmods/modtrezorui2.c',
|
||||
'embed/extmod/rustmods.c',
|
||||
]
|
||||
|
||||
# modutime
|
||||
|
@ -17,12 +17,13 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "librust.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
#if MICROPY_PY_TREZORUI2
|
||||
|
||||
#include "librust.h"
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_trezorui2, mp_module_trezorui2);
|
||||
#endif
|
||||
|
||||
#endif // MICROPY_PY_TREZORUI2
|
||||
#if MICROPY_PY_TREZORPROTO
|
||||
MP_REGISTER_MODULE(MP_QSTR_trezorproto, mp_module_trezorproto);
|
||||
#endif
|
@ -1,85 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "py/runtime.h"
|
||||
|
||||
#if MICROPY_PY_TREZORPROTO
|
||||
|
||||
#include "librust.h"
|
||||
|
||||
/// from trezor.protobuf import MessageType
|
||||
/// T = TypeVar("T", bound=MessageType)
|
||||
|
||||
/// def type_for_name(name: str) -> type[T]:
|
||||
/// """Find the message definition for the given protobuf name."""
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorutils_protobuf_type_for_name_obj,
|
||||
protobuf_type_for_name);
|
||||
|
||||
/// def type_for_wire(wire_type: int) -> type[T]:
|
||||
/// """Find the message definition for the given wire type (numeric
|
||||
/// identifier)."""
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorutils_protobuf_type_for_wire_obj,
|
||||
protobuf_type_for_wire);
|
||||
|
||||
/// def decode(
|
||||
/// buffer: bytes,
|
||||
/// msg_type: Type[T],
|
||||
/// enable_experimental: bool,
|
||||
/// ) -> T:
|
||||
/// """Decode data in the buffer into the specified message type."""
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorutils_protobuf_decode_obj,
|
||||
protobuf_decode);
|
||||
|
||||
/// def encoded_length(msg: MessageType) -> int:
|
||||
/// """Calculate length of encoding of the specified message."""
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorutils_protobuf_encoded_length_obj,
|
||||
protobuf_len);
|
||||
|
||||
/// def encode(buffer: bytearray, msg: MessageType) -> int:
|
||||
/// """Encode the message into the specified buffer. Return length of
|
||||
/// encoding."""
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorutils_protobuf_encode_obj,
|
||||
protobuf_encode);
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_trezorproto_globals_table[] = {
|
||||
{MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_trezorproto)},
|
||||
|
||||
{MP_ROM_QSTR(MP_QSTR_type_for_name),
|
||||
MP_ROM_PTR(&mod_trezorutils_protobuf_type_for_name_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_type_for_wire),
|
||||
MP_ROM_PTR(&mod_trezorutils_protobuf_type_for_wire_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_decode),
|
||||
MP_ROM_PTR(&mod_trezorutils_protobuf_decode_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_encoded_length),
|
||||
MP_ROM_PTR(&mod_trezorutils_protobuf_encoded_length_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_encode),
|
||||
MP_ROM_PTR(&mod_trezorutils_protobuf_encode_obj)},
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_trezorproto_globals,
|
||||
mp_module_trezorproto_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_trezorproto = {
|
||||
.base = {&mp_type_module},
|
||||
.globals = (mp_obj_dict_t *)&mp_module_trezorproto_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_trezorproto, mp_module_trezorproto);
|
||||
|
||||
#endif // MICROPY_PY_TREZORPROTO
|
@ -1,17 +1,13 @@
|
||||
#include "librust_qstr.h"
|
||||
#include "py/obj.h"
|
||||
|
||||
mp_obj_t protobuf_type_for_name(mp_obj_t name);
|
||||
mp_obj_t protobuf_type_for_wire(mp_obj_t wire_id);
|
||||
mp_obj_t protobuf_decode(mp_obj_t buf, mp_obj_t def,
|
||||
mp_obj_t enable_experimental);
|
||||
mp_obj_t protobuf_len(mp_obj_t obj);
|
||||
mp_obj_t protobuf_encode(mp_obj_t buf, mp_obj_t obj);
|
||||
#include "librust_qstr.h"
|
||||
|
||||
#ifdef TREZOR_EMULATOR
|
||||
mp_obj_t protobuf_debug_msg_type();
|
||||
mp_obj_t protobuf_debug_msg_def_type();
|
||||
#endif
|
||||
|
||||
extern mp_obj_module_t mp_module_trezorproto;
|
||||
extern mp_obj_module_t mp_module_trezorui2;
|
||||
|
||||
#ifdef TREZOR_EMULATOR
|
||||
|
@ -55,10 +55,13 @@ static void _librust_qstrs(void) {
|
||||
MP_QSTR_confirm_with_info;
|
||||
MP_QSTR_count;
|
||||
MP_QSTR_data;
|
||||
MP_QSTR_decode;
|
||||
MP_QSTR_description;
|
||||
MP_QSTR_disable_animation;
|
||||
MP_QSTR_draw_welcome_screen;
|
||||
MP_QSTR_dry_run;
|
||||
MP_QSTR_encode;
|
||||
MP_QSTR_encoded_length;
|
||||
MP_QSTR_extra;
|
||||
MP_QSTR_fee_amount;
|
||||
MP_QSTR_fee_label;
|
||||
@ -130,8 +133,11 @@ static void _librust_qstrs(void) {
|
||||
MP_QSTR_total_label;
|
||||
MP_QSTR_touch_event;
|
||||
MP_QSTR_trace;
|
||||
MP_QSTR_trezorproto;
|
||||
MP_QSTR_trezorui2;
|
||||
MP_QSTR_tutorial;
|
||||
MP_QSTR_type_for_name;
|
||||
MP_QSTR_type_for_wire;
|
||||
MP_QSTR_usb_event;
|
||||
MP_QSTR_user_fee_change;
|
||||
MP_QSTR_value;
|
||||
|
@ -15,29 +15,6 @@ use super::{
|
||||
zigzag,
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn protobuf_type_for_name(name: Obj) -> Obj {
|
||||
let block = || {
|
||||
let name = Qstr::try_from(name)?;
|
||||
let def = MsgDef::for_name(name.to_u16()).ok_or_else(|| Error::KeyError(name.into()))?;
|
||||
let obj = MsgDefObj::alloc(def)?.into();
|
||||
Ok(obj)
|
||||
};
|
||||
unsafe { util::try_or_raise(block) }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn protobuf_type_for_wire(wire_id: Obj) -> Obj {
|
||||
let block = || {
|
||||
let wire_id = u16::try_from(wire_id)?;
|
||||
let def = MsgDef::for_wire_id(wire_id).ok_or_else(|| Error::KeyError(wire_id.into()))?;
|
||||
let obj = MsgDefObj::alloc(def)?.into();
|
||||
Ok(obj)
|
||||
};
|
||||
unsafe { util::try_or_raise(block) }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn protobuf_decode(buf: Obj, msg_def: Obj, enable_experimental: Obj) -> Obj {
|
||||
let block = || {
|
||||
let def = Gc::<MsgDefObj>::try_from(msg_def)?;
|
||||
|
@ -12,7 +12,6 @@ use super::{
|
||||
zigzag,
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn protobuf_len(obj: Obj) -> Obj {
|
||||
let block = || {
|
||||
let obj = Gc::<MsgObj>::try_from(obj)?;
|
||||
@ -23,7 +22,6 @@ pub extern "C" fn protobuf_len(obj: Obj) -> Obj {
|
||||
unsafe { util::try_or_raise(block) }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn protobuf_encode(buf: Obj, obj: Obj) -> Obj {
|
||||
let block = || {
|
||||
let obj = Gc::<MsgObj>::try_from(obj)?;
|
||||
|
@ -7,6 +7,7 @@ use crate::{
|
||||
ffi,
|
||||
gc::Gc,
|
||||
map::Map,
|
||||
module::Module,
|
||||
obj::{Obj, ObjBase},
|
||||
qstr::Qstr,
|
||||
typ::Type,
|
||||
@ -15,8 +16,9 @@ use crate::{
|
||||
};
|
||||
|
||||
use super::{
|
||||
decode::Decoder,
|
||||
decode::{protobuf_decode, Decoder},
|
||||
defs::{find_name_by_msg_offset, get_msg, MsgDef},
|
||||
encode::{protobuf_encode, protobuf_len},
|
||||
};
|
||||
|
||||
#[repr(C)]
|
||||
@ -289,3 +291,72 @@ pub extern "C" fn protobuf_debug_msg_type() -> &'static Type {
|
||||
pub extern "C" fn protobuf_debug_msg_def_type() -> &'static Type {
|
||||
MsgDefObj::obj_type()
|
||||
}
|
||||
|
||||
pub extern "C" fn protobuf_type_for_name(name: Obj) -> Obj {
|
||||
let block = || {
|
||||
let name = Qstr::try_from(name)?;
|
||||
let def = MsgDef::for_name(name.to_u16()).ok_or_else(|| Error::KeyError(name.into()))?;
|
||||
let obj = MsgDefObj::alloc(def)?.into();
|
||||
Ok(obj)
|
||||
};
|
||||
unsafe { util::try_or_raise(block) }
|
||||
}
|
||||
|
||||
pub extern "C" fn protobuf_type_for_wire(wire_id: Obj) -> Obj {
|
||||
let block = || {
|
||||
let wire_id = u16::try_from(wire_id)?;
|
||||
let def = MsgDef::for_wire_id(wire_id).ok_or_else(|| Error::KeyError(wire_id.into()))?;
|
||||
let obj = MsgDefObj::alloc(def)?.into();
|
||||
Ok(obj)
|
||||
};
|
||||
unsafe { util::try_or_raise(block) }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub static mp_module_trezorproto: Module = obj_module! {
|
||||
/// from typing_extensions import Self
|
||||
///
|
||||
/// # XXX
|
||||
/// # Note that MessageType "subclasses" are not true subclasses, but instead instances
|
||||
/// # of the built-in metaclass MsgDef. MessageType instances are in fact instances of
|
||||
/// # the built-in type Msg. That is why isinstance checks do not work, and instead the
|
||||
/// # MessageTypeSubclass.is_type_of() method must be used.
|
||||
///
|
||||
/// class MessageType:
|
||||
/// MESSAGE_NAME: ClassVar[str] = "MessageType"
|
||||
/// MESSAGE_WIRE_TYPE: ClassVar[int | None] = None
|
||||
///
|
||||
/// @classmethod
|
||||
/// def is_type_of(cls: type[Self], msg: "MessageType") -> TypeGuard[Self]:
|
||||
/// """Identify if the provided message belongs to this type."""
|
||||
///
|
||||
/// mock:global
|
||||
/// T = TypeVar("T", bound=MessageType)
|
||||
|
||||
Qstr::MP_QSTR___name__ => Qstr::MP_QSTR_trezorproto.to_obj(),
|
||||
|
||||
/// def type_for_name(name: str) -> type[MessageType]:
|
||||
/// """Find the message definition for the given protobuf name."""
|
||||
Qstr::MP_QSTR_type_for_name => obj_fn_1!(protobuf_type_for_name).as_obj(),
|
||||
|
||||
/// def type_for_wire(wire_id: int) -> type[MessageType]:
|
||||
/// """Find the message definition for the given wire type (numeric identifier)."""
|
||||
Qstr::MP_QSTR_type_for_wire => obj_fn_1!(protobuf_type_for_wire).as_obj(),
|
||||
|
||||
/// def decode(
|
||||
/// buffer: bytes,
|
||||
/// msg_type: type[T],
|
||||
/// enable_experimental: bool,
|
||||
/// ) -> T:
|
||||
/// """Decode data in the buffer into the specified message type."""
|
||||
Qstr::MP_QSTR_decode => obj_fn_3!(protobuf_decode).as_obj(),
|
||||
|
||||
/// def encoded_length(msg: MessageType) -> int:
|
||||
/// """Calculate length of encoding of the specified message."""
|
||||
Qstr::MP_QSTR_encoded_length => obj_fn_1!(protobuf_len).as_obj(),
|
||||
|
||||
/// def encode(buffer: bytearray, msg: MessageType) -> int:
|
||||
/// """Encode the message into the specified buffer. Return length of
|
||||
/// encoding."""
|
||||
Qstr::MP_QSTR_encode => obj_fn_2!(protobuf_encode).as_obj()
|
||||
};
|
||||
|
@ -1,34 +1,47 @@
|
||||
from typing import *
|
||||
from trezor.protobuf import MessageType
|
||||
from typing_extensions import Self
|
||||
# XXX
|
||||
# Note that MessageType "subclasses" are not true subclasses, but instead instances
|
||||
# of the built-in metaclass MsgDef. MessageType instances are in fact instances of
|
||||
# the built-in type Msg. That is why isinstance checks do not work, and instead the
|
||||
# MessageTypeSubclass.is_type_of() method must be used.
|
||||
|
||||
|
||||
# rust/src/protobuf/obj.rs
|
||||
class MessageType:
|
||||
MESSAGE_NAME: ClassVar[str] = "MessageType"
|
||||
MESSAGE_WIRE_TYPE: ClassVar[int | None] = None
|
||||
@classmethod
|
||||
def is_type_of(cls: type[Self], msg: "MessageType") -> TypeGuard[Self]:
|
||||
"""Identify if the provided message belongs to this type."""
|
||||
T = TypeVar("T", bound=MessageType)
|
||||
|
||||
|
||||
# extmod/rustmods/modtrezorproto.c
|
||||
def type_for_name(name: str) -> type[T]:
|
||||
# rust/src/protobuf/obj.rs
|
||||
def type_for_name(name: str) -> type[MessageType]:
|
||||
"""Find the message definition for the given protobuf name."""
|
||||
|
||||
|
||||
# extmod/rustmods/modtrezorproto.c
|
||||
def type_for_wire(wire_type: int) -> type[T]:
|
||||
"""Find the message definition for the given wire type (numeric
|
||||
identifier)."""
|
||||
# rust/src/protobuf/obj.rs
|
||||
def type_for_wire(wire_id: int) -> type[MessageType]:
|
||||
"""Find the message definition for the given wire type (numeric identifier)."""
|
||||
|
||||
|
||||
# extmod/rustmods/modtrezorproto.c
|
||||
# rust/src/protobuf/obj.rs
|
||||
def decode(
|
||||
buffer: bytes,
|
||||
msg_type: Type[T],
|
||||
msg_type: type[T],
|
||||
enable_experimental: bool,
|
||||
) -> T:
|
||||
"""Decode data in the buffer into the specified message type."""
|
||||
|
||||
|
||||
# extmod/rustmods/modtrezorproto.c
|
||||
# rust/src/protobuf/obj.rs
|
||||
def encoded_length(msg: MessageType) -> int:
|
||||
"""Calculate length of encoding of the specified message."""
|
||||
|
||||
|
||||
# extmod/rustmods/modtrezorproto.c
|
||||
# rust/src/protobuf/obj.rs
|
||||
def encode(buffer: bytearray, msg: MessageType) -> int:
|
||||
"""Encode the message into the specified buffer. Return length of
|
||||
encoding."""
|
||||
|
@ -9,23 +9,7 @@ type_for_name = trezorproto.type_for_name
|
||||
type_for_wire = trezorproto.type_for_wire
|
||||
|
||||
if TYPE_CHECKING:
|
||||
# XXX
|
||||
# Note that MessageType "subclasses" are not true subclasses, but instead instances
|
||||
# of the built-in metaclass MsgDef. MessageType instances are in fact instances of
|
||||
# the built-in type Msg. That is why isinstance checks do not work, and instead the
|
||||
# MessageTypeSubclass.is_type_of() method must be used.
|
||||
from typing import TypeGuard, TypeVar
|
||||
|
||||
T = TypeVar("T", bound="MessageType")
|
||||
|
||||
class MessageType:
|
||||
MESSAGE_NAME: str = "MessageType"
|
||||
MESSAGE_WIRE_TYPE: int | None = None
|
||||
|
||||
@classmethod
|
||||
def is_type_of(cls: type[T], msg: "MessageType") -> TypeGuard[T]:
|
||||
"""Identify if the provided message belongs to this type."""
|
||||
raise NotImplementedError
|
||||
MessageType = trezorproto.MessageType
|
||||
|
||||
|
||||
def load_message_buffer(
|
||||
|
Loading…
Reference in New Issue
Block a user