1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-02-28 07:12:28 +00:00

feat(core/ui): add basic confirmation for Nostr signing

[no changelog]
This commit is contained in:
Ioan Bizău 2024-12-17 18:08:07 +01:00
parent dff4ca5ab0
commit 4350b0d31d
8 changed files with 30 additions and 4 deletions

View File

@ -339,6 +339,7 @@ static void _librust_qstrs(void) {
MP_QSTR_modify_fee__transaction_fee; MP_QSTR_modify_fee__transaction_fee;
MP_QSTR_more_info_callback; MP_QSTR_more_info_callback;
MP_QSTR_multiple_pages_texts; MP_QSTR_multiple_pages_texts;
MP_QSTR_nostr__event_kind_template;
MP_QSTR_notification; MP_QSTR_notification;
MP_QSTR_notification_level; MP_QSTR_notification_level;
MP_QSTR_page_count; MP_QSTR_page_count;

View File

@ -1402,6 +1402,8 @@ pub enum TranslatedString {
solana__stake_on_question = 989, // "Stake SOL on {0}?" solana__stake_on_question = 989, // "Stake SOL on {0}?"
sign_message__confirm_without_review = 990, // "Confirm without review" sign_message__confirm_without_review = 990, // "Confirm without review"
instructions__tap_to_continue = 991, // "Tap to continue" instructions__tap_to_continue = 991, // "Tap to continue"
#[cfg(feature = "universal_fw")]
nostr__event_kind_template = 992, // "Event kind: {0}"
} }
impl TranslatedString { impl TranslatedString {
@ -2800,6 +2802,8 @@ impl TranslatedString {
Self::solana__stake_on_question => "Stake SOL on {0}?", Self::solana__stake_on_question => "Stake SOL on {0}?",
Self::sign_message__confirm_without_review => "Confirm without review", Self::sign_message__confirm_without_review => "Confirm without review",
Self::instructions__tap_to_continue => "Tap to continue", Self::instructions__tap_to_continue => "Tap to continue",
#[cfg(feature = "universal_fw")]
Self::nostr__event_kind_template => "Event kind: {0}",
} }
} }
@ -4197,6 +4201,8 @@ impl TranslatedString {
Qstr::MP_QSTR_solana__stake_on_question => Some(Self::solana__stake_on_question), Qstr::MP_QSTR_solana__stake_on_question => Some(Self::solana__stake_on_question),
Qstr::MP_QSTR_sign_message__confirm_without_review => Some(Self::sign_message__confirm_without_review), Qstr::MP_QSTR_sign_message__confirm_without_review => Some(Self::sign_message__confirm_without_review),
Qstr::MP_QSTR_instructions__tap_to_continue => Some(Self::instructions__tap_to_continue), Qstr::MP_QSTR_instructions__tap_to_continue => Some(Self::instructions__tap_to_continue),
#[cfg(feature = "universal_fw")]
Qstr::MP_QSTR_nostr__event_kind_template => Some(Self::nostr__event_kind_template),
_ => None, _ => None,
} }
} }

View File

@ -497,6 +497,7 @@ class TR:
nem__under_namespace: str = "under namespace" nem__under_namespace: str = "under namespace"
nem__unencrypted: str = "Unencrypted" nem__unencrypted: str = "Unencrypted"
nem__unknown_mosaic: str = "Unknown mosaic!" nem__unknown_mosaic: str = "Unknown mosaic!"
nostr__event_kind_template: str = "Event kind: {0}"
passphrase__access_wallet: str = "Access passphrase wallet?" passphrase__access_wallet: str = "Access passphrase wallet?"
passphrase__always_on_device: str = "Always enter your passphrase on Trezor?" passphrase__always_on_device: str = "Always enter your passphrase on Trezor?"
passphrase__continue_with_empty_passphrase: str = "Continue with empty passphrase?" passphrase__continue_with_empty_passphrase: str = "Continue with empty passphrase?"

View File

@ -12,9 +12,11 @@ if TYPE_CHECKING:
async def sign_event(msg: NostrSignEvent, keychain: Keychain) -> NostrEventSignature: async def sign_event(msg: NostrSignEvent, keychain: Keychain) -> NostrEventSignature:
from ubinascii import hexlify from ubinascii import hexlify
from trezor import TR
from trezor.crypto.curve import secp256k1 from trezor.crypto.curve import secp256k1
from trezor.crypto.hashlib import sha256 from trezor.crypto.hashlib import sha256
from trezor.messages import NostrEventSignature from trezor.messages import NostrEventSignature
from trezor.ui.layouts import confirm_value
from apps.common import paths from apps.common import paths
@ -29,6 +31,19 @@ async def sign_event(msg: NostrSignEvent, keychain: Keychain) -> NostrEventSigna
node = keychain.derive(address_n) node = keychain.derive(address_n)
pk = node.public_key()[-32:] pk = node.public_key()[-32:]
title = TR.nostr__event_kind_template.format(kind)
# confirm_value on TR only accepts one single info item
# which is why we concatenate all of them here.
# This is not great, but it gets the job done for now.
tags_str = f"created_at: {created_at}"
for t in tags:
tags_str += f"\n\n{t[0]}: " + (f" {' '.join(t[1:])}" if len(t) > 1 else "")
await confirm_value(
title, content, "", "nostr_sign_event", info_items=[("", tags_str)]
)
# The event ID is obtained by serializing the event in a specific way: # The event ID is obtained by serializing the event in a specific way:
# "[0,pubkey,created_at,kind,tags,content]" # "[0,pubkey,created_at,kind,tags,content]"
# See NIP-01: https://github.com/nostr-protocol/nips/blob/master/01.md # See NIP-01: https://github.com/nostr-protocol/nips/blob/master/01.md

View File

@ -792,6 +792,7 @@ async def confirm_value(
else: else:
info_items_list = list(info_items) info_items_list = list(info_items)
if len(info_items_list) > 1: if len(info_items_list) > 1:
# TODO: Support more than one info item!
raise NotImplementedError("Only one info item is supported") raise NotImplementedError("Only one info item is supported")
send_button_request = True send_button_request = True

View File

@ -499,6 +499,7 @@
"nem__under_namespace": "under namespace", "nem__under_namespace": "under namespace",
"nem__unencrypted": "Unencrypted", "nem__unencrypted": "Unencrypted",
"nem__unknown_mosaic": "Unknown mosaic!", "nem__unknown_mosaic": "Unknown mosaic!",
"nostr__event_kind_template": "Event kind: {0}",
"passphrase__access_wallet": "Access passphrase wallet?", "passphrase__access_wallet": "Access passphrase wallet?",
"passphrase__always_on_device": "Always enter your passphrase on Trezor?", "passphrase__always_on_device": "Always enter your passphrase on Trezor?",
"passphrase__continue_with_empty_passphrase": "Continue with empty passphrase?", "passphrase__continue_with_empty_passphrase": "Continue with empty passphrase?",

View File

@ -990,5 +990,6 @@
"988": "solana__vote_account", "988": "solana__vote_account",
"989": "solana__stake_on_question", "989": "solana__stake_on_question",
"990": "sign_message__confirm_without_review", "990": "sign_message__confirm_without_review",
"991": "instructions__tap_to_continue" "991": "instructions__tap_to_continue",
"992": "nostr__event_kind_template"
} }

View File

@ -1,8 +1,8 @@
{ {
"current": { "current": {
"merkle_root": "1754d367a3f9796a460e21677a38465ac51110a5abaae96a8977e64cd3d35e27", "merkle_root": "6684203c68c3a64d607c948fac5eeaa9f349f0e81cf54c8dfc662d5a8d3662e8",
"datetime": "2025-02-25T22:15:23.529862", "datetime": "2025-02-27T10:39:27.809453",
"commit": "ba8a64d3e42febd344f60f039b6ac21ffb36aa9c" "commit": "3dd1b0c026405da729821b8130baa7bfff432121"
}, },
"history": [ "history": [
{ {