diff --git a/Cargo.lock b/Cargo.lock index 993dc20..bf6d9f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -192,9 +192,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "ledger_device_sdk" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6357bb0259db7b9c0ac031ab5ce13d32df66df3ec8d83e3f8ab0751082d969ff" +checksum = "eaea86ded135eb27f837fa339baf8ed90ff5864a58feef1a7d923627d99711cf" dependencies = [ "include_gif", "ledger_secure_sdk_sys", diff --git a/Cargo.toml b/Cargo.toml index 1237264..563cf0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ authors = ["yhql", "agrojean-ledger", "dj8yf0μl"] edition = "2021" [dependencies] -ledger_device_sdk = "1.4.0" +ledger_device_sdk = "1.4.3" ledger_secure_sdk_sys = "1.0.2" include_gif = "1.0.1" hex = { version = "0.4.3", default-features = false, features = ["serde"] } diff --git a/src/app_ui/address.rs b/src/app_ui/address.rs index 72705cb..2382ebf 100644 --- a/src/app_ui/address.rs +++ b/src/app_ui/address.rs @@ -15,9 +15,9 @@ * limitations under the License. *****************************************************************************/ -use crate::AppSW; use crate::utils::crypto; use crate::utils::types::fmt_buffer::FmtBuffer; +use crate::AppSW; use ledger_device_sdk::ui::bitmaps::{CROSSMARK, EYE, VALIDATE_14}; use ledger_device_sdk::ui::gadgets::{Field, MultiFieldReview}; diff --git a/src/app_ui/fields_writer.rs b/src/app_ui/fields_writer.rs index e0fd627..f9cc675 100644 --- a/src/app_ui/fields_writer.rs +++ b/src/app_ui/fields_writer.rs @@ -2,13 +2,12 @@ use ledger_device_sdk::ui::gadgets::Field; use crate::utils::types::capped_string::ElipsisFields; - - pub struct FieldsWriter<'a, const N: usize> { buffer: [Field<'a>; N], used: usize, } +#[derive(Debug)] pub struct FieldsOverflow; impl<'a, const N: usize> FieldsWriter<'a, N> { diff --git a/src/app_ui/sign/action.rs b/src/app_ui/sign/action.rs index c3e82dc..079b7e4 100644 --- a/src/app_ui/sign/action.rs +++ b/src/app_ui/sign/action.rs @@ -8,6 +8,7 @@ use numtoa::NumToA; mod create_account; mod delete_account; +mod delete_key; mod transfer; pub fn ui_display_transfer( @@ -47,6 +48,19 @@ pub fn ui_display_delete_account( ui_display_common(&mut writer, ordinal, total_actions) } +pub fn ui_display_delete_key( + delete_key: &parsing::types::DeleteKey, + ordinal: u32, + total_actions: u32, +) -> bool { + let mut field_context: delete_key::FieldsContext = delete_key::FieldsContext::new(); + let mut writer: FieldsWriter<'_, 2> = FieldsWriter::new(); + + delete_key::format(delete_key, &mut field_context, &mut writer); + + ui_display_common(&mut writer, ordinal, total_actions) +} + pub fn ui_display_common( writer: &mut FieldsWriter<'_, N>, ordinal: u32, diff --git a/src/app_ui/sign/action/create_account.rs b/src/app_ui/sign/action/create_account.rs index bad193e..1ffde5d 100644 --- a/src/app_ui/sign/action/create_account.rs +++ b/src/app_ui/sign/action/create_account.rs @@ -1,20 +1,16 @@ use crate::parsing; use ledger_device_sdk::ui::gadgets::Field; -use crate::{ - app_ui::fields_writer::FieldsWriter, - utils::types::capped_string::ElipsisFields, -}; +use crate::{app_ui::fields_writer::FieldsWriter, utils::types::capped_string::ElipsisFields}; pub fn format( _create_account: &parsing::types::CreateAccount, writer: &'_ mut FieldsWriter<'_, 1>, ) { - match writer.push_fields(ElipsisFields::one(Field { - name: "Action type:", - value: "Create Account", - })) { - Ok(..) => {} - Err(_err) => panic!("wrong total fields in tx prefix FieldsWriter"), - } + writer + .push_fields(ElipsisFields::one(Field { + name: "Action type:", + value: "Create Account", + })) + .unwrap(); } diff --git a/src/app_ui/sign/action/delete_account.rs b/src/app_ui/sign/action/delete_account.rs index 5dc4f9f..e8b4eb1 100644 --- a/src/app_ui/sign/action/delete_account.rs +++ b/src/app_ui/sign/action/delete_account.rs @@ -1,26 +1,19 @@ use crate::parsing; use ledger_device_sdk::ui::gadgets::Field; -use crate::{ - app_ui::fields_writer::FieldsWriter, - utils::types::capped_string::ElipsisFields, -}; +use crate::{app_ui::fields_writer::FieldsWriter, utils::types::capped_string::ElipsisFields}; pub fn format<'b, 'a: 'b>( delete_account: &'a parsing::types::DeleteAccount, writer: &'_ mut FieldsWriter<'b, 3>, ) { - match writer.push_fields(ElipsisFields::one(Field { - name: "Action type:", - value: "Delete Account", - })) { - Ok(..) => {} - Err(_err) => panic!("wrong total fields in tx prefix FieldsWriter"), - } + writer + .push_fields(ElipsisFields::one(Field { + name: "Action type:", + value: "Delete Account", + })) + .unwrap(); let beneficiary_id = delete_account.beneficiary_id.ui_fields("Beneficiary"); - match writer.push_fields(beneficiary_id) { - Ok(..) => {} - Err(_err) => panic!("wrong total fields in tx prefix FieldsWriter"), - } + writer.push_fields(beneficiary_id).unwrap(); } diff --git a/src/app_ui/sign/action/delete_key.rs b/src/app_ui/sign/action/delete_key.rs new file mode 100644 index 0000000..0b7c953 --- /dev/null +++ b/src/app_ui/sign/action/delete_key.rs @@ -0,0 +1,68 @@ +use ledger_device_sdk::ui::gadgets::Field; + +use crate::{ + app_ui::fields_writer::FieldsWriter, + parsing::{self, types::tx_public_key::TxPublicKey}, + utils::types::{capped_string::ElipsisFields, fmt_buffer::FmtBuffer}, +}; + +pub struct FieldsContext { + buffer: FmtBuffer<100>, +} + +impl FieldsContext { + pub fn new() -> Self { + Self { + buffer: FmtBuffer::new(), + } + } + + fn format_public_key(&mut self, public_key: &TxPublicKey) { + match public_key { + TxPublicKey::ED25519(arr) => { + let mut tmp_buf = [0u8; 50]; + // NOTE: expecting `tmp_buf` to be always large enough : 1.4 * 32 + let len = bs58::encode(arr).onto(&mut tmp_buf[..]).unwrap(); + // expecting `bs58` to always produce correct strings + // https://docs.rs/bs58/0.5.0/src/bs58/encode.rs.html#201 + let bs58_str = core::str::from_utf8(&tmp_buf[..len]).unwrap(); + + self.buffer.write_str("ed25519:"); + self.buffer.write_str(bs58_str); + } + TxPublicKey::SECP256K1(arr) => { + let mut tmp_buf = [0u8; 90]; + + // expecting `tmp_buf` to be always large enough: 1.4 * 64 + let len = bs58::encode(arr).onto(&mut tmp_buf[..]).unwrap(); + // expecting `bs58` to always produce correct strings + // https://docs.rs/bs58/0.5.0/src/bs58/encode.rs.html#201 + let bs58_str = core::str::from_utf8(&tmp_buf[..len]).unwrap(); + + self.buffer.write_str("secp256k1:"); + self.buffer.write_str(bs58_str); + } + } + } +} + +pub fn format<'b, 'a: 'b>( + delete_key: &parsing::types::DeleteKey, + field_context: &'a mut FieldsContext, + writer: &'_ mut FieldsWriter<'b, 2>, +) { + field_context.format_public_key(&delete_key.public_key); + writer + .push_fields(ElipsisFields::one(Field { + name: "Action type:", + value: "Delete Key", + })) + .unwrap(); + + writer + .push_fields(ElipsisFields::one(Field { + name: "Public Key:", + value: field_context.buffer.as_str(), + })) + .unwrap(); +} diff --git a/src/app_ui/sign/action/transfer.rs b/src/app_ui/sign/action/transfer.rs index 0192613..620012b 100644 --- a/src/app_ui/sign/action/transfer.rs +++ b/src/app_ui/sign/action/transfer.rs @@ -1,10 +1,7 @@ use crate::parsing::{self, types::action::ONE_NEAR}; use ledger_device_sdk::ui::gadgets::Field; -use crate::{ - app_ui::fields_writer::FieldsWriter, - utils::types::capped_string::ElipsisFields, -}; +use crate::{app_ui::fields_writer::FieldsWriter, utils::types::capped_string::ElipsisFields}; pub struct FieldsContext { pub float_buffer: dtoa::Buffer, @@ -15,7 +12,6 @@ impl FieldsContext { Self { float_buffer: dtoa::Buffer::new(), } - } } @@ -24,21 +20,19 @@ pub fn format<'b, 'a: 'b>( field_context: &'a mut FieldsContext, writer: &'_ mut FieldsWriter<'b, 2>, ) { - match writer.push_fields(ElipsisFields::one(Field { - name: "Action type:", - value: "Transfer", - })) { - Ok(..) => {} - Err(_err) => panic!("wrong total fields in tx prefix FieldsWriter"), - } + writer + .push_fields(ElipsisFields::one(Field { + name: "Action type:", + value: "Transfer", + })) + .unwrap(); let deposit = (transfer.deposit as f64) / (ONE_NEAR as f64); let printed = field_context.float_buffer.format(deposit); - match writer.push_fields(ElipsisFields::one(Field { - name: "Amount (NEAR)", - value: printed, - })) { - Ok(..) => {} - Err(_err) => panic!("wrong total fields in tx prefix FieldsWriter"), - } + writer + .push_fields(ElipsisFields::one(Field { + name: "Amount (NEAR)", + value: printed, + })) + .unwrap(); } diff --git a/src/app_ui/sign/transaction_prefix.rs b/src/app_ui/sign/transaction_prefix.rs index 57fd5de..8fbfaf0 100644 --- a/src/app_ui/sign/transaction_prefix.rs +++ b/src/app_ui/sign/transaction_prefix.rs @@ -9,30 +9,26 @@ use crate::{ }; pub fn ui_display(transaction_prefix: &parsing::types::TransactionPrefix) -> bool { + #[cfg(feature = "speculos")] + transaction_prefix.debug_print(); + let mut field_writer: FieldsWriter<'_, 5> = FieldsWriter::new(); let signer_id = transaction_prefix.signer_id.ui_fields("Signer Id"); - match field_writer.push_fields(signer_id) { - Ok(..) => {} - Err(_err) => panic!("wrong total fields in tx prefix FieldsWriter"), - } + field_writer.push_fields(signer_id).unwrap(); let receiver_id = transaction_prefix.receiver_id.ui_fields("Receiver Id"); - match field_writer.push_fields(receiver_id) { - Ok(..) => {} - Err(_err) => panic!("wrong total fields in tx prefix FieldsWriter"), - } + field_writer.push_fields(receiver_id).unwrap(); let mut numtoa_buf = [0u8; 10]; let num_actions_str = transaction_prefix .number_of_actions .numtoa_str(10, &mut numtoa_buf); - match field_writer.push_fields(ElipsisFields::one(Field { - name: "Total actions:", - value: num_actions_str, - })) { - Ok(..) => {} - Err(_err) => panic!("wrong total fields in tx prefix FieldsWriter"), - } + field_writer + .push_fields(ElipsisFields::one(Field { + name: "Total actions:", + value: num_actions_str, + })) + .unwrap(); let my_review = MultiFieldReview::new( field_writer.get_fields(), diff --git a/src/app_ui/sign/widgets.rs b/src/app_ui/sign/widgets.rs index 2d4ce6f..881b3f9 100644 --- a/src/app_ui/sign/widgets.rs +++ b/src/app_ui/sign/widgets.rs @@ -17,7 +17,7 @@ use ledger_device_sdk::ui::bitmaps::WARNING; use ledger_device_sdk::ui::gadgets::clear_screen; -use ledger_device_sdk::ui::layout::{StringPlace, Location, Layout}; +use ledger_device_sdk::ui::layout::{Layout, Location, StringPlace}; use ledger_device_sdk::ui::screen_util::screen_update; pub fn display_receiving() { diff --git a/src/handlers/get_public_key.rs b/src/handlers/get_public_key.rs index 097028e..5f5070e 100644 --- a/src/handlers/get_public_key.rs +++ b/src/handlers/get_public_key.rs @@ -20,7 +20,6 @@ use crate::utils::crypto; use crate::AppSW; use ledger_device_sdk::io::Comm; - pub fn handler(comm: &mut Comm, display: bool) -> Result<(), AppSW> { let data = comm.get_data().map_err(|_| AppSW::WrongApduLength)?; let path = crypto::PathBip32::parse(data).map_err(|_| AppSW::Bip32PathParsingFail)?; diff --git a/src/handlers/get_version.rs b/src/handlers/get_version.rs index 4661866..f6c38ef 100644 --- a/src/handlers/get_version.rs +++ b/src/handlers/get_version.rs @@ -20,7 +20,6 @@ use ledger_device_sdk::io; #[cfg(feature = "speculos")] use ledger_device_sdk::testing; - pub fn handler(comm: &mut io::Comm) -> Result<(), AppSW> { #[cfg(feature = "speculos")] testing::debug_print("enter `handler_get_version` fn\n"); diff --git a/src/handlers/get_wallet_id.rs b/src/handlers/get_wallet_id.rs index 400e1a3..86d5237 100644 --- a/src/handlers/get_wallet_id.rs +++ b/src/handlers/get_wallet_id.rs @@ -3,7 +3,6 @@ use crate::utils::crypto; use crate::AppSW; use ledger_device_sdk::io::Comm; - pub fn handler(comm: &mut Comm) -> Result<(), AppSW> { let data = comm.get_data().map_err(|_| AppSW::WrongApduLength)?; let path = crypto::PathBip32::parse(data).map_err(|_| AppSW::Bip32PathParsingFail)?; diff --git a/src/handlers/sign_tx.rs b/src/handlers/sign_tx.rs index 5f3bf86..f8ef1f6 100644 --- a/src/handlers/sign_tx.rs +++ b/src/handlers/sign_tx.rs @@ -33,9 +33,10 @@ const MAX_TRANSACTION_LEN: usize = 534; pub struct Signature(pub [u8; 64]); -pub mod transfer; pub mod create_account; pub mod delete_account; +pub mod delete_key; +pub mod transfer; fn popup_transaction_prefix(stream: &mut HashingStream>) -> Result { let mut tx_prefix = parsing::types::TransactionPrefix { @@ -65,6 +66,7 @@ fn popup_action( Action::Transfer => transfer::handle(stream, ordinal_action, total_actions), Action::CreateAccount => create_account::handle(stream, ordinal_action, total_actions), Action::DeleteAccount => delete_account::handle(stream, ordinal_action, total_actions), + Action::DeleteKey => delete_key::handle(stream, ordinal_action, total_actions), _ => unimplemented!(), } } diff --git a/src/handlers/sign_tx/create_account.rs b/src/handlers/sign_tx/create_account.rs index e01ff13..5686b39 100644 --- a/src/handlers/sign_tx/create_account.rs +++ b/src/handlers/sign_tx/create_account.rs @@ -1,16 +1,26 @@ -use crate::{AppSW, parsing::{HashingStream, SingleTxStream, types::CreateAccount, borsh::BorshDeserialize}}; use crate::sign_ui; +use crate::{ + parsing::{borsh::BorshDeserialize, types::CreateAccount, HashingStream, SingleTxStream}, + AppSW, +}; -pub fn handle(stream: &mut HashingStream>, ordinal_action: u32, total_actions: u32) -> Result<(), AppSW> { - let create_account = CreateAccount::deserialize_reader(stream).map_err(|_err| AppSW::TxParsingFail)?; +pub fn handle( + stream: &mut HashingStream>, + ordinal_action: u32, + total_actions: u32, +) -> Result<(), AppSW> { + let create_account = + CreateAccount::deserialize_reader(stream).map_err(|_err| AppSW::TxParsingFail)?; #[cfg(feature = "speculos")] create_account.debug_print(); - - if !sign_ui::action::ui_display_create_account(&create_account, ordinal_action + 1, total_actions) { + if !sign_ui::action::ui_display_create_account( + &create_account, + ordinal_action + 1, + total_actions, + ) { return Err(AppSW::Deny); } Ok(()) - } diff --git a/src/handlers/sign_tx/delete_account.rs b/src/handlers/sign_tx/delete_account.rs index e6fe1f2..20639e2 100644 --- a/src/handlers/sign_tx/delete_account.rs +++ b/src/handlers/sign_tx/delete_account.rs @@ -1,17 +1,28 @@ -use crate::{AppSW, parsing::{HashingStream, SingleTxStream, types::DeleteAccount}}; use crate::sign_ui; +use crate::{ + parsing::{types::DeleteAccount, HashingStream, SingleTxStream}, + AppSW, +}; -pub fn handle(stream: &mut HashingStream>, ordinal_action: u32, total_actions: u32) -> Result<(), AppSW> { +pub fn handle( + stream: &mut HashingStream>, + ordinal_action: u32, + total_actions: u32, +) -> Result<(), AppSW> { let mut delete_account = DeleteAccount::new(); - delete_account.deserialize_reader_in_place(stream).map_err(|_err| AppSW::TxParsingFail)?; + delete_account + .deserialize_reader_in_place(stream) + .map_err(|_err| AppSW::TxParsingFail)?; #[cfg(feature = "speculos")] delete_account.debug_print(); - - if !sign_ui::action::ui_display_delete_account(&delete_account, ordinal_action + 1, total_actions) { + if !sign_ui::action::ui_display_delete_account( + &delete_account, + ordinal_action + 1, + total_actions, + ) { return Err(AppSW::Deny); } Ok(()) - } diff --git a/src/handlers/sign_tx/delete_key.rs b/src/handlers/sign_tx/delete_key.rs new file mode 100644 index 0000000..8183120 --- /dev/null +++ b/src/handlers/sign_tx/delete_key.rs @@ -0,0 +1,21 @@ +use crate::sign_ui; +use crate::{ + parsing::{borsh::BorshDeserialize, types::DeleteKey, HashingStream, SingleTxStream}, + AppSW, +}; + +pub fn handle( + stream: &mut HashingStream>, + ordinal_action: u32, + total_actions: u32, +) -> Result<(), AppSW> { + let delete_key = DeleteKey::deserialize_reader(stream).map_err(|_err| AppSW::TxParsingFail)?; + + #[cfg(feature = "speculos")] + delete_key.debug_print(); + + if !sign_ui::action::ui_display_delete_key(&delete_key, ordinal_action + 1, total_actions) { + return Err(AppSW::Deny); + } + Ok(()) +} diff --git a/src/handlers/sign_tx/transfer.rs b/src/handlers/sign_tx/transfer.rs index d517620..21fa37a 100644 --- a/src/handlers/sign_tx/transfer.rs +++ b/src/handlers/sign_tx/transfer.rs @@ -1,16 +1,21 @@ -use crate::{AppSW, parsing::{HashingStream, SingleTxStream, types::Transfer, borsh::BorshDeserialize}}; use crate::sign_ui; +use crate::{ + parsing::{borsh::BorshDeserialize, types::Transfer, HashingStream, SingleTxStream}, + AppSW, +}; -pub fn handle(stream: &mut HashingStream>, ordinal_action: u32, total_actions: u32) -> Result<(), AppSW> { +pub fn handle( + stream: &mut HashingStream>, + ordinal_action: u32, + total_actions: u32, +) -> Result<(), AppSW> { let transfer = Transfer::deserialize_reader(stream).map_err(|_err| AppSW::TxParsingFail)?; #[cfg(feature = "speculos")] transfer.debug_print(); - if !sign_ui::action::ui_display_transfer(&transfer, ordinal_action + 1, total_actions) { return Err(AppSW::Deny); } Ok(()) - } diff --git a/src/io/mod.rs b/src/io/mod.rs index 411cffa..56b9dfc 100644 --- a/src/io/mod.rs +++ b/src/io/mod.rs @@ -51,12 +51,10 @@ pub struct Error { repr: Repr, } - enum Repr { Simple(ErrorKind), } - /// A list specifying general categories of I/O error. /// /// This list is intended to grow over time and it is not recommended to @@ -378,9 +376,7 @@ pub trait Write { while !buf.is_empty() { match self.write(buf) { Ok(0) => { - return Err(Error::from( - ErrorKind::WriteZero, - )); + return Err(Error::from(ErrorKind::WriteZero)); } Ok(n) => buf = &buf[n..], Err(ref e) if e.kind() == ErrorKind::Interrupted => {} @@ -526,9 +522,7 @@ impl Write for &mut [u8] { if self.write(data)? == data.len() { Ok(()) } else { - Err(Error::from( - ErrorKind::WriteZero, - )) + Err(Error::from(ErrorKind::WriteZero)) } } @@ -537,7 +531,6 @@ impl Write for &mut [u8] { } } - /// The `Read` trait allows for reading bytes from a source. /// /// Implementors of the `Read` trait are called 'readers'. @@ -798,9 +791,7 @@ fn default_read_exact(this: &mut R, mut buf: &mut [u8]) -> Res } } if !buf.is_empty() { - Err(Error::from( - ErrorKind::UnexpectedEof, - )) + Err(Error::from(ErrorKind::UnexpectedEof)) } else { Ok(()) } @@ -836,9 +827,7 @@ impl Read for &[u8] { fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> { if buf.len() > self.len() { - return Err(Error::from( - ErrorKind::UnexpectedEof, - )); + return Err(Error::from(ErrorKind::UnexpectedEof)); } let (a, b) = self.split_at(buf.len()); diff --git a/src/main.rs b/src/main.rs index e177d2c..8be95d4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -56,11 +56,13 @@ pub mod parsing { pub mod transaction_stream_reader; pub mod types { pub mod action; + pub mod crypto_hash; pub mod transaction_prefix; + pub mod tx_public_key; pub use action::{ - create_account::CreateAccount, delete_account::DeleteAccount, transfer::Transfer, - Action, + create_account::CreateAccount, delete_account::DeleteAccount, delete_key::DeleteKey, + transfer::Transfer, Action, }; pub use transaction_prefix::TransactionPrefix; } diff --git a/src/parsing/transaction_stream_reader/mod.rs b/src/parsing/transaction_stream_reader/mod.rs index 0429fff..bf8cf90 100644 --- a/src/parsing/transaction_stream_reader/mod.rs +++ b/src/parsing/transaction_stream_reader/mod.rs @@ -5,7 +5,7 @@ use ledger_device_sdk::{ use crate::{io, AppSW, Instruction}; use ledger_secure_sdk_sys::{ - cx_hash_t, cx_hash_update, cx_sha256_init_no_throw, cx_sha256_t, CX_OK, cx_hash_final + cx_hash_final, cx_hash_t, cx_hash_update, cx_sha256_init_no_throw, cx_sha256_t, CX_OK, }; #[cfg(feature = "speculos")] @@ -61,7 +61,6 @@ impl HashingStream { } } Ok(Sha256Digest(array)) - } } diff --git a/src/parsing/types/action/delete_account.rs b/src/parsing/types/action/delete_account.rs index 01f096a..ecf1e3d 100644 --- a/src/parsing/types/action/delete_account.rs +++ b/src/parsing/types/action/delete_account.rs @@ -12,7 +12,6 @@ impl DeleteAccount { Self { beneficiary_id: CappedString::new(false), } - } pub fn deserialize_reader_in_place(&mut self, reader: &mut R) -> Result<()> { self.beneficiary_id.deserialize_reader_in_place(reader)?; diff --git a/src/parsing/types/action/delete_key.rs b/src/parsing/types/action/delete_key.rs new file mode 100644 index 0000000..e3cbc74 --- /dev/null +++ b/src/parsing/types/action/delete_key.rs @@ -0,0 +1,33 @@ +use crate::{ + io::{Read, Result}, + parsing::{borsh::BorshDeserialize, types::tx_public_key::TxPublicKey}, +}; + +pub struct DeleteKey { + /// A public key associated with the access_key to be deleted. + pub public_key: TxPublicKey, +} + +impl BorshDeserialize for DeleteKey { + fn deserialize_reader(rd: &mut R) -> Result { + Ok(Self { + public_key: BorshDeserialize::deserialize_reader(rd)?, + }) + } +} + +impl DeleteKey { + #[cfg(feature = "speculos")] + pub fn debug_print(&self) { + use ledger_device_sdk::testing; + use numtoa::NumToA; + + let mut numtoa_buf = [0u8; 40]; + + testing::debug_print("debug printing delete key action:\n"); + testing::debug_print("size of self: \n"); + testing::debug_print(core::mem::size_of_val(self).numtoa_str(10, &mut numtoa_buf)); + testing::debug_print("\n"); + testing::debug_print("debug printing delete key action finish:\n"); + } +} diff --git a/src/parsing/types/action/mod.rs b/src/parsing/types/action/mod.rs index 25c3928..8f80e81 100644 --- a/src/parsing/types/action/mod.rs +++ b/src/parsing/types/action/mod.rs @@ -10,6 +10,7 @@ pub const ONE_NEAR: Balance = 1_000_000_000_000_000_000_000_000; pub mod create_account; pub mod delete_account; +pub mod delete_key; pub mod transfer; pub enum Action { @@ -28,9 +29,10 @@ impl BorshDeserialize for Action { fn deserialize_reader(reader: &mut R) -> Result { let variant_tag = u8::deserialize_reader(reader)?; match variant_tag { - 1 | 2 | 4 | 5 | 6 | 8 => unimplemented!("stub for other variants"), + 1 | 2 | 4 | 5 | 8 => unimplemented!("stub for other variants"), 0 => Ok(Self::CreateAccount), 3 => Ok(Self::Transfer), + 6 => Ok(Self::DeleteKey), 7 => Ok(Self::DeleteAccount), _ => { return Err(Error::from(ErrorKind::InvalidData)); diff --git a/src/parsing/types/action/transfer.rs b/src/parsing/types/action/transfer.rs index 4df70f5..7b26ad1 100644 --- a/src/parsing/types/action/transfer.rs +++ b/src/parsing/types/action/transfer.rs @@ -32,7 +32,6 @@ impl Transfer { testing::debug_print("\n"); testing::debug_print("debug printing amount:\n"); - testing::debug_print(self.deposit.numtoa_str(10, &mut numtoa_buf)); testing::debug_print("\n"); let deposit = (self.deposit as f64) / (ONE_NEAR as f64); diff --git a/src/parsing/types/crypto_hash.rs b/src/parsing/types/crypto_hash.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/parsing/types/crypto_hash.rs @@ -0,0 +1 @@ + diff --git a/src/parsing/types/transaction_prefix/mod.rs b/src/parsing/types/transaction_prefix/mod.rs index 012f5bd..3e7075e 100644 --- a/src/parsing/types/transaction_prefix/mod.rs +++ b/src/parsing/types/transaction_prefix/mod.rs @@ -2,66 +2,30 @@ use ledger_device_sdk::testing; use crate::{ + io::{Read, Result}, parsing::borsh::BorshDeserialize, - io::{ErrorKind, Read, Result}, utils::types::capped_string::CappedString, }; +use super::tx_public_key::TxPublicKey; + // NOTE: works on nanos, and speculos -// +// // signer_id: CappedString<400>, -// receiver_id: CappedString<400>, +// receiver_id: CappedString<400>, // works, but overflows total MultiFieldReview windows for display -// +// // signer_id: CappedString<300>, (Signer Id 1/18 -> Signer Id 18/18) // receiver_id: CappedString<300> (Receiver Id 1/18 -> Receiver Id 18/18) -// works +// works pub struct TransactionPrefix { pub signer_id: CappedString<64>, pub receiver_id: CappedString<64>, pub number_of_actions: u32, } -pub enum KeyType { - ED25519 = 0, - SECP256K1 = 1, -} - -pub enum TxPublicKey { - /// 256 bit elliptic curve based public-key. - ED25519([u8; 32]), - /// 512 bit elliptic curve based public-key used in Bitcoin's public-key cryptography. - SECP256K1([u8; 64]), -} - pub struct CryptoHash(pub [u8; 32]); -impl TryFrom for KeyType { - type Error = crate::io::Error; - - fn try_from(value: u8) -> core::result::Result { - match value { - 0 => Ok(KeyType::ED25519), - 1 => Ok(KeyType::SECP256K1), - _unknown_key_type => Err(Self::Error::from(ErrorKind::InvalidData)), - } - } -} - -impl BorshDeserialize for TxPublicKey { - fn deserialize_reader(rd: &mut R) -> Result { - let key_type = KeyType::try_from(u8::deserialize_reader(rd)?)?; - match key_type { - KeyType::ED25519 => Ok(TxPublicKey::ED25519(BorshDeserialize::deserialize_reader( - rd, - )?)), - KeyType::SECP256K1 => Ok(TxPublicKey::SECP256K1( - BorshDeserialize::deserialize_reader(rd)?, - )), - } - } -} - impl BorshDeserialize for CryptoHash { fn deserialize_reader(rd: &mut R) -> Result { Ok(Self(BorshDeserialize::deserialize_reader(rd)?)) @@ -76,6 +40,7 @@ impl TransactionPrefix { let pk: TxPublicKey = BorshDeserialize::deserialize_reader(reader)?; drop(pk); let nonce: u64 = BorshDeserialize::deserialize_reader(reader)?; + #[allow(dropping_copy_types)] drop(nonce); self.receiver_id.deserialize_reader_in_place(reader)?; @@ -94,12 +59,16 @@ impl TransactionPrefix { pub fn debug_print(&self) { use numtoa::NumToA; testing::debug_print("debug printing tx_prefix:\n"); + let mut numtoa_buf = [0u8; 40]; + + testing::debug_print("size of self: \n"); + testing::debug_print(core::mem::size_of_val(self).numtoa_str(10, &mut numtoa_buf)); + testing::debug_print("\n"); testing::debug_print(self.signer_id.as_str()); testing::debug_print("\n"); testing::debug_print(self.receiver_id.as_str()); testing::debug_print("\n"); - let mut numtoa_buf = [0u8; 40]; testing::debug_print(self.number_of_actions.numtoa_str(10, &mut numtoa_buf)); testing::debug_print("\n"); diff --git a/src/parsing/types/tx_public_key.rs b/src/parsing/types/tx_public_key.rs new file mode 100644 index 0000000..94c8ad0 --- /dev/null +++ b/src/parsing/types/tx_public_key.rs @@ -0,0 +1,42 @@ +use crate::{ + io::{ErrorKind, Read, Result}, + parsing::borsh::BorshDeserialize, +}; + +pub enum KeyType { + ED25519 = 0, + SECP256K1 = 1, +} + +pub enum TxPublicKey { + /// 256 bit elliptic curve based public-key. + ED25519([u8; 32]), + /// 512 bit elliptic curve based public-key used in Bitcoin's public-key cryptography. + SECP256K1([u8; 64]), +} + +impl TryFrom for KeyType { + type Error = crate::io::Error; + + fn try_from(value: u8) -> core::result::Result { + match value { + 0 => Ok(KeyType::ED25519), + 1 => Ok(KeyType::SECP256K1), + _unknown_key_type => Err(Self::Error::from(ErrorKind::InvalidData)), + } + } +} + +impl BorshDeserialize for TxPublicKey { + fn deserialize_reader(rd: &mut R) -> Result { + let key_type = KeyType::try_from(u8::deserialize_reader(rd)?)?; + match key_type { + KeyType::ED25519 => Ok(TxPublicKey::ED25519(BorshDeserialize::deserialize_reader( + rd, + )?)), + KeyType::SECP256K1 => Ok(TxPublicKey::SECP256K1( + BorshDeserialize::deserialize_reader(rd)?, + )), + } + } +} diff --git a/src/utils/crypto/public_key.rs b/src/utils/crypto/public_key.rs index fb402b2..0017a4b 100644 --- a/src/utils/crypto/public_key.rs +++ b/src/utils/crypto/public_key.rs @@ -7,7 +7,6 @@ use crate::AppSW; use crate::utils::types::fmt_buffer::FmtBuffer; - const PUBLIC_KEY_BIG_ENDIAN_LEN: usize = 32; const PUBLIC_KEY_LITTLE_ENDIAN_LEN: usize = 65; diff --git a/src/utils/types/capped_string.rs b/src/utils/types/capped_string.rs index fc56f3f..cb81f01 100644 --- a/src/utils/types/capped_string.rs +++ b/src/utils/types/capped_string.rs @@ -1,8 +1,8 @@ use ledger_device_sdk::ui::gadgets::Field; use crate::{ - parsing::borsh::BorshDeserialize, io::{Error, ErrorKind, Read, Result}, + parsing::borsh::BorshDeserialize, }; pub enum ElipsisFields<'a> { One([Field<'a>; 1]), @@ -13,7 +13,6 @@ impl<'a> ElipsisFields<'a> { pub fn one(field: Field<'a>) -> Self { ElipsisFields::One([field]) } - } pub struct CappedString { diff --git a/src/utils/types/fmt_buffer.rs b/src/utils/types/fmt_buffer.rs index f9be120..5eb2a66 100644 --- a/src/utils/types/fmt_buffer.rs +++ b/src/utils/types/fmt_buffer.rs @@ -5,7 +5,6 @@ pub struct FmtBuffer { } impl FmtBuffer { - pub fn new() -> Self { FmtBuffer { buffer: [0u8; N], @@ -23,11 +22,10 @@ impl FmtBuffer { #[allow(unused)] pub fn truncated(&self) -> bool { self.truncated - } } -// NOTE: doing formatting with +// NOTE: doing formatting with // impl core::fmt::Write for FmtBuffer { // doesn't work due to app crashes in speculos and hangs of app on device ) // potentially similar issue: https://github.com/rust-lang/rust/issues/44538 @@ -55,4 +53,3 @@ impl FmtBuffer { self.used += bytes_written; } } -