mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-07-01 12:22:34 +00:00
DOCS: hello world feature - core, protobuf, trezorlib, tests
This commit is contained in:
parent
ed1785a985
commit
e1cbb8a970
28
common/protob/messages-hello.proto
Normal file
28
common/protob/messages-hello.proto
Normal file
@ -0,0 +1,28 @@
|
||||
syntax = "proto2";
|
||||
package hw.trezor.messages.helloworld;
|
||||
|
||||
// Sugar for easier handling in Java
|
||||
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
||||
option java_outer_classname = "TrezorMessageHelloWorld";
|
||||
|
||||
import "messages.proto";
|
||||
|
||||
|
||||
/**
|
||||
* Request: Hello world request for text
|
||||
* @next HelloWorldResponse
|
||||
* @next Failure
|
||||
*/
|
||||
message HelloWorldRequest {
|
||||
required string name = 1;
|
||||
optional uint32 amount = 2 [default=1];
|
||||
optional bool show_display = 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Response: Hello world text
|
||||
* @end
|
||||
*/
|
||||
message HelloWorldResponse {
|
||||
required string text = 1;
|
||||
}
|
@ -372,4 +372,8 @@ enum MessageType {
|
||||
MessageType_SolanaAddress = 903 [(wire_out) = true];
|
||||
MessageType_SolanaSignTx = 904 [(wire_in) = true];
|
||||
MessageType_SolanaTxSignature = 905 [(wire_out) = true];
|
||||
|
||||
// Hello world
|
||||
MessageType_HelloWorldRequest = 1000 [(wire_in) = true];
|
||||
MessageType_HelloWorldResponse = 1001 [(wire_out) = true];
|
||||
}
|
||||
|
@ -365,6 +365,8 @@ apps.misc.get_entropy
|
||||
import apps.misc.get_entropy
|
||||
apps.misc.get_firmware_hash
|
||||
import apps.misc.get_firmware_hash
|
||||
apps.misc.hello_world
|
||||
import apps.misc.hello_world
|
||||
apps.misc.sign_identity
|
||||
import apps.misc.sign_identity
|
||||
apps.workflow_handlers
|
||||
|
23
core/src/apps/misc/hello_world.py
Normal file
23
core/src/apps/misc/hello_world.py
Normal file
@ -0,0 +1,23 @@
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from trezor.messages import HelloWorldResponse
|
||||
from trezor.ui.layouts import confirm_text
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from trezor.messages import HelloWorldRequest
|
||||
|
||||
|
||||
async def hello_world(msg: HelloWorldRequest) -> HelloWorldResponse:
|
||||
text = _get_text_from_msg(msg)
|
||||
if msg.show_display:
|
||||
await confirm_text(
|
||||
"confirm_hello_world",
|
||||
"Hello world",
|
||||
text,
|
||||
description="Hello world example",
|
||||
)
|
||||
return HelloWorldResponse(text=text)
|
||||
|
||||
|
||||
def _get_text_from_msg(msg: HelloWorldRequest) -> str:
|
||||
return msg.amount * f"Hello {msg.name}!\n"
|
@ -93,6 +93,8 @@ def _find_message_handler_module(msg_type: int) -> str:
|
||||
return "apps.misc.get_firmware_hash"
|
||||
if msg_type == MessageType.CosiCommit:
|
||||
return "apps.misc.cosi_commit"
|
||||
if msg_type == MessageType.HelloWorldRequest:
|
||||
return "apps.misc.hello_world"
|
||||
|
||||
if not utils.BITCOIN_ONLY:
|
||||
if msg_type == MessageType.SetU2FCounter:
|
||||
|
@ -243,3 +243,5 @@ if not utils.BITCOIN_ONLY:
|
||||
SolanaAddress = 903
|
||||
SolanaSignTx = 904
|
||||
SolanaTxSignature = 905
|
||||
HelloWorldRequest = 1000
|
||||
HelloWorldResponse = 1001
|
||||
|
@ -261,6 +261,8 @@ if TYPE_CHECKING:
|
||||
SolanaAddress = 903
|
||||
SolanaSignTx = 904
|
||||
SolanaTxSignature = 905
|
||||
HelloWorldRequest = 1000
|
||||
HelloWorldResponse = 1001
|
||||
|
||||
class FailureType(IntEnum):
|
||||
UnexpectedMessage = 1
|
||||
|
@ -3923,6 +3923,38 @@ if TYPE_CHECKING:
|
||||
def is_type_of(cls, msg: Any) -> TypeGuard["EthereumAccessList"]:
|
||||
return isinstance(msg, cls)
|
||||
|
||||
class HelloWorldRequest(protobuf.MessageType):
|
||||
name: "str"
|
||||
amount: "int"
|
||||
show_display: "bool | None"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
name: "str",
|
||||
amount: "int | None" = None,
|
||||
show_display: "bool | None" = None,
|
||||
) -> None:
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def is_type_of(cls, msg: Any) -> TypeGuard["HelloWorldRequest"]:
|
||||
return isinstance(msg, cls)
|
||||
|
||||
class HelloWorldResponse(protobuf.MessageType):
|
||||
text: "str"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
text: "str",
|
||||
) -> None:
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def is_type_of(cls, msg: Any) -> TypeGuard["HelloWorldResponse"]:
|
||||
return isinstance(msg, cls)
|
||||
|
||||
class MoneroTransactionSourceEntry(protobuf.MessageType):
|
||||
outputs: "list[MoneroOutputEntry]"
|
||||
real_output: "int | None"
|
||||
|
14
core/tests/test_apps.misc.hello_world.py
Normal file
14
core/tests/test_apps.misc.hello_world.py
Normal file
@ -0,0 +1,14 @@
|
||||
from common import *
|
||||
|
||||
from trezor.messages import HelloWorldRequest
|
||||
from apps.misc.hello_world import _get_text_from_msg
|
||||
|
||||
|
||||
class TestHelloWorld(unittest.TestCase):
|
||||
def test_get_text_from_msg(self):
|
||||
msg = HelloWorldRequest(name="Satoshi", amount=2, show_display=False)
|
||||
self.assertEqual(_get_text_from_msg(msg), "Hello Satoshi!\nHello Satoshi!\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
@ -9,7 +9,8 @@ SKIPPED_MESSAGES := Binance Cardano DebugMonero Eos Monero Ontology Ripple SdPro
|
||||
EthereumSignTypedData EthereumTypedDataStructRequest EthereumTypedDataStructAck \
|
||||
EthereumTypedDataValueRequest EthereumTypedDataValueAck ShowDeviceTutorial \
|
||||
UnlockBootloader AuthenticateDevice AuthenticityProof \
|
||||
Solana StellarClaimClaimableBalanceOp
|
||||
Solana StellarClaimClaimableBalanceOp \
|
||||
HelloWorldRequest HelloWorldResponse
|
||||
|
||||
ifeq ($(BITCOIN_ONLY), 1)
|
||||
SKIPPED_MESSAGES += Ethereum NEM Stellar
|
||||
|
28
python/src/trezorlib/cli/hello_world.py
Normal file
28
python/src/trezorlib/cli/hello_world.py
Normal file
@ -0,0 +1,28 @@
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
import click
|
||||
|
||||
from .. import hello_world
|
||||
from . import with_client
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..client import TrezorClient
|
||||
|
||||
|
||||
@click.group(name="helloworld")
|
||||
def cli() -> None:
|
||||
"""Hello world commands."""
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.argument("name")
|
||||
@click.option("-a", "--amount", type=int, help="How many times to greet.")
|
||||
@click.option(
|
||||
"-d", "--show-display", is_flag=True, help="Whether to show confirmation screen."
|
||||
)
|
||||
@with_client
|
||||
def say_hello(
|
||||
client: "TrezorClient", name: str, amount: Optional[int], show_display: bool
|
||||
) -> str:
|
||||
"""Simply say hello to the supplied name."""
|
||||
return hello_world.say_hello(client, name, amount, show_display=show_display)
|
@ -42,6 +42,7 @@ from . import (
|
||||
ethereum,
|
||||
fido,
|
||||
firmware,
|
||||
hello_world,
|
||||
monero,
|
||||
nem,
|
||||
ripple,
|
||||
@ -407,6 +408,7 @@ cli.add_command(crypto.cli)
|
||||
cli.add_command(device.cli)
|
||||
cli.add_command(eos.cli)
|
||||
cli.add_command(ethereum.cli)
|
||||
cli.add_command(hello_world.cli)
|
||||
cli.add_command(fido.cli)
|
||||
cli.add_command(monero.cli)
|
||||
cli.add_command(nem.cli)
|
||||
|
24
python/src/trezorlib/hello_world.py
Normal file
24
python/src/trezorlib/hello_world.py
Normal file
@ -0,0 +1,24 @@
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from . import messages
|
||||
from .tools import expect
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .client import TrezorClient
|
||||
from .protobuf import MessageType
|
||||
|
||||
|
||||
@expect(messages.HelloWorldResponse, field="text", ret_type=str)
|
||||
def say_hello(
|
||||
client: "TrezorClient",
|
||||
name: str,
|
||||
amount: Optional[int],
|
||||
show_display: bool,
|
||||
) -> "MessageType":
|
||||
return client.call(
|
||||
messages.HelloWorldRequest(
|
||||
name=name,
|
||||
amount=amount,
|
||||
show_display=show_display,
|
||||
)
|
||||
)
|
@ -269,6 +269,8 @@ class MessageType(IntEnum):
|
||||
SolanaAddress = 903
|
||||
SolanaSignTx = 904
|
||||
SolanaTxSignature = 905
|
||||
HelloWorldRequest = 1000
|
||||
HelloWorldResponse = 1001
|
||||
|
||||
|
||||
class FailureType(IntEnum):
|
||||
@ -5211,6 +5213,40 @@ class EthereumAccessList(protobuf.MessageType):
|
||||
self.address = address
|
||||
|
||||
|
||||
class HelloWorldRequest(protobuf.MessageType):
|
||||
MESSAGE_WIRE_TYPE = 1000
|
||||
FIELDS = {
|
||||
1: protobuf.Field("name", "string", repeated=False, required=True),
|
||||
2: protobuf.Field("amount", "uint32", repeated=False, required=False, default=1),
|
||||
3: protobuf.Field("show_display", "bool", repeated=False, required=False, default=None),
|
||||
}
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
name: "str",
|
||||
amount: Optional["int"] = 1,
|
||||
show_display: Optional["bool"] = None,
|
||||
) -> None:
|
||||
self.name = name
|
||||
self.amount = amount
|
||||
self.show_display = show_display
|
||||
|
||||
|
||||
class HelloWorldResponse(protobuf.MessageType):
|
||||
MESSAGE_WIRE_TYPE = 1001
|
||||
FIELDS = {
|
||||
1: protobuf.Field("text", "string", repeated=False, required=True),
|
||||
}
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
text: "str",
|
||||
) -> None:
|
||||
self.text = text
|
||||
|
||||
|
||||
class MoneroTransactionSourceEntry(protobuf.MessageType):
|
||||
MESSAGE_WIRE_TYPE = None
|
||||
FIELDS = {
|
||||
|
2
rust/trezor-client/src/messages/generated.rs
generated
2
rust/trezor-client/src/messages/generated.rs
generated
@ -246,6 +246,8 @@ trezor_message_impl! {
|
||||
SolanaAddress => MessageType_SolanaAddress,
|
||||
SolanaSignTx => MessageType_SolanaSignTx,
|
||||
SolanaTxSignature => MessageType_SolanaTxSignature,
|
||||
HelloWorldRequest => MessageType_HelloWorldRequest,
|
||||
HelloWorldResponse => MessageType_HelloWorldResponse,
|
||||
}
|
||||
|
||||
#[cfg(feature = "stellar")]
|
||||
|
64
rust/trezor-client/src/protos/generated/messages.rs
generated
64
rust/trezor-client/src/protos/generated/messages.rs
generated
@ -508,6 +508,10 @@ pub enum MessageType {
|
||||
MessageType_SolanaSignTx = 904,
|
||||
// @@protoc_insertion_point(enum_value:hw.trezor.messages.MessageType.MessageType_SolanaTxSignature)
|
||||
MessageType_SolanaTxSignature = 905,
|
||||
// @@protoc_insertion_point(enum_value:hw.trezor.messages.MessageType.MessageType_HelloWorldRequest)
|
||||
MessageType_HelloWorldRequest = 1000,
|
||||
// @@protoc_insertion_point(enum_value:hw.trezor.messages.MessageType.MessageType_HelloWorldResponse)
|
||||
MessageType_HelloWorldResponse = 1001,
|
||||
}
|
||||
|
||||
impl ::protobuf::Enum for MessageType {
|
||||
@ -759,6 +763,8 @@ impl ::protobuf::Enum for MessageType {
|
||||
903 => ::std::option::Option::Some(MessageType::MessageType_SolanaAddress),
|
||||
904 => ::std::option::Option::Some(MessageType::MessageType_SolanaSignTx),
|
||||
905 => ::std::option::Option::Some(MessageType::MessageType_SolanaTxSignature),
|
||||
1000 => ::std::option::Option::Some(MessageType::MessageType_HelloWorldRequest),
|
||||
1001 => ::std::option::Option::Some(MessageType::MessageType_HelloWorldResponse),
|
||||
_ => ::std::option::Option::None
|
||||
}
|
||||
}
|
||||
@ -1005,6 +1011,8 @@ impl ::protobuf::Enum for MessageType {
|
||||
"MessageType_SolanaAddress" => ::std::option::Option::Some(MessageType::MessageType_SolanaAddress),
|
||||
"MessageType_SolanaSignTx" => ::std::option::Option::Some(MessageType::MessageType_SolanaSignTx),
|
||||
"MessageType_SolanaTxSignature" => ::std::option::Option::Some(MessageType::MessageType_SolanaTxSignature),
|
||||
"MessageType_HelloWorldRequest" => ::std::option::Option::Some(MessageType::MessageType_HelloWorldRequest),
|
||||
"MessageType_HelloWorldResponse" => ::std::option::Option::Some(MessageType::MessageType_HelloWorldResponse),
|
||||
_ => ::std::option::Option::None
|
||||
}
|
||||
}
|
||||
@ -1250,6 +1258,8 @@ impl ::protobuf::Enum for MessageType {
|
||||
MessageType::MessageType_SolanaAddress,
|
||||
MessageType::MessageType_SolanaSignTx,
|
||||
MessageType::MessageType_SolanaTxSignature,
|
||||
MessageType::MessageType_HelloWorldRequest,
|
||||
MessageType::MessageType_HelloWorldResponse,
|
||||
];
|
||||
}
|
||||
|
||||
@ -1501,6 +1511,8 @@ impl ::protobuf::EnumFull for MessageType {
|
||||
MessageType::MessageType_SolanaAddress => 237,
|
||||
MessageType::MessageType_SolanaSignTx => 238,
|
||||
MessageType::MessageType_SolanaTxSignature => 239,
|
||||
MessageType::MessageType_HelloWorldRequest => 240,
|
||||
MessageType::MessageType_HelloWorldResponse => 241,
|
||||
};
|
||||
Self::enum_descriptor().value_by_index(index)
|
||||
}
|
||||
@ -1550,7 +1562,7 @@ pub mod exts {
|
||||
|
||||
static file_descriptor_proto_data: &'static [u8] = b"\
|
||||
\n\x0emessages.proto\x12\x12hw.trezor.messages\x1a\x20google/protobuf/de\
|
||||
scriptor.proto*\x8bS\n\x0bMessageType\x12(\n\x16MessageType_Initialize\
|
||||
scriptor.proto*\xe0S\n\x0bMessageType\x12(\n\x16MessageType_Initialize\
|
||||
\x10\0\x1a\x0c\x80\xa6\x1d\x01\xb0\xb5\x18\x01\x90\xb5\x18\x01\x12\x1e\n\
|
||||
\x10MessageType_Ping\x10\x01\x1a\x08\x80\xa6\x1d\x01\x90\xb5\x18\x01\x12\
|
||||
%\n\x13MessageType_Success\x10\x02\x1a\x0c\x80\xa6\x1d\x01\xa8\xb5\x18\
|
||||
@ -1821,30 +1833,32 @@ static file_descriptor_proto_data: &'static [u8] = b"\
|
||||
\x07\x1a\x04\x90\xb5\x18\x01\x12$\n\x19MessageType_SolanaAddress\x10\x87\
|
||||
\x07\x1a\x04\x98\xb5\x18\x01\x12#\n\x18MessageType_SolanaSignTx\x10\x88\
|
||||
\x07\x1a\x04\x90\xb5\x18\x01\x12(\n\x1dMessageType_SolanaTxSignature\x10\
|
||||
\x89\x07\x1a\x04\x98\xb5\x18\x01\x1a\x04\xc8\xf3\x18\x01\"\x04\x08Z\x10\
|
||||
\\\"\x04\x08r\x10z\"\x06\x08\xdb\x01\x10\xdb\x01\"\x06\x08\xe0\x01\x10\
|
||||
\xe0\x01\"\x06\x08\xac\x02\x10\xb0\x02\"\x06\x08\xb5\x02\x10\xb8\x02:<\n\
|
||||
\x07wire_in\x18\xd2\x86\x03\x20\x01(\x08\x12!.google.protobuf.EnumValueO\
|
||||
ptionsR\x06wireIn:>\n\x08wire_out\x18\xd3\x86\x03\x20\x01(\x08\x12!.goog\
|
||||
le.protobuf.EnumValueOptionsR\x07wireOut:G\n\rwire_debug_in\x18\xd4\x86\
|
||||
\x03\x20\x01(\x08\x12!.google.protobuf.EnumValueOptionsR\x0bwireDebugIn:\
|
||||
I\n\x0ewire_debug_out\x18\xd5\x86\x03\x20\x01(\x08\x12!.google.protobuf.\
|
||||
EnumValueOptionsR\x0cwireDebugOut:@\n\twire_tiny\x18\xd6\x86\x03\x20\x01\
|
||||
(\x08\x12!.google.protobuf.EnumValueOptionsR\x08wireTiny:L\n\x0fwire_boo\
|
||||
tloader\x18\xd7\x86\x03\x20\x01(\x08\x12!.google.protobuf.EnumValueOptio\
|
||||
nsR\x0ewireBootloader:C\n\x0bwire_no_fsm\x18\xd8\x86\x03\x20\x01(\x08\
|
||||
\x12!.google.protobuf.EnumValueOptionsR\twireNoFsm:F\n\x0cbitcoin_only\
|
||||
\x18\xe0\xd4\x03\x20\x01(\x08\x12!.google.protobuf.EnumValueOptionsR\x0b\
|
||||
bitcoinOnly:U\n\x17has_bitcoin_only_values\x18\xb9\x8e\x03\x20\x01(\x08\
|
||||
\x12\x1c.google.protobuf.EnumOptionsR\x14hasBitcoinOnlyValues:T\n\x14exp\
|
||||
erimental_message\x18\xa1\x96\x03\x20\x01(\x08\x12\x1f.google.protobuf.M\
|
||||
essageOptionsR\x13experimentalMessage:>\n\twire_type\x18\xa2\x96\x03\x20\
|
||||
\x01(\r\x12\x1f.google.protobuf.MessageOptionsR\x08wireType:N\n\x12exper\
|
||||
imental_field\x18\x89\x9e\x03\x20\x01(\x08\x12\x1d.google.protobuf.Field\
|
||||
OptionsR\x11experimentalField:U\n\x17include_in_bitcoin_only\x18\xe0\xd4\
|
||||
\x03\x20\x01(\x08\x12\x1c.google.protobuf.FileOptionsR\x14includeInBitco\
|
||||
inOnlyB8\n#com.satoshilabs.trezor.lib.protobufB\rTrezorMessage\x80\xa6\
|
||||
\x1d\x01\
|
||||
\x89\x07\x1a\x04\x98\xb5\x18\x01\x12(\n\x1dMessageType_HelloWorldRequest\
|
||||
\x10\xe8\x07\x1a\x04\x90\xb5\x18\x01\x12)\n\x1eMessageType_HelloWorldRes\
|
||||
ponse\x10\xe9\x07\x1a\x04\x98\xb5\x18\x01\x1a\x04\xc8\xf3\x18\x01\"\x04\
|
||||
\x08Z\x10\\\"\x04\x08r\x10z\"\x06\x08\xdb\x01\x10\xdb\x01\"\x06\x08\xe0\
|
||||
\x01\x10\xe0\x01\"\x06\x08\xac\x02\x10\xb0\x02\"\x06\x08\xb5\x02\x10\xb8\
|
||||
\x02:<\n\x07wire_in\x18\xd2\x86\x03\x20\x01(\x08\x12!.google.protobuf.En\
|
||||
umValueOptionsR\x06wireIn:>\n\x08wire_out\x18\xd3\x86\x03\x20\x01(\x08\
|
||||
\x12!.google.protobuf.EnumValueOptionsR\x07wireOut:G\n\rwire_debug_in\
|
||||
\x18\xd4\x86\x03\x20\x01(\x08\x12!.google.protobuf.EnumValueOptionsR\x0b\
|
||||
wireDebugIn:I\n\x0ewire_debug_out\x18\xd5\x86\x03\x20\x01(\x08\x12!.goog\
|
||||
le.protobuf.EnumValueOptionsR\x0cwireDebugOut:@\n\twire_tiny\x18\xd6\x86\
|
||||
\x03\x20\x01(\x08\x12!.google.protobuf.EnumValueOptionsR\x08wireTiny:L\n\
|
||||
\x0fwire_bootloader\x18\xd7\x86\x03\x20\x01(\x08\x12!.google.protobuf.En\
|
||||
umValueOptionsR\x0ewireBootloader:C\n\x0bwire_no_fsm\x18\xd8\x86\x03\x20\
|
||||
\x01(\x08\x12!.google.protobuf.EnumValueOptionsR\twireNoFsm:F\n\x0cbitco\
|
||||
in_only\x18\xe0\xd4\x03\x20\x01(\x08\x12!.google.protobuf.EnumValueOptio\
|
||||
nsR\x0bbitcoinOnly:U\n\x17has_bitcoin_only_values\x18\xb9\x8e\x03\x20\
|
||||
\x01(\x08\x12\x1c.google.protobuf.EnumOptionsR\x14hasBitcoinOnlyValues:T\
|
||||
\n\x14experimental_message\x18\xa1\x96\x03\x20\x01(\x08\x12\x1f.google.p\
|
||||
rotobuf.MessageOptionsR\x13experimentalMessage:>\n\twire_type\x18\xa2\
|
||||
\x96\x03\x20\x01(\r\x12\x1f.google.protobuf.MessageOptionsR\x08wireType:\
|
||||
N\n\x12experimental_field\x18\x89\x9e\x03\x20\x01(\x08\x12\x1d.google.pr\
|
||||
otobuf.FieldOptionsR\x11experimentalField:U\n\x17include_in_bitcoin_only\
|
||||
\x18\xe0\xd4\x03\x20\x01(\x08\x12\x1c.google.protobuf.FileOptionsR\x14in\
|
||||
cludeInBitcoinOnlyB8\n#com.satoshilabs.trezor.lib.protobufB\rTrezorMessa\
|
||||
ge\x80\xa6\x1d\x01\
|
||||
";
|
||||
|
||||
/// `FileDescriptorProto` object which was a source for this generated file
|
||||
|
462
rust/trezor-client/src/protos/generated/messages_hello.rs
generated
Normal file
462
rust/trezor-client/src/protos/generated/messages_hello.rs
generated
Normal file
@ -0,0 +1,462 @@
|
||||
// This file is generated by rust-protobuf 3.3.0. Do not edit
|
||||
// .proto file is parsed by protoc 3.19.6
|
||||
// @generated
|
||||
|
||||
// https://github.com/rust-lang/rust-clippy/issues/702
|
||||
#![allow(unknown_lints)]
|
||||
#![allow(clippy::all)]
|
||||
|
||||
#![allow(unused_attributes)]
|
||||
#![cfg_attr(rustfmt, rustfmt::skip)]
|
||||
|
||||
#![allow(box_pointers)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(missing_docs)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(non_upper_case_globals)]
|
||||
#![allow(trivial_casts)]
|
||||
#![allow(unused_results)]
|
||||
#![allow(unused_mut)]
|
||||
|
||||
//! Generated file from `messages-hello.proto`
|
||||
|
||||
/// Generated files are compatible only with the same version
|
||||
/// of protobuf runtime.
|
||||
const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_3_3_0;
|
||||
|
||||
// @@protoc_insertion_point(message:hw.trezor.messages.helloworld.HelloWorldRequest)
|
||||
#[derive(PartialEq,Clone,Default,Debug)]
|
||||
pub struct HelloWorldRequest {
|
||||
// message fields
|
||||
// @@protoc_insertion_point(field:hw.trezor.messages.helloworld.HelloWorldRequest.name)
|
||||
pub name: ::std::option::Option<::std::string::String>,
|
||||
// @@protoc_insertion_point(field:hw.trezor.messages.helloworld.HelloWorldRequest.amount)
|
||||
pub amount: ::std::option::Option<u32>,
|
||||
// @@protoc_insertion_point(field:hw.trezor.messages.helloworld.HelloWorldRequest.show_display)
|
||||
pub show_display: ::std::option::Option<bool>,
|
||||
// special fields
|
||||
// @@protoc_insertion_point(special_field:hw.trezor.messages.helloworld.HelloWorldRequest.special_fields)
|
||||
pub special_fields: ::protobuf::SpecialFields,
|
||||
}
|
||||
|
||||
impl<'a> ::std::default::Default for &'a HelloWorldRequest {
|
||||
fn default() -> &'a HelloWorldRequest {
|
||||
<HelloWorldRequest as ::protobuf::Message>::default_instance()
|
||||
}
|
||||
}
|
||||
|
||||
impl HelloWorldRequest {
|
||||
pub fn new() -> HelloWorldRequest {
|
||||
::std::default::Default::default()
|
||||
}
|
||||
|
||||
// required string name = 1;
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
match self.name.as_ref() {
|
||||
Some(v) => v,
|
||||
None => "",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear_name(&mut self) {
|
||||
self.name = ::std::option::Option::None;
|
||||
}
|
||||
|
||||
pub fn has_name(&self) -> bool {
|
||||
self.name.is_some()
|
||||
}
|
||||
|
||||
// Param is passed by value, moved
|
||||
pub fn set_name(&mut self, v: ::std::string::String) {
|
||||
self.name = ::std::option::Option::Some(v);
|
||||
}
|
||||
|
||||
// Mutable pointer to the field.
|
||||
// If field is not initialized, it is initialized with default value first.
|
||||
pub fn mut_name(&mut self) -> &mut ::std::string::String {
|
||||
if self.name.is_none() {
|
||||
self.name = ::std::option::Option::Some(::std::string::String::new());
|
||||
}
|
||||
self.name.as_mut().unwrap()
|
||||
}
|
||||
|
||||
// Take field
|
||||
pub fn take_name(&mut self) -> ::std::string::String {
|
||||
self.name.take().unwrap_or_else(|| ::std::string::String::new())
|
||||
}
|
||||
|
||||
// optional uint32 amount = 2;
|
||||
|
||||
pub fn amount(&self) -> u32 {
|
||||
self.amount.unwrap_or(1u32)
|
||||
}
|
||||
|
||||
pub fn clear_amount(&mut self) {
|
||||
self.amount = ::std::option::Option::None;
|
||||
}
|
||||
|
||||
pub fn has_amount(&self) -> bool {
|
||||
self.amount.is_some()
|
||||
}
|
||||
|
||||
// Param is passed by value, moved
|
||||
pub fn set_amount(&mut self, v: u32) {
|
||||
self.amount = ::std::option::Option::Some(v);
|
||||
}
|
||||
|
||||
// optional bool show_display = 3;
|
||||
|
||||
pub fn show_display(&self) -> bool {
|
||||
self.show_display.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn clear_show_display(&mut self) {
|
||||
self.show_display = ::std::option::Option::None;
|
||||
}
|
||||
|
||||
pub fn has_show_display(&self) -> bool {
|
||||
self.show_display.is_some()
|
||||
}
|
||||
|
||||
// Param is passed by value, moved
|
||||
pub fn set_show_display(&mut self, v: bool) {
|
||||
self.show_display = ::std::option::Option::Some(v);
|
||||
}
|
||||
|
||||
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
|
||||
let mut fields = ::std::vec::Vec::with_capacity(3);
|
||||
let mut oneofs = ::std::vec::Vec::with_capacity(0);
|
||||
fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>(
|
||||
"name",
|
||||
|m: &HelloWorldRequest| { &m.name },
|
||||
|m: &mut HelloWorldRequest| { &mut m.name },
|
||||
));
|
||||
fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>(
|
||||
"amount",
|
||||
|m: &HelloWorldRequest| { &m.amount },
|
||||
|m: &mut HelloWorldRequest| { &mut m.amount },
|
||||
));
|
||||
fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>(
|
||||
"show_display",
|
||||
|m: &HelloWorldRequest| { &m.show_display },
|
||||
|m: &mut HelloWorldRequest| { &mut m.show_display },
|
||||
));
|
||||
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<HelloWorldRequest>(
|
||||
"HelloWorldRequest",
|
||||
fields,
|
||||
oneofs,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::Message for HelloWorldRequest {
|
||||
const NAME: &'static str = "HelloWorldRequest";
|
||||
|
||||
fn is_initialized(&self) -> bool {
|
||||
if self.name.is_none() {
|
||||
return false;
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
|
||||
while let Some(tag) = is.read_raw_tag_or_eof()? {
|
||||
match tag {
|
||||
10 => {
|
||||
self.name = ::std::option::Option::Some(is.read_string()?);
|
||||
},
|
||||
16 => {
|
||||
self.amount = ::std::option::Option::Some(is.read_uint32()?);
|
||||
},
|
||||
24 => {
|
||||
self.show_display = ::std::option::Option::Some(is.read_bool()?);
|
||||
},
|
||||
tag => {
|
||||
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
|
||||
},
|
||||
};
|
||||
}
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
|
||||
// Compute sizes of nested messages
|
||||
#[allow(unused_variables)]
|
||||
fn compute_size(&self) -> u64 {
|
||||
let mut my_size = 0;
|
||||
if let Some(v) = self.name.as_ref() {
|
||||
my_size += ::protobuf::rt::string_size(1, &v);
|
||||
}
|
||||
if let Some(v) = self.amount {
|
||||
my_size += ::protobuf::rt::uint32_size(2, v);
|
||||
}
|
||||
if let Some(v) = self.show_display {
|
||||
my_size += 1 + 1;
|
||||
}
|
||||
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
|
||||
self.special_fields.cached_size().set(my_size as u32);
|
||||
my_size
|
||||
}
|
||||
|
||||
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
|
||||
if let Some(v) = self.name.as_ref() {
|
||||
os.write_string(1, v)?;
|
||||
}
|
||||
if let Some(v) = self.amount {
|
||||
os.write_uint32(2, v)?;
|
||||
}
|
||||
if let Some(v) = self.show_display {
|
||||
os.write_bool(3, v)?;
|
||||
}
|
||||
os.write_unknown_fields(self.special_fields.unknown_fields())?;
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
|
||||
fn special_fields(&self) -> &::protobuf::SpecialFields {
|
||||
&self.special_fields
|
||||
}
|
||||
|
||||
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
|
||||
&mut self.special_fields
|
||||
}
|
||||
|
||||
fn new() -> HelloWorldRequest {
|
||||
HelloWorldRequest::new()
|
||||
}
|
||||
|
||||
fn clear(&mut self) {
|
||||
self.name = ::std::option::Option::None;
|
||||
self.amount = ::std::option::Option::None;
|
||||
self.show_display = ::std::option::Option::None;
|
||||
self.special_fields.clear();
|
||||
}
|
||||
|
||||
fn default_instance() -> &'static HelloWorldRequest {
|
||||
static instance: HelloWorldRequest = HelloWorldRequest {
|
||||
name: ::std::option::Option::None,
|
||||
amount: ::std::option::Option::None,
|
||||
show_display: ::std::option::Option::None,
|
||||
special_fields: ::protobuf::SpecialFields::new(),
|
||||
};
|
||||
&instance
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::MessageFull for HelloWorldRequest {
|
||||
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
|
||||
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
|
||||
descriptor.get(|| file_descriptor().message_by_package_relative_name("HelloWorldRequest").unwrap()).clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Display for HelloWorldRequest {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||
::protobuf::text_format::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::reflect::ProtobufValue for HelloWorldRequest {
|
||||
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(message:hw.trezor.messages.helloworld.HelloWorldResponse)
|
||||
#[derive(PartialEq,Clone,Default,Debug)]
|
||||
pub struct HelloWorldResponse {
|
||||
// message fields
|
||||
// @@protoc_insertion_point(field:hw.trezor.messages.helloworld.HelloWorldResponse.text)
|
||||
pub text: ::std::option::Option<::std::string::String>,
|
||||
// special fields
|
||||
// @@protoc_insertion_point(special_field:hw.trezor.messages.helloworld.HelloWorldResponse.special_fields)
|
||||
pub special_fields: ::protobuf::SpecialFields,
|
||||
}
|
||||
|
||||
impl<'a> ::std::default::Default for &'a HelloWorldResponse {
|
||||
fn default() -> &'a HelloWorldResponse {
|
||||
<HelloWorldResponse as ::protobuf::Message>::default_instance()
|
||||
}
|
||||
}
|
||||
|
||||
impl HelloWorldResponse {
|
||||
pub fn new() -> HelloWorldResponse {
|
||||
::std::default::Default::default()
|
||||
}
|
||||
|
||||
// required string text = 1;
|
||||
|
||||
pub fn text(&self) -> &str {
|
||||
match self.text.as_ref() {
|
||||
Some(v) => v,
|
||||
None => "",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear_text(&mut self) {
|
||||
self.text = ::std::option::Option::None;
|
||||
}
|
||||
|
||||
pub fn has_text(&self) -> bool {
|
||||
self.text.is_some()
|
||||
}
|
||||
|
||||
// Param is passed by value, moved
|
||||
pub fn set_text(&mut self, v: ::std::string::String) {
|
||||
self.text = ::std::option::Option::Some(v);
|
||||
}
|
||||
|
||||
// Mutable pointer to the field.
|
||||
// If field is not initialized, it is initialized with default value first.
|
||||
pub fn mut_text(&mut self) -> &mut ::std::string::String {
|
||||
if self.text.is_none() {
|
||||
self.text = ::std::option::Option::Some(::std::string::String::new());
|
||||
}
|
||||
self.text.as_mut().unwrap()
|
||||
}
|
||||
|
||||
// Take field
|
||||
pub fn take_text(&mut self) -> ::std::string::String {
|
||||
self.text.take().unwrap_or_else(|| ::std::string::String::new())
|
||||
}
|
||||
|
||||
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
|
||||
let mut fields = ::std::vec::Vec::with_capacity(1);
|
||||
let mut oneofs = ::std::vec::Vec::with_capacity(0);
|
||||
fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>(
|
||||
"text",
|
||||
|m: &HelloWorldResponse| { &m.text },
|
||||
|m: &mut HelloWorldResponse| { &mut m.text },
|
||||
));
|
||||
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<HelloWorldResponse>(
|
||||
"HelloWorldResponse",
|
||||
fields,
|
||||
oneofs,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::Message for HelloWorldResponse {
|
||||
const NAME: &'static str = "HelloWorldResponse";
|
||||
|
||||
fn is_initialized(&self) -> bool {
|
||||
if self.text.is_none() {
|
||||
return false;
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
|
||||
while let Some(tag) = is.read_raw_tag_or_eof()? {
|
||||
match tag {
|
||||
10 => {
|
||||
self.text = ::std::option::Option::Some(is.read_string()?);
|
||||
},
|
||||
tag => {
|
||||
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
|
||||
},
|
||||
};
|
||||
}
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
|
||||
// Compute sizes of nested messages
|
||||
#[allow(unused_variables)]
|
||||
fn compute_size(&self) -> u64 {
|
||||
let mut my_size = 0;
|
||||
if let Some(v) = self.text.as_ref() {
|
||||
my_size += ::protobuf::rt::string_size(1, &v);
|
||||
}
|
||||
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
|
||||
self.special_fields.cached_size().set(my_size as u32);
|
||||
my_size
|
||||
}
|
||||
|
||||
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
|
||||
if let Some(v) = self.text.as_ref() {
|
||||
os.write_string(1, v)?;
|
||||
}
|
||||
os.write_unknown_fields(self.special_fields.unknown_fields())?;
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
|
||||
fn special_fields(&self) -> &::protobuf::SpecialFields {
|
||||
&self.special_fields
|
||||
}
|
||||
|
||||
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
|
||||
&mut self.special_fields
|
||||
}
|
||||
|
||||
fn new() -> HelloWorldResponse {
|
||||
HelloWorldResponse::new()
|
||||
}
|
||||
|
||||
fn clear(&mut self) {
|
||||
self.text = ::std::option::Option::None;
|
||||
self.special_fields.clear();
|
||||
}
|
||||
|
||||
fn default_instance() -> &'static HelloWorldResponse {
|
||||
static instance: HelloWorldResponse = HelloWorldResponse {
|
||||
text: ::std::option::Option::None,
|
||||
special_fields: ::protobuf::SpecialFields::new(),
|
||||
};
|
||||
&instance
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::MessageFull for HelloWorldResponse {
|
||||
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
|
||||
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
|
||||
descriptor.get(|| file_descriptor().message_by_package_relative_name("HelloWorldResponse").unwrap()).clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Display for HelloWorldResponse {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||
::protobuf::text_format::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::reflect::ProtobufValue for HelloWorldResponse {
|
||||
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
|
||||
}
|
||||
|
||||
static file_descriptor_proto_data: &'static [u8] = b"\
|
||||
\n\x14messages-hello.proto\x12\x1dhw.trezor.messages.helloworld\x1a\x0em\
|
||||
essages.proto\"e\n\x11HelloWorldRequest\x12\x12\n\x04name\x18\x01\x20\
|
||||
\x02(\tR\x04name\x12\x19\n\x06amount\x18\x02\x20\x01(\r:\x011R\x06amount\
|
||||
\x12!\n\x0cshow_display\x18\x03\x20\x01(\x08R\x0bshowDisplay\"(\n\x12Hel\
|
||||
loWorldResponse\x12\x12\n\x04text\x18\x01\x20\x02(\tR\x04textB>\n#com.sa\
|
||||
toshilabs.trezor.lib.protobufB\x17TrezorMessageHelloWorld\
|
||||
";
|
||||
|
||||
/// `FileDescriptorProto` object which was a source for this generated file
|
||||
fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
|
||||
static file_descriptor_proto_lazy: ::protobuf::rt::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::Lazy::new();
|
||||
file_descriptor_proto_lazy.get(|| {
|
||||
::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()
|
||||
})
|
||||
}
|
||||
|
||||
/// `FileDescriptor` object which allows dynamic access to files
|
||||
pub fn file_descriptor() -> &'static ::protobuf::reflect::FileDescriptor {
|
||||
static generated_file_descriptor_lazy: ::protobuf::rt::Lazy<::protobuf::reflect::GeneratedFileDescriptor> = ::protobuf::rt::Lazy::new();
|
||||
static file_descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::FileDescriptor> = ::protobuf::rt::Lazy::new();
|
||||
file_descriptor.get(|| {
|
||||
let generated_file_descriptor = generated_file_descriptor_lazy.get(|| {
|
||||
let mut deps = ::std::vec::Vec::with_capacity(1);
|
||||
deps.push(super::messages::file_descriptor().clone());
|
||||
let mut messages = ::std::vec::Vec::with_capacity(2);
|
||||
messages.push(HelloWorldRequest::generated_message_descriptor_data());
|
||||
messages.push(HelloWorldResponse::generated_message_descriptor_data());
|
||||
let mut enums = ::std::vec::Vec::with_capacity(0);
|
||||
::protobuf::reflect::GeneratedFileDescriptor::new_generated(
|
||||
file_descriptor_proto(),
|
||||
deps,
|
||||
messages,
|
||||
enums,
|
||||
)
|
||||
});
|
||||
::protobuf::reflect::FileDescriptor::new_generated_2(generated_file_descriptor)
|
||||
})
|
||||
}
|
43
tests/device_tests/misc/test_hello_world.py
Normal file
43
tests/device_tests/misc/test_hello_world.py
Normal file
@ -0,0 +1,43 @@
|
||||
# This file is part of the Trezor project.
|
||||
#
|
||||
# Copyright (C) 2012-2019 SatoshiLabs and contributors
|
||||
#
|
||||
# This library is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License version 3
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# This library 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 Lesser General Public License for more details.
|
||||
#
|
||||
# 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>.
|
||||
|
||||
from typing import Optional
|
||||
|
||||
import pytest
|
||||
|
||||
from trezorlib import hello_world
|
||||
from trezorlib.debuglink import TrezorClientDebugLink as Client
|
||||
|
||||
VECTORS = ( # name, amount, show_display
|
||||
("George", 2, True),
|
||||
("John", 3, False),
|
||||
("Hannah", None, False),
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.skip_t1
|
||||
@pytest.mark.parametrize("name, amount, show_display", VECTORS)
|
||||
def test_hello_world(
|
||||
client: Client, name: str, amount: Optional[int], show_display: bool
|
||||
):
|
||||
with client:
|
||||
greeting_text = hello_world.say_hello(
|
||||
client, name=name, amount=amount, show_display=show_display
|
||||
)
|
||||
greeting_lines = greeting_text.strip().splitlines()
|
||||
|
||||
assert len(greeting_lines) == amount or 1
|
||||
assert all(name in line for line in greeting_lines)
|
@ -3139,6 +3139,9 @@
|
||||
"TT_misc-test_cosi.py::test_slip26_paths[\\x00-3]": "2cbaa2088776f1c7c735aa1ef767d33f8ad8ebdb592b6d9814dd1bbabd6da9b5",
|
||||
"TT_misc-test_cosi.py::test_slip26_paths[\\xfe\\xfe\\xfe\\xfe-0]": "58a16c31957f7d540da34a30f54631e607eca1af6efb27a0b3877e49f77a9d56",
|
||||
"TT_misc-test_cosi.py::test_slip26_paths[dog-0]": "7cee26436a0025a56eb1f67e432e4e707857714c1bbf5f61df60cc20f54c84ab",
|
||||
"TT_misc-test_hello_world.py::test_hello_world[George-2-True]": "061e096ed3b47be216f4c7eb01999b4ec8bace1e3608a0de1fc128747b28a060",
|
||||
"TT_misc-test_hello_world.py::test_hello_world[Hannah-None-False]": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3",
|
||||
"TT_misc-test_hello_world.py::test_hello_world[John-3-False]": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3",
|
||||
"TT_misc-test_msg_cipherkeyvalue.py::test_decrypt": "b34ae9ac7b3ea7467afe774bf615ca1e1eab26c64fe5d25178071bf15e8d6518",
|
||||
"TT_misc-test_msg_cipherkeyvalue.py::test_decrypt_badlen": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3",
|
||||
"TT_misc-test_msg_cipherkeyvalue.py::test_encrypt": "648e45403ce412314e9d91625ace8ffdee52ff37ac99b13f4e86d018a024515d",
|
||||
|
Loading…
Reference in New Issue
Block a user