From 8ceefbf7eaa9b5a263211698a5bf8402f6af806c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Jas=CC=8Cko?= Date: Sun, 11 Feb 2024 15:57:16 +0100 Subject: [PATCH] fix(cardano): Return pubkey This ends up being useful for software wallets. --- common/protob/messages-cardano.proto | 5 +- .../tests/fixtures/cardano/sign_message.json | 34 +++-- core/src/apps/cardano/sign_message.py | 7 +- core/src/trezor/messages.py | 2 + python/src/trezorlib/messages.py | 3 + .../src/protos/generated/messages_cardano.rs | 116 +++++++++++++----- .../device_tests/cardano/test_sign_message.py | 1 + 7 files changed, 124 insertions(+), 44 deletions(-) diff --git a/common/protob/messages-cardano.proto b/common/protob/messages-cardano.proto index 87e691872..e7fd52d78 100644 --- a/common/protob/messages-cardano.proto +++ b/common/protob/messages-cardano.proto @@ -542,6 +542,7 @@ message CardanoMessageItemHostAck { * @end */ message CardanoSignMessageFinished { - required bytes signature = 1; - required bytes address = 2; + required bytes signature = 1; // signature for structure containing payload and protected headers + required bytes address = 2; // value of the address field in protected headers + required bytes pub_key = 3; // public key given by signing path } diff --git a/common/tests/fixtures/cardano/sign_message.json b/common/tests/fixtures/cardano/sign_message.json index f8f672758..dd8e92b73 100644 --- a/common/tests/fixtures/cardano/sign_message.json +++ b/common/tests/fixtures/cardano/sign_message.json @@ -14,7 +14,8 @@ }, "result": { "signature": "5ad6ba670e65353b2c1ad4053a1ed4a9348a73fe965ffa0afafa24bad06e3eb3e325d49029604c09bf665c3c43a750ec81a43b1f8b746b07e999b913b980d006", - "address": "d9553a4de9c7ad8532abdb1d0a7f425b8007d25c9f1edcf0b5f5c3ba" + "address": "d9553a4de9c7ad8532abdb1d0a7f425b8007d25c9f1edcf0b5f5c3ba", + "pub_key": "67e3d14e1e0db2a6ff68832994451f63d3e92a4ee85c3681d72634ccfe889f2c" } }, { @@ -34,7 +35,8 @@ }, "result": { "signature": "9efaff0b74c0beb2cadd727d8bafe13b31107235c5fc46c6c33e596e024d391c9fbe37072e43965add6ee0a4788562382031486b74fd59d636aa1ca3b1ddfe06", - "address": "0180f9e2c88e6c817008f3a812ed889b4a4da8e0bd103f86e7335422aa122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277" + "address": "0180f9e2c88e6c817008f3a812ed889b4a4da8e0bd103f86e7335422aa122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277", + "pub_key": "67e3d14e1e0db2a6ff68832994451f63d3e92a4ee85c3681d72634ccfe889f2c" } }, { @@ -47,10 +49,11 @@ }, "result": { "signature": "2c325e542fa78d76d916e50f50b85e770354a44e071f08fdb8ec5d0bcbf844cf70dcf5c87b7a51cd7f0269a59eec8d438c3c27eb42b971e7ccb7f864714c4b06", - "address": "d9553a4de9c7ad8532abdb1d0a7f425b8007d25c9f1edcf0b5f5c3ba" + "address": "d9553a4de9c7ad8532abdb1d0a7f425b8007d25c9f1edcf0b5f5c3ba", + "pub_key": "67e3d14e1e0db2a6ff68832994451f63d3e92a4ee85c3681d72634ccfe889f2c" } }, - { + { "description": "Sign short ASCII payload", "parameters": { "signing_path": "m/1852'/1815'/4'/0/0", @@ -60,10 +63,11 @@ }, "result": { "signature": "2201b8e7fa9ea919935e06ecc3e845433855066acaaf61cb8e624a2eb7139b73a9d126e7ee04548fff06ac933bd5419fc78c5aebee9b536cbee1481b52ec3e03", - "address": "d9553a4de9c7ad8532abdb1d0a7f425b8007d25c9f1edcf0b5f5c3ba" + "address": "d9553a4de9c7ad8532abdb1d0a7f425b8007d25c9f1edcf0b5f5c3ba", + "pub_key": "67e3d14e1e0db2a6ff68832994451f63d3e92a4ee85c3681d72634ccfe889f2c" } }, - { + { "description": "Sign short ASCII payload rendered as hex", "parameters": { "signing_path": "m/1852'/1815'/4'/0/0", @@ -73,7 +77,8 @@ }, "result": { "signature": "2201b8e7fa9ea919935e06ecc3e845433855066acaaf61cb8e624a2eb7139b73a9d126e7ee04548fff06ac933bd5419fc78c5aebee9b536cbee1481b52ec3e03", - "address": "d9553a4de9c7ad8532abdb1d0a7f425b8007d25c9f1edcf0b5f5c3ba" + "address": "d9553a4de9c7ad8532abdb1d0a7f425b8007d25c9f1edcf0b5f5c3ba", + "pub_key": "67e3d14e1e0db2a6ff68832994451f63d3e92a4ee85c3681d72634ccfe889f2c" } }, { @@ -86,7 +91,8 @@ }, "result": { "signature": "b09177a06cb2deba7ada89fec96fc4380e746f67c6b16a9ef9ae6b7cbbe941fdad8a8a573b809cd88db296b91b476c436033a29d86a63959e270047e47cd5d0d", - "address": "d9553a4de9c7ad8532abdb1d0a7f425b8007d25c9f1edcf0b5f5c3ba" + "address": "d9553a4de9c7ad8532abdb1d0a7f425b8007d25c9f1edcf0b5f5c3ba", + "pub_key": "67e3d14e1e0db2a6ff68832994451f63d3e92a4ee85c3681d72634ccfe889f2c" } }, { @@ -99,7 +105,8 @@ }, "result": { "signature": "a2503039a8ec620e05d9e4345339d61cd11480fbfcc75ea1a10789751a7c5f46ba06786eb1719da62db76c20313ad3445839b8117abac206cc4bd63ea623fc07", - "address": "d9553a4de9c7ad8532abdb1d0a7f425b8007d25c9f1edcf0b5f5c3ba" + "address": "d9553a4de9c7ad8532abdb1d0a7f425b8007d25c9f1edcf0b5f5c3ba", + "pub_key": "67e3d14e1e0db2a6ff68832994451f63d3e92a4ee85c3681d72634ccfe889f2c" } }, { @@ -112,7 +119,8 @@ }, "result": { "signature": "92331e75bb4c3208317ac422f2fc9d8b9b09d3f81cc487edaa7028d262553e5691532fb166a40e45eb2e4addd4280ff7e07bd4249e964d969e91555317b05f08", - "address": "d9553a4de9c7ad8532abdb1d0a7f425b8007d25c9f1edcf0b5f5c3ba" + "address": "d9553a4de9c7ad8532abdb1d0a7f425b8007d25c9f1edcf0b5f5c3ba", + "pub_key": "67e3d14e1e0db2a6ff68832994451f63d3e92a4ee85c3681d72634ccfe889f2c" } }, { @@ -127,7 +135,8 @@ }, "result": { "signature": "eb7e48bb2de912b24ea4e295cfbf338e95e2a2d9c5eb41d72ddd8ebf96ca6128696e91e65e20a755821781b8ea0b4aa7ffcfa6ab0c7da2c67ecaf33fcd596509", - "address": "d9553a4de9c7ad8532abdb1d0a7f425b8007d25c9f1edcf0b5f5c3ba" + "address": "d9553a4de9c7ad8532abdb1d0a7f425b8007d25c9f1edcf0b5f5c3ba", + "pub_key": "67e3d14e1e0db2a6ff68832994451f63d3e92a4ee85c3681d72634ccfe889f2c" } }, { @@ -142,7 +151,8 @@ }, "result": { "signature": "1cd79c511e58e0d00bc402c24631a982c0f596e13cad38447d4f31213d085b23b9990b45023450f5ab4d47987993af662702b07bfc8195feb80b2c9e1c1dc10f", - "address": "d9553a4de9c7ad8532abdb1d0a7f425b8007d25c9f1edcf0b5f5c3ba" + "address": "d9553a4de9c7ad8532abdb1d0a7f425b8007d25c9f1edcf0b5f5c3ba", + "pub_key": "67e3d14e1e0db2a6ff68832994451f63d3e92a4ee85c3681d72634ccfe889f2c" } } ] diff --git a/core/src/apps/cardano/sign_message.py b/core/src/apps/cardano/sign_message.py index a8fb8f887..edf01fb89 100644 --- a/core/src/apps/cardano/sign_message.py +++ b/core/src/apps/cardano/sign_message.py @@ -7,6 +7,7 @@ from trezor.wire.context import call as ctx_call from apps.cardano.helpers.chunks import MAX_CHUNK_SIZE, ChunkIterator from apps.cardano.helpers.credential import Credential from apps.cardano.helpers.paths import SCHEMA_MINT, SCHEMA_PUBKEY +from apps.cardano.helpers.utils import derive_public_key from apps.common import cbor from . import addresses, seed @@ -182,4 +183,8 @@ async def sign_message( _cborize_sig_structure(payload=payload, protected_headers=headers), ) - return CardanoSignMessageFinished(signature=signature, address=address) + return CardanoSignMessageFinished( + signature=signature, + address=address, + pub_key=derive_public_key(keychain, msg.signing_path), + ) diff --git a/core/src/trezor/messages.py b/core/src/trezor/messages.py index 74a7cb488..14e98a79e 100644 --- a/core/src/trezor/messages.py +++ b/core/src/trezor/messages.py @@ -1924,12 +1924,14 @@ if TYPE_CHECKING: class CardanoSignMessageFinished(protobuf.MessageType): signature: "bytes" address: "bytes" + pub_key: "bytes" def __init__( self, *, signature: "bytes", address: "bytes", + pub_key: "bytes", ) -> None: pass diff --git a/python/src/trezorlib/messages.py b/python/src/trezorlib/messages.py index f80f77f4b..80c0adf7e 100644 --- a/python/src/trezorlib/messages.py +++ b/python/src/trezorlib/messages.py @@ -2983,6 +2983,7 @@ class CardanoSignMessageFinished(protobuf.MessageType): FIELDS = { 1: protobuf.Field("signature", "bytes", repeated=False, required=True), 2: protobuf.Field("address", "bytes", repeated=False, required=True), + 3: protobuf.Field("pub_key", "bytes", repeated=False, required=True), } def __init__( @@ -2990,9 +2991,11 @@ class CardanoSignMessageFinished(protobuf.MessageType): *, signature: "bytes", address: "bytes", + pub_key: "bytes", ) -> None: self.signature = signature self.address = address + self.pub_key = pub_key class CipherKeyValue(protobuf.MessageType): diff --git a/rust/trezor-client/src/protos/generated/messages_cardano.rs b/rust/trezor-client/src/protos/generated/messages_cardano.rs index 77e05d553..e3dd0f955 100644 --- a/rust/trezor-client/src/protos/generated/messages_cardano.rs +++ b/rust/trezor-client/src/protos/generated/messages_cardano.rs @@ -9954,6 +9954,8 @@ pub struct CardanoSignMessageFinished { pub signature: ::std::option::Option<::std::vec::Vec>, // @@protoc_insertion_point(field:hw.trezor.messages.cardano.CardanoSignMessageFinished.address) pub address: ::std::option::Option<::std::vec::Vec>, + // @@protoc_insertion_point(field:hw.trezor.messages.cardano.CardanoSignMessageFinished.pub_key) + pub pub_key: ::std::option::Option<::std::vec::Vec>, // special fields // @@protoc_insertion_point(special_field:hw.trezor.messages.cardano.CardanoSignMessageFinished.special_fields) pub special_fields: ::protobuf::SpecialFields, @@ -10042,8 +10044,44 @@ impl CardanoSignMessageFinished { self.address.take().unwrap_or_else(|| ::std::vec::Vec::new()) } + // required bytes pub_key = 3; + + pub fn pub_key(&self) -> &[u8] { + match self.pub_key.as_ref() { + Some(v) => v, + None => &[], + } + } + + pub fn clear_pub_key(&mut self) { + self.pub_key = ::std::option::Option::None; + } + + pub fn has_pub_key(&self) -> bool { + self.pub_key.is_some() + } + + // Param is passed by value, moved + pub fn set_pub_key(&mut self, v: ::std::vec::Vec) { + self.pub_key = ::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_pub_key(&mut self) -> &mut ::std::vec::Vec { + if self.pub_key.is_none() { + self.pub_key = ::std::option::Option::Some(::std::vec::Vec::new()); + } + self.pub_key.as_mut().unwrap() + } + + // Take field + pub fn take_pub_key(&mut self) -> ::std::vec::Vec { + self.pub_key.take().unwrap_or_else(|| ::std::vec::Vec::new()) + } + fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { - let mut fields = ::std::vec::Vec::with_capacity(2); + 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::<_, _>( "signature", @@ -10055,6 +10093,11 @@ impl CardanoSignMessageFinished { |m: &CardanoSignMessageFinished| { &m.address }, |m: &mut CardanoSignMessageFinished| { &mut m.address }, )); + fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( + "pub_key", + |m: &CardanoSignMessageFinished| { &m.pub_key }, + |m: &mut CardanoSignMessageFinished| { &mut m.pub_key }, + )); ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( "CardanoSignMessageFinished", fields, @@ -10073,6 +10116,9 @@ impl ::protobuf::Message for CardanoSignMessageFinished { if self.address.is_none() { return false; } + if self.pub_key.is_none() { + return false; + } true } @@ -10085,6 +10131,9 @@ impl ::protobuf::Message for CardanoSignMessageFinished { 18 => { self.address = ::std::option::Option::Some(is.read_bytes()?); }, + 26 => { + self.pub_key = ::std::option::Option::Some(is.read_bytes()?); + }, tag => { ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; }, @@ -10103,6 +10152,9 @@ impl ::protobuf::Message for CardanoSignMessageFinished { if let Some(v) = self.address.as_ref() { my_size += ::protobuf::rt::bytes_size(2, &v); } + if let Some(v) = self.pub_key.as_ref() { + my_size += ::protobuf::rt::bytes_size(3, &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 @@ -10115,6 +10167,9 @@ impl ::protobuf::Message for CardanoSignMessageFinished { if let Some(v) = self.address.as_ref() { os.write_bytes(2, v)?; } + if let Some(v) = self.pub_key.as_ref() { + os.write_bytes(3, v)?; + } os.write_unknown_fields(self.special_fields.unknown_fields())?; ::std::result::Result::Ok(()) } @@ -10134,6 +10189,7 @@ impl ::protobuf::Message for CardanoSignMessageFinished { fn clear(&mut self) { self.signature = ::std::option::Option::None; self.address = ::std::option::Option::None; + self.pub_key = ::std::option::Option::None; self.special_fields.clear(); } @@ -10141,6 +10197,7 @@ impl ::protobuf::Message for CardanoSignMessageFinished { static instance: CardanoSignMessageFinished = CardanoSignMessageFinished { signature: ::std::option::Option::None, address: ::std::option::Option::None, + pub_key: ::std::option::Option::None, special_fields: ::protobuf::SpecialFields::new(), }; &instance @@ -11116,35 +11173,36 @@ static file_descriptor_proto_data: &'static [u8] = b"\ ssParameters\x12Z\n\x0fderivation_type\x18\x08\x20\x02(\x0e21.hw.trezor.\ messages.cardano.CardanoDerivationTypeR\x0ederivationType\"\x17\n\x15Car\ danoMessageItemAck\"0\n\x1aCardanoMessagePayloadChunk\x12\x12\n\x04data\ - \x18\x01\x20\x02(\x0cR\x04data\"\x1b\n\x19CardanoMessageItemHostAck\"T\n\ + \x18\x01\x20\x02(\x0cR\x04data\"\x1b\n\x19CardanoMessageItemHostAck\"m\n\ \x1aCardanoSignMessageFinished\x12\x1c\n\tsignature\x18\x01\x20\x02(\x0c\ - R\tsignature\x12\x18\n\x07address\x18\x02\x20\x02(\x0cR\x07address*B\n\ - \x15CardanoDerivationType\x12\n\n\x06LEDGER\x10\0\x12\n\n\x06ICARUS\x10\ - \x01\x12\x11\n\rICARUS_TREZOR\x10\x02*\xd2\x01\n\x12CardanoAddressType\ - \x12\x08\n\x04BASE\x10\0\x12\x13\n\x0fBASE_SCRIPT_KEY\x10\x01\x12\x13\n\ - \x0fBASE_KEY_SCRIPT\x10\x02\x12\x16\n\x12BASE_SCRIPT_SCRIPT\x10\x03\x12\ - \x0b\n\x07POINTER\x10\x04\x12\x12\n\x0ePOINTER_SCRIPT\x10\x05\x12\x0e\n\ - \nENTERPRISE\x10\x06\x12\x15\n\x11ENTERPRISE_SCRIPT\x10\x07\x12\t\n\x05B\ - YRON\x10\x08\x12\n\n\x06REWARD\x10\x0e\x12\x11\n\rREWARD_SCRIPT\x10\x0f*\ - o\n\x17CardanoNativeScriptType\x12\x0b\n\x07PUB_KEY\x10\0\x12\x07\n\x03A\ - LL\x10\x01\x12\x07\n\x03ANY\x10\x02\x12\n\n\x06N_OF_K\x10\x03\x12\x12\n\ - \x0eINVALID_BEFORE\x10\x04\x12\x15\n\x11INVALID_HEREAFTER\x10\x05*K\n$Ca\ - rdanoNativeScriptHashDisplayFormat\x12\x08\n\x04HIDE\x10\0\x12\n\n\x06BE\ - CH32\x10\x01\x12\r\n\tPOLICY_ID\x10\x02*G\n\"CardanoTxOutputSerializatio\ - nFormat\x12\x10\n\x0cARRAY_LEGACY\x10\0\x12\x0f\n\x0bMAP_BABBAGE\x10\x01\ - *}\n\x16CardanoCertificateType\x12\x16\n\x12STAKE_REGISTRATION\x10\0\x12\ - \x18\n\x14STAKE_DEREGISTRATION\x10\x01\x12\x14\n\x10STAKE_DELEGATION\x10\ - \x02\x12\x1b\n\x17STAKE_POOL_REGISTRATION\x10\x03*X\n\x14CardanoPoolRela\ - yType\x12\x12\n\x0eSINGLE_HOST_IP\x10\0\x12\x14\n\x10SINGLE_HOST_NAME\ - \x10\x01\x12\x16\n\x12MULTIPLE_HOST_NAME\x10\x02*R\n$CardanoTxAuxiliaryD\ - ataSupplementType\x12\x08\n\x04NONE\x10\0\x12\x20\n\x1cCVOTE_REGISTRATIO\ - N_SIGNATURE\x10\x01*6\n\x1eCardanoCVoteRegistrationFormat\x12\t\n\x05CIP\ - 15\x10\0\x12\t\n\x05CIP36\x10\x01*\x82\x01\n\x14CardanoTxSigningMode\x12\ - \x18\n\x14ORDINARY_TRANSACTION\x10\0\x12\x1e\n\x1aPOOL_REGISTRATION_AS_O\ - WNER\x10\x01\x12\x18\n\x14MULTISIG_TRANSACTION\x10\x02\x12\x16\n\x12PLUT\ - US_TRANSACTION\x10\x03*>\n\x14CardanoTxWitnessType\x12\x11\n\rBYRON_WITN\ - ESS\x10\0\x12\x13\n\x0fSHELLEY_WITNESS\x10\x01B;\n#com.satoshilabs.trezo\ - r.lib.protobufB\x14TrezorMessageCardano\ + R\tsignature\x12\x18\n\x07address\x18\x02\x20\x02(\x0cR\x07address\x12\ + \x17\n\x07pub_key\x18\x03\x20\x02(\x0cR\x06pubKey*B\n\x15CardanoDerivati\ + onType\x12\n\n\x06LEDGER\x10\0\x12\n\n\x06ICARUS\x10\x01\x12\x11\n\rICAR\ + US_TREZOR\x10\x02*\xd2\x01\n\x12CardanoAddressType\x12\x08\n\x04BASE\x10\ + \0\x12\x13\n\x0fBASE_SCRIPT_KEY\x10\x01\x12\x13\n\x0fBASE_KEY_SCRIPT\x10\ + \x02\x12\x16\n\x12BASE_SCRIPT_SCRIPT\x10\x03\x12\x0b\n\x07POINTER\x10\ + \x04\x12\x12\n\x0ePOINTER_SCRIPT\x10\x05\x12\x0e\n\nENTERPRISE\x10\x06\ + \x12\x15\n\x11ENTERPRISE_SCRIPT\x10\x07\x12\t\n\x05BYRON\x10\x08\x12\n\n\ + \x06REWARD\x10\x0e\x12\x11\n\rREWARD_SCRIPT\x10\x0f*o\n\x17CardanoNative\ + ScriptType\x12\x0b\n\x07PUB_KEY\x10\0\x12\x07\n\x03ALL\x10\x01\x12\x07\n\ + \x03ANY\x10\x02\x12\n\n\x06N_OF_K\x10\x03\x12\x12\n\x0eINVALID_BEFORE\ + \x10\x04\x12\x15\n\x11INVALID_HEREAFTER\x10\x05*K\n$CardanoNativeScriptH\ + ashDisplayFormat\x12\x08\n\x04HIDE\x10\0\x12\n\n\x06BECH32\x10\x01\x12\r\ + \n\tPOLICY_ID\x10\x02*G\n\"CardanoTxOutputSerializationFormat\x12\x10\n\ + \x0cARRAY_LEGACY\x10\0\x12\x0f\n\x0bMAP_BABBAGE\x10\x01*}\n\x16CardanoCe\ + rtificateType\x12\x16\n\x12STAKE_REGISTRATION\x10\0\x12\x18\n\x14STAKE_D\ + EREGISTRATION\x10\x01\x12\x14\n\x10STAKE_DELEGATION\x10\x02\x12\x1b\n\ + \x17STAKE_POOL_REGISTRATION\x10\x03*X\n\x14CardanoPoolRelayType\x12\x12\ + \n\x0eSINGLE_HOST_IP\x10\0\x12\x14\n\x10SINGLE_HOST_NAME\x10\x01\x12\x16\ + \n\x12MULTIPLE_HOST_NAME\x10\x02*R\n$CardanoTxAuxiliaryDataSupplementTyp\ + e\x12\x08\n\x04NONE\x10\0\x12\x20\n\x1cCVOTE_REGISTRATION_SIGNATURE\x10\ + \x01*6\n\x1eCardanoCVoteRegistrationFormat\x12\t\n\x05CIP15\x10\0\x12\t\ + \n\x05CIP36\x10\x01*\x82\x01\n\x14CardanoTxSigningMode\x12\x18\n\x14ORDI\ + NARY_TRANSACTION\x10\0\x12\x1e\n\x1aPOOL_REGISTRATION_AS_OWNER\x10\x01\ + \x12\x18\n\x14MULTISIG_TRANSACTION\x10\x02\x12\x16\n\x12PLUTUS_TRANSACTI\ + ON\x10\x03*>\n\x14CardanoTxWitnessType\x12\x11\n\rBYRON_WITNESS\x10\0\ + \x12\x13\n\x0fSHELLEY_WITNESS\x10\x01B;\n#com.satoshilabs.trezor.lib.pro\ + tobufB\x14TrezorMessageCardano\ "; /// `FileDescriptorProto` object which was a source for this generated file diff --git a/tests/device_tests/cardano/test_sign_message.py b/tests/device_tests/cardano/test_sign_message.py index 170d529db..93898ade8 100644 --- a/tests/device_tests/cardano/test_sign_message.py +++ b/tests/device_tests/cardano/test_sign_message.py @@ -50,4 +50,5 @@ def _transform_expected_result(result: dict) -> messages.CardanoSignMessageFinis return messages.CardanoSignMessageFinished( signature=bytes.fromhex(result["signature"]), address=bytes.fromhex(result["address"]), + pub_key=bytes.fromhex(result["pub_key"]), )