diff --git a/common/protob/messages-management.proto b/common/protob/messages-management.proto index c9a47a5b0..e2c084175 100644 --- a/common/protob/messages-management.proto +++ b/common/protob/messages-management.proto @@ -111,6 +111,7 @@ message Features { Capability_ShamirGroups = 16 [(bitcoin_only) = true]; Capability_PassphraseEntry = 17 [(bitcoin_only) = true]; // the device is capable of passphrase entry directly on the device Capability_Solana = 18; + Capability_Translations = 19 [(bitcoin_only) = true]; } optional BackupType backup_type = 31; // type of device backup (BIP-39 / SLIP-39 basic / SLIP-39 advanced) optional bool sd_card_present = 32; // is SD card present diff --git a/core/src/apps/base.py b/core/src/apps/base.py index 27d0c16b7..4ba716ce4 100644 --- a/core/src/apps/base.py +++ b/core/src/apps/base.py @@ -103,6 +103,7 @@ def get_features() -> Features: Capability.Shamir, Capability.ShamirGroups, Capability.PassphraseEntry, + Capability.Translations, ] else: f.capabilities = [ @@ -121,6 +122,7 @@ def get_features() -> Features: Capability.ShamirGroups, Capability.PassphraseEntry, Capability.Solana, + Capability.Translations, ] # We do not support some currencies on T2B1 diff --git a/core/src/trezor/enums/Capability.py b/core/src/trezor/enums/Capability.py index 9ebc7dc05..5cc5dbddd 100644 --- a/core/src/trezor/enums/Capability.py +++ b/core/src/trezor/enums/Capability.py @@ -9,6 +9,7 @@ Crypto = 5 Shamir = 15 ShamirGroups = 16 PassphraseEntry = 17 +Translations = 19 if not utils.BITCOIN_ONLY: Bitcoin_like = 2 Binance = 3 diff --git a/core/src/trezor/enums/__init__.py b/core/src/trezor/enums/__init__.py index cce49799f..3335f1b27 100644 --- a/core/src/trezor/enums/__init__.py +++ b/core/src/trezor/enums/__init__.py @@ -446,6 +446,7 @@ if TYPE_CHECKING: ShamirGroups = 16 PassphraseEntry = 17 Solana = 18 + Translations = 19 class SdProtectOperationType(IntEnum): DISABLE = 0 diff --git a/python/src/trezorlib/messages.py b/python/src/trezorlib/messages.py index f53d426df..a8ae02096 100644 --- a/python/src/trezorlib/messages.py +++ b/python/src/trezorlib/messages.py @@ -477,6 +477,7 @@ class Capability(IntEnum): ShamirGroups = 16 PassphraseEntry = 17 Solana = 18 + Translations = 19 class SdProtectOperationType(IntEnum): diff --git a/rust/trezor-client/src/protos/generated/messages_management.rs b/rust/trezor-client/src/protos/generated/messages_management.rs index 12bf9495f..c163b5ea7 100644 --- a/rust/trezor-client/src/protos/generated/messages_management.rs +++ b/rust/trezor-client/src/protos/generated/messages_management.rs @@ -2453,6 +2453,8 @@ pub mod features { Capability_PassphraseEntry = 17, // @@protoc_insertion_point(enum_value:hw.trezor.messages.management.Features.Capability.Capability_Solana) Capability_Solana = 18, + // @@protoc_insertion_point(enum_value:hw.trezor.messages.management.Features.Capability.Capability_Translations) + Capability_Translations = 19, } impl ::protobuf::Enum for Capability { @@ -2482,6 +2484,7 @@ pub mod features { 16 => ::std::option::Option::Some(Capability::Capability_ShamirGroups), 17 => ::std::option::Option::Some(Capability::Capability_PassphraseEntry), 18 => ::std::option::Option::Some(Capability::Capability_Solana), + 19 => ::std::option::Option::Some(Capability::Capability_Translations), _ => ::std::option::Option::None } } @@ -2506,6 +2509,7 @@ pub mod features { "Capability_ShamirGroups" => ::std::option::Option::Some(Capability::Capability_ShamirGroups), "Capability_PassphraseEntry" => ::std::option::Option::Some(Capability::Capability_PassphraseEntry), "Capability_Solana" => ::std::option::Option::Some(Capability::Capability_Solana), + "Capability_Translations" => ::std::option::Option::Some(Capability::Capability_Translations), _ => ::std::option::Option::None } } @@ -2529,6 +2533,7 @@ pub mod features { Capability::Capability_ShamirGroups, Capability::Capability_PassphraseEntry, Capability::Capability_Solana, + Capability::Capability_Translations, ]; } @@ -2558,6 +2563,7 @@ pub mod features { Capability::Capability_ShamirGroups => 15, Capability::Capability_PassphraseEntry => 16, Capability::Capability_Solana => 17, + Capability::Capability_Translations => 18, }; Self::enum_descriptor().value_by_index(index) } @@ -10305,7 +10311,7 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \x0emessages.proto\"\x80\x01\n\nInitialize\x12\x1d\n\nsession_id\x18\x01\ \x20\x01(\x0cR\tsessionId\x12,\n\x10_skip_passphrase\x18\x02\x20\x01(\ \x08R\x0eSkipPassphraseB\x02\x18\x01\x12%\n\x0ederive_cardano\x18\x03\ - \x20\x01(\x08R\rderiveCardano\"\r\n\x0bGetFeatures\"\xb0\x13\n\x08Featur\ + \x20\x01(\x08R\rderiveCardano\"\r\n\x0bGetFeatures\"\xd3\x13\n\x08Featur\ es\x12\x16\n\x06vendor\x18\x01\x20\x01(\tR\x06vendor\x12#\n\rmajor_versi\ on\x18\x02\x20\x02(\rR\x0cmajorVersion\x12#\n\rminor_version\x18\x03\x20\ \x02(\rR\x0cminorVersion\x12#\n\rpatch_version\x18\x04\x20\x02(\rR\x0cpa\ @@ -10349,7 +10355,7 @@ static file_descriptor_proto_data: &'static [u8] = b"\ n_width\x18/\x20\x01(\rR\x0fhomescreenWidth\x12+\n\x11homescreen_height\ \x180\x20\x01(\rR\x10homescreenHeight\x12+\n\x11bootloader_locked\x181\ \x20\x01(\x08R\x10bootloaderLocked\x12>\n\x18language_version_matches\ - \x182\x20\x01(\x08:\x04trueR\x16languageVersionMatches\"\xe1\x03\n\nCapa\ + \x182\x20\x01(\x08:\x04trueR\x16languageVersionMatches\"\x84\x04\n\nCapa\ bility\x12\x1c\n\x12Capability_Bitcoin\x10\x01\x1a\x04\x80\xa6\x1d\x01\ \x12\x1b\n\x17Capability_Bitcoin_like\x10\x02\x12\x16\n\x12Capability_Bi\ nance\x10\x03\x12\x16\n\x12Capability_Cardano\x10\x04\x12\x1b\n\x11Capab\ @@ -10361,18 +10367,19 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \x10\r\x12\x12\n\x0eCapability_U2F\x10\x0e\x12\x1b\n\x11Capability_Shami\ r\x10\x0f\x1a\x04\x80\xa6\x1d\x01\x12!\n\x17Capability_ShamirGroups\x10\ \x10\x1a\x04\x80\xa6\x1d\x01\x12$\n\x1aCapability_PassphraseEntry\x10\ - \x11\x1a\x04\x80\xa6\x1d\x01\x12\x15\n\x11Capability_Solana\x10\x12\x1a\ - \x04\xc8\xf3\x18\x01\"\x0c\n\nLockDevice\"&\n\x07SetBusy\x12\x1b\n\texpi\ - ry_ms\x18\x01\x20\x01(\rR\x08expiryMs\"\x0c\n\nEndSession\"\x9b\x04\n\rA\ - pplySettings\x12\x1e\n\x08language\x18\x01\x20\x01(\tR\x08languageB\x02\ - \x18\x01\x12\x14\n\x05label\x18\x02\x20\x01(\tR\x05label\x12%\n\x0euse_p\ - assphrase\x18\x03\x20\x01(\x08R\rusePassphrase\x12\x1e\n\nhomescreen\x18\ - \x04\x20\x01(\x0cR\nhomescreen\x120\n\x12_passphrase_source\x18\x05\x20\ - \x01(\rR\x10PassphraseSourceB\x02\x18\x01\x12+\n\x12auto_lock_delay_ms\ - \x18\x06\x20\x01(\rR\x0fautoLockDelayMs\x12)\n\x10display_rotation\x18\ - \x07\x20\x01(\rR\x0fdisplayRotation\x12=\n\x1bpassphrase_always_on_devic\ - e\x18\x08\x20\x01(\x08R\x18passphraseAlwaysOnDevice\x12T\n\rsafety_check\ - s\x18\t\x20\x01(\x0e2/.hw.trezor.messages.management.SafetyCheckLevelR\ + \x11\x1a\x04\x80\xa6\x1d\x01\x12\x15\n\x11Capability_Solana\x10\x12\x12!\ + \n\x17Capability_Translations\x10\x13\x1a\x04\x80\xa6\x1d\x01\x1a\x04\ + \xc8\xf3\x18\x01\"\x0c\n\nLockDevice\"&\n\x07SetBusy\x12\x1b\n\texpiry_m\ + s\x18\x01\x20\x01(\rR\x08expiryMs\"\x0c\n\nEndSession\"\x9b\x04\n\rApply\ + Settings\x12\x1e\n\x08language\x18\x01\x20\x01(\tR\x08languageB\x02\x18\ + \x01\x12\x14\n\x05label\x18\x02\x20\x01(\tR\x05label\x12%\n\x0euse_passp\ + hrase\x18\x03\x20\x01(\x08R\rusePassphrase\x12\x1e\n\nhomescreen\x18\x04\ + \x20\x01(\x0cR\nhomescreen\x120\n\x12_passphrase_source\x18\x05\x20\x01(\ + \rR\x10PassphraseSourceB\x02\x18\x01\x12+\n\x12auto_lock_delay_ms\x18\ + \x06\x20\x01(\rR\x0fautoLockDelayMs\x12)\n\x10display_rotation\x18\x07\ + \x20\x01(\rR\x0fdisplayRotation\x12=\n\x1bpassphrase_always_on_device\ + \x18\x08\x20\x01(\x08R\x18passphraseAlwaysOnDevice\x12T\n\rsafety_checks\ + \x18\t\x20\x01(\x0e2/.hw.trezor.messages.management.SafetyCheckLevelR\ \x0csafetyChecks\x123\n\x15experimental_features\x18\n\x20\x01(\x08R\x14\ experimentalFeatures\x129\n\x19hide_passphrase_from_host\x18\x0b\x20\x01\ (\x08R\x16hidePassphraseFromHost\"T\n\x0eChangeLanguage\x12\x1f\n\x0bdat\ diff --git a/tests/device_tests/test_basic.py b/tests/device_tests/test_basic.py index 356759797..c2d1202eb 100644 --- a/tests/device_tests/test_basic.py +++ b/tests/device_tests/test_basic.py @@ -14,7 +14,7 @@ # You should have received a copy of the License along with this library. # If not, see . -from trezorlib import device, messages +from trezorlib import device, messages, models from trezorlib.debuglink import TrezorClientDebugLink as Client @@ -26,6 +26,12 @@ def test_features(client: Client): assert f0 == f1 +def test_capabilities(client: Client): + assert (messages.Capability.Translations in client.features.capabilities) == ( + client.model is not models.T1B1 + ) + + def test_ping(client: Client): ping = client.call(messages.Ping(message="ahoj!")) assert ping == messages.Success(message="ahoj!") diff --git a/tests/ui_tests/fixtures.json b/tests/ui_tests/fixtures.json index 80636830c..8f156e5ec 100644 --- a/tests/ui_tests/fixtures.json +++ b/tests/ui_tests/fixtures.json @@ -640,6 +640,7 @@ "T1_en_test_autolock.py::test_autolock_default_value": "cde0dd7c453463cbfbb6bb35289fca350efd43511f2701b634c0fbb81f7d9dec", "T1_en_test_autolock.py::test_autolock_ignores_getaddress": "4f24424b5a55618ecc6d3e57a96071a222892dcef874428c3914ab86eca98c77", "T1_en_test_autolock.py::test_autolock_ignores_initialize": "4f24424b5a55618ecc6d3e57a96071a222892dcef874428c3914ab86eca98c77", +"T1_en_test_basic.py::test_capabilities": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "T1_en_test_basic.py::test_device_id_different": "aac15a6d12d21966c77572aeebd56ebc2a47ecba3a508f5a421af2a5da2919e7", "T1_en_test_basic.py::test_device_id_same": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "T1_en_test_basic.py::test_features": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", @@ -2150,6 +2151,7 @@ "TR_cs_test_autolock.py::test_autolock_default_value": "2cf032b5e7ea2994acb9e0121c1e10dff929dc572a5a7528cbf29b49110a5ef2", "TR_cs_test_autolock.py::test_autolock_ignores_getaddress": "f41f9fc64537c29f6f530ced022d28fe9f713ae31babe974d9b0795edd5adf7e", "TR_cs_test_autolock.py::test_autolock_ignores_initialize": "f41f9fc64537c29f6f530ced022d28fe9f713ae31babe974d9b0795edd5adf7e", +"TR_cs_test_basic.py::test_capabilities": "cb2b7df43c09354e4c03fa6f0286109ac5051752699e8ca5c230cdc0445af2ed", "TR_cs_test_basic.py::test_device_id_different": "bec90ea7be13f6437adf5c70496bb66def054ef2919d7b9ec3a131e00acfea6f", "TR_cs_test_basic.py::test_device_id_same": "cb2b7df43c09354e4c03fa6f0286109ac5051752699e8ca5c230cdc0445af2ed", "TR_cs_test_basic.py::test_features": "cb2b7df43c09354e4c03fa6f0286109ac5051752699e8ca5c230cdc0445af2ed", @@ -3494,6 +3496,7 @@ "TR_de_test_autolock.py::test_autolock_default_value": "d3866c3a7a71d5141f2bb3dc5cd4391e374c68a3731396fdd0424e2f3e5203c9", "TR_de_test_autolock.py::test_autolock_ignores_getaddress": "51615badba3006364c3dabd47c492854d554feb1d3b6e181f974c1ac8bcefc1f", "TR_de_test_autolock.py::test_autolock_ignores_initialize": "51615badba3006364c3dabd47c492854d554feb1d3b6e181f974c1ac8bcefc1f", +"TR_de_test_basic.py::test_capabilities": "9bdb526d0b64a91e862ec4ba7ced36adf20382a193c8f0c5788a70564aeac23a", "TR_de_test_basic.py::test_device_id_different": "fa2c0c07f4ec4380d9539b8553d342c33d856fd6de71125519a32f11534a3ec3", "TR_de_test_basic.py::test_device_id_same": "9bdb526d0b64a91e862ec4ba7ced36adf20382a193c8f0c5788a70564aeac23a", "TR_de_test_basic.py::test_features": "9bdb526d0b64a91e862ec4ba7ced36adf20382a193c8f0c5788a70564aeac23a", @@ -4856,6 +4859,7 @@ "TR_en_test_autolock.py::test_autolock_default_value": "d810436f4404563b1a3dda410cbda2f42969ef6bc746b85fefc6fce2fe835369", "TR_en_test_autolock.py::test_autolock_ignores_getaddress": "c5e41fe24ab50d93b40d5ce91a2b4232cef22046ea0d6c0e01603b01a333ada6", "TR_en_test_autolock.py::test_autolock_ignores_initialize": "c5e41fe24ab50d93b40d5ce91a2b4232cef22046ea0d6c0e01603b01a333ada6", +"TR_en_test_basic.py::test_capabilities": "8c801bd0142e5c1ad4aad50b34c7debb1b8f17a2e0a87eb7f95531b9fd15e095", "TR_en_test_basic.py::test_device_id_different": "0abb37c5dd2cc89e22f3952cfec9191413873c9c291df8c8a43a7c89f23b5fd5", "TR_en_test_basic.py::test_device_id_same": "8c801bd0142e5c1ad4aad50b34c7debb1b8f17a2e0a87eb7f95531b9fd15e095", "TR_en_test_basic.py::test_features": "8c801bd0142e5c1ad4aad50b34c7debb1b8f17a2e0a87eb7f95531b9fd15e095", @@ -6200,6 +6204,7 @@ "TR_es_test_autolock.py::test_autolock_default_value": "927810786eb074d1cc988911dbc29ae74d6f00aa29d1cd599bc5f17a16069919", "TR_es_test_autolock.py::test_autolock_ignores_getaddress": "301168c91c5445413aea30cde335975b85e9e716adc04d9a02700d61b777a72b", "TR_es_test_autolock.py::test_autolock_ignores_initialize": "301168c91c5445413aea30cde335975b85e9e716adc04d9a02700d61b777a72b", +"TR_es_test_basic.py::test_capabilities": "5e88affdb4b3898af738bfabb224b94e674c0d5b8bd6ea4f73a601c972f5858c", "TR_es_test_basic.py::test_device_id_different": "9f7fac6440897a401ba3f318edb6278403e5c80f69e7d493553f0eb9e6a70382", "TR_es_test_basic.py::test_device_id_same": "5e88affdb4b3898af738bfabb224b94e674c0d5b8bd6ea4f73a601c972f5858c", "TR_es_test_basic.py::test_features": "5e88affdb4b3898af738bfabb224b94e674c0d5b8bd6ea4f73a601c972f5858c", @@ -7544,6 +7549,7 @@ "TR_fr_test_autolock.py::test_autolock_default_value": "3643f7de60feef3c64f48f2eab351b884581b011753fbab6a195e22278ce40ef", "TR_fr_test_autolock.py::test_autolock_ignores_getaddress": "5ff13140edeb1beb2e18aab3e9615eb974608600688c4197583cdfddd3bd10fc", "TR_fr_test_autolock.py::test_autolock_ignores_initialize": "5ff13140edeb1beb2e18aab3e9615eb974608600688c4197583cdfddd3bd10fc", +"TR_fr_test_basic.py::test_capabilities": "3bbca7f9b0cc44dd18b1fb71d34dec0542b8ac69e022cf4cd1f2792a41b4fb20", "TR_fr_test_basic.py::test_device_id_different": "13e6884d46c72f52d0b084923e11044e76bf287129f8e81530f6fbe66f9c428e", "TR_fr_test_basic.py::test_device_id_same": "3bbca7f9b0cc44dd18b1fb71d34dec0542b8ac69e022cf4cd1f2792a41b4fb20", "TR_fr_test_basic.py::test_features": "3bbca7f9b0cc44dd18b1fb71d34dec0542b8ac69e022cf4cd1f2792a41b4fb20", @@ -9195,6 +9201,7 @@ "TT_cs_test_autolock.py::test_autolock_default_value": "c0e766094ced5d92e93b13549efea2b4eeaaf1527288224c1a55b3e5b5b42c40", "TT_cs_test_autolock.py::test_autolock_ignores_getaddress": "3397142387fe4c8fedb16a5a4d37f34366417d8505b38ade99a2b13959af96a6", "TT_cs_test_autolock.py::test_autolock_ignores_initialize": "3397142387fe4c8fedb16a5a4d37f34366417d8505b38ade99a2b13959af96a6", +"TT_cs_test_basic.py::test_capabilities": "56f6f2887f3022efefed50e9c478040b38762e8a120586df0f1cea4941f5c34b", "TT_cs_test_basic.py::test_device_id_different": "797083da15c42b7da1b2f4b4e9c86384aaf495cfd2148ae7af4f7db92621e2f8", "TT_cs_test_basic.py::test_device_id_same": "56f6f2887f3022efefed50e9c478040b38762e8a120586df0f1cea4941f5c34b", "TT_cs_test_basic.py::test_features": "56f6f2887f3022efefed50e9c478040b38762e8a120586df0f1cea4941f5c34b", @@ -10619,6 +10626,7 @@ "TT_de_test_autolock.py::test_autolock_default_value": "990c021d0d76f73a9184369fd743ac16f0b6ddf3ce90af1aace16777ae23c52f", "TT_de_test_autolock.py::test_autolock_ignores_getaddress": "d9163d1565b2fa43ee0fabe50b92f9be131cd43b113f4f462aa8b05c90be091a", "TT_de_test_autolock.py::test_autolock_ignores_initialize": "d9163d1565b2fa43ee0fabe50b92f9be131cd43b113f4f462aa8b05c90be091a", +"TT_de_test_basic.py::test_capabilities": "4ed24353a7aa99e894d4ed3cb45be13f54a94577289f3919be62add4c6c36390", "TT_de_test_basic.py::test_device_id_different": "b17901702c0399a7ca6ed20ae39b8eb6bbae5d74a15d38c2868febaecdbad328", "TT_de_test_basic.py::test_device_id_same": "4ed24353a7aa99e894d4ed3cb45be13f54a94577289f3919be62add4c6c36390", "TT_de_test_basic.py::test_features": "4ed24353a7aa99e894d4ed3cb45be13f54a94577289f3919be62add4c6c36390", @@ -12061,6 +12069,7 @@ "TT_en_test_autolock.py::test_autolock_default_value": "26456e47387df96753a31089b42925fa24d29604564d9145a0a40e7eed03b04d", "TT_en_test_autolock.py::test_autolock_ignores_getaddress": "2d1ca9c45112dad7e5bbb908baa086b02547a3e710fab8eff79551e63e19b790", "TT_en_test_autolock.py::test_autolock_ignores_initialize": "2d1ca9c45112dad7e5bbb908baa086b02547a3e710fab8eff79551e63e19b790", +"TT_en_test_basic.py::test_capabilities": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3", "TT_en_test_basic.py::test_device_id_different": "a2311d35eab312a51948f62e75484cb352c7794764403812a33acc9bfc89ca73", "TT_en_test_basic.py::test_device_id_same": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3", "TT_en_test_basic.py::test_features": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3", @@ -13503,6 +13512,7 @@ "TT_es_test_autolock.py::test_autolock_default_value": "02be3ec680cda907c1d2bdb7568966bbfe51a2dd8e575cb61548941d77b9289e", "TT_es_test_autolock.py::test_autolock_ignores_getaddress": "6742759bce4335b47bbb6ab11763d58829bcd4f47810f16f48ab90d407c4ee27", "TT_es_test_autolock.py::test_autolock_ignores_initialize": "6742759bce4335b47bbb6ab11763d58829bcd4f47810f16f48ab90d407c4ee27", +"TT_es_test_basic.py::test_capabilities": "3d2d3c815bfd09c3235e3749e66769dc375f49f9cc92f13f4a7b7df38e6bcfab", "TT_es_test_basic.py::test_device_id_different": "6b89cf6b8e0af123d0f64761dc06bc97f14ed1a83a66473453ae8afa74bd9786", "TT_es_test_basic.py::test_device_id_same": "3d2d3c815bfd09c3235e3749e66769dc375f49f9cc92f13f4a7b7df38e6bcfab", "TT_es_test_basic.py::test_features": "3d2d3c815bfd09c3235e3749e66769dc375f49f9cc92f13f4a7b7df38e6bcfab", @@ -14927,6 +14937,7 @@ "TT_fr_test_autolock.py::test_autolock_default_value": "18fe4ca2286a608313430e59ac8c56daec9f096960c10a0bedecf427f9fa2e9c", "TT_fr_test_autolock.py::test_autolock_ignores_getaddress": "6355be29769b7ced748606e8cd9aab0ab9b651a5a24e39765e8a5da4c9767a1c", "TT_fr_test_autolock.py::test_autolock_ignores_initialize": "6355be29769b7ced748606e8cd9aab0ab9b651a5a24e39765e8a5da4c9767a1c", +"TT_fr_test_basic.py::test_capabilities": "5c03427cb7e315cb2f1e036c2edb2cc7c527ac80783c331fda0749bf306bcd94", "TT_fr_test_basic.py::test_device_id_different": "4319b6013ad542a90cf01faac389609f5967202eb6d846ca5aeac343cf03c934", "TT_fr_test_basic.py::test_device_id_same": "5c03427cb7e315cb2f1e036c2edb2cc7c527ac80783c331fda0749bf306bcd94", "TT_fr_test_basic.py::test_features": "5c03427cb7e315cb2f1e036c2edb2cc7c527ac80783c331fda0749bf306bcd94",