From 756366419f560b2d41b3bd1f8da79820feb56bbd Mon Sep 17 00:00:00 2001 From: GroM Date: Wed, 16 Oct 2024 16:54:09 +0200 Subject: [PATCH 01/30] Add swap CI workflow --- .github/workflows/swap_ci_workflow.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/workflows/swap_ci_workflow.yml diff --git a/.github/workflows/swap_ci_workflow.yml b/.github/workflows/swap_ci_workflow.yml new file mode 100644 index 0000000..3384162 --- /dev/null +++ b/.github/workflows/swap_ci_workflow.yml @@ -0,0 +1,18 @@ +name: Swap functional tests + +on: + workflow_dispatch: + push: + branches: + - master + - main + - develop + pull_request: + +jobs: + job_functional_tests: + uses: LedgerHQ/app-exchange/.github/workflows/reusable_swap_functional_tests.yml@swap-near + with: + branch_for_near: ${{ github.ref }} + test_filter: '"NEAR or near or Near"' + branch_for_exchange: 'swap-near' \ No newline at end of file From 55ee04fbc0d846f2a8889fa70fc0e48f68f36d28 Mon Sep 17 00:00:00 2001 From: GroM Date: Tue, 22 Oct 2024 06:31:54 +0200 Subject: [PATCH 02/30] check_address: first implementation --- Cargo.lock | 13 +++++++------ Cargo.toml | 8 +++++++- src/main.rs | 38 +++++++++++++++++++++++++++++++++++++- 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 49bc6b3..695a8f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "adler" @@ -315,8 +315,6 @@ dependencies = [ [[package]] name = "include_gif" version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8511434ad4b61bf0be7c61707d0172b6ad091519da93bf95d66555f3f0d994ac" dependencies = [ "flate2", "image", @@ -367,9 +365,7 @@ dependencies = [ [[package]] name = "ledger_secure_sdk_sys" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dae67d1f69230aa9798ddf94b8fc0b6a21f3ea7206db813b9c12aa2f783fd396" +version = "1.6.0" dependencies = [ "bindgen", "cc", @@ -454,6 +450,7 @@ dependencies = [ "hex", "include_gif", "ledger_device_sdk", + "ledger_secure_sdk_sys", "near_gas", "near_token", "numtoa", @@ -835,3 +832,7 @@ checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" dependencies = [ "simd-adler32", ] + +[[patch.unused]] +name = "ledger_device_sdk" +version = "1.19.0" diff --git a/Cargo.toml b/Cargo.toml index 80e7f81..d8ea5c3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,8 @@ authors = ["dj8yf0μl", "polyprogrammist"] edition = "2021" [dependencies] -ledger_device_sdk = "1.17.5" +ledger_device_sdk = "1.17.4" +ledger_secure_sdk_sys = { version = "1.5.1", features = ["heap"]} include_gif = "1.2.0" hex = { version = "0.4.3", default-features = false, features = ["serde"] } bs58 = { version = "0.5.0", default-features = false } @@ -44,3 +45,8 @@ icon = "icons/app_near_40px.gif" [features] default = [] speculos = ["ledger_device_sdk/speculos"] + +[patch.crates-io] +ledger_device_sdk = { path = "../ledger-device-rust-sdk/ledger_device_sdk" } +ledger_secure_sdk_sys = { path = "../ledger-device-rust-sdk/ledger_secure_sdk_sys" } +include_gif = { path = "../ledger-device-rust-sdk/include_gif" } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 1742706..4afea1e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -239,7 +239,43 @@ impl TryFrom for Instruction { use ledger_device_sdk::nbgl::init_comm; #[no_mangle] -extern "C" fn sample_main() { +extern "C" fn sample_main(arg0: u32) { + if arg0 != 0 { + ledger_device_sdk::testing::debug_print("call app as a lib\n"); + + let cmd = ledger_device_sdk::libcall::get_command(arg0); + + match cmd { + ledger_device_sdk::libcall::LibCallCommand::CheckAddress => { + let _params = ledger_device_sdk::libcall::get_check_address_params(arg0); + // let check_address_params = parsing::types::base58_buf::Base58Buf::from_slice( + // params.ref_address, + // params.ref_address.len(), + // ); + // let path = utils::crypto::path::PathBip32::from_bytes(¶ms.dpath); + // let check_address_params = parsing::CheckAddressParams { + // path, + // check_address_params, + // }; + // let result = handlers::common::validate_public_key::handler(check_address_params); + // ledger_secure_sdk_sys::os_lib_end(); + // if result { + // ledger_secure_sdk_sys::exit_app(0); + // } else { + // ledger_secure_sdk_sys::exit_app(1); + // } + } + _ => { + ledger_device_sdk::testing::debug_print("Unknown command\n"); + } + } + unsafe { + ledger_secure_sdk_sys::os_lib_end(); + } + } + + ledger_device_sdk::testing::debug_print("call app-near as a standalone\n"); + let mut comm = Comm::new(); #[cfg(any(target_os = "stax", target_os = "flex"))] From 0940392bae67170e0e2446c0fac885c312b1b894 Mon Sep 17 00:00:00 2001 From: GroM Date: Thu, 5 Dec 2024 17:05:25 +0100 Subject: [PATCH 03/30] check_address and get_printable_amount OK --- Cargo.lock | 8 +---- Cargo.toml | 4 +-- src/main.rs | 102 ++++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 87 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 695a8f0..84a4f54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -350,9 +350,7 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "ledger_device_sdk" -version = "1.17.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626eae22265c909eaa40d67db1817d7a79e980990da2ce6fbd5259f4cd685147" +version = "1.19.0" dependencies = [ "const-zero", "include_gif", @@ -832,7 +830,3 @@ checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" dependencies = [ "simd-adler32", ] - -[[patch.unused]] -name = "ledger_device_sdk" -version = "1.19.0" diff --git a/Cargo.toml b/Cargo.toml index d8ea5c3..48cfb8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,8 +5,8 @@ authors = ["dj8yf0μl", "polyprogrammist"] edition = "2021" [dependencies] -ledger_device_sdk = "1.17.4" -ledger_secure_sdk_sys = { version = "1.5.1", features = ["heap"]} +ledger_device_sdk = "1.18.4" +ledger_secure_sdk_sys = { version = "1.5.3", features = ["heap"]} include_gif = "1.2.0" hex = { version = "0.4.3", default-features = false, features = ["serde"] } bs58 = { version = "0.5.0", default-features = false } diff --git a/src/main.rs b/src/main.rs index 4afea1e..9ae3dcd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -121,9 +121,12 @@ use app_ui::menu::ui_menu_main; use handlers::{ get_public_key, get_version, get_wallet_id, sign_nep366_delegate, sign_nep413_msg, sign_tx, }; -use ledger_device_sdk::io::{ApduHeader, Comm, Event, Reply, StatusWords}; #[cfg(feature = "speculos")] use ledger_device_sdk::testing; +use ledger_device_sdk::{ + io::{ApduHeader, Comm, Event, Reply, StatusWords}, + testing::debug_print, +}; use parsing::SingleTxStream; ledger_device_sdk::set_panic!(ledger_device_sdk::exiting_panic); @@ -241,29 +244,92 @@ use ledger_device_sdk::nbgl::init_comm; #[no_mangle] extern "C" fn sample_main(arg0: u32) { if arg0 != 0 { + use crate::utils::types::base58_buf::Base58Buf; + use fmt_buffer::Buffer; + use near_token::{NearToken, TokenBuffer}; + ledger_device_sdk::testing::debug_print("call app as a lib\n"); let cmd = ledger_device_sdk::libcall::get_command(arg0); match cmd { ledger_device_sdk::libcall::LibCallCommand::CheckAddress => { - let _params = ledger_device_sdk::libcall::get_check_address_params(arg0); - // let check_address_params = parsing::types::base58_buf::Base58Buf::from_slice( - // params.ref_address, - // params.ref_address.len(), - // ); - // let path = utils::crypto::path::PathBip32::from_bytes(¶ms.dpath); - // let check_address_params = parsing::CheckAddressParams { - // path, - // check_address_params, - // }; - // let result = handlers::common::validate_public_key::handler(check_address_params); - // ledger_secure_sdk_sys::os_lib_end(); - // if result { - // ledger_secure_sdk_sys::exit_app(0); - // } else { - // ledger_secure_sdk_sys::exit_app(1); - // } + let mut params = ledger_device_sdk::libcall::get_check_address_params(arg0); + + let path = + match utils::crypto::PathBip32::parse(¶ms.dpath[..params.dpath_len * 4]) { + Ok(path) => path, + Err(_) => { + debug_print("Derivation path failure\n"); + unsafe { + *(params.result) = 0i32; + ledger_secure_sdk_sys::os_lib_end(); + } + } + }; + + let pk = match ledger_device_sdk::ecc::Ed25519::derive_from_path_slip10(&path.0) + .public_key() + { + Ok(pk) => pk, + Err(_) => { + debug_print("Public key derivation failure\n"); + unsafe { + *(params.result) = 0i32; + ledger_secure_sdk_sys::os_lib_end(); + } + } + }; + + let pk = utils::crypto::PublicKeyBe::from_little_endian(pk); + + let mut bs58_buf: Base58Buf<50> = Base58Buf::new(); + match bs58_buf.encode(&pk.0) { + Ok(_) => { + debug_print("PK base58 encoding ok\n"); + } + Err(_) => { + debug_print("PK base58 encoding failure\n"); + unsafe { + *(params.result) = 0i32; + ledger_secure_sdk_sys::os_lib_end(); + } + } + } + + if bs58_buf.as_str().eq(core::str::from_utf8( + ¶ms.ref_address[..params.ref_address_len], + ) + .unwrap()) + { + unsafe { + debug_print("set result OK\n"); + *(params.result) = 1i32; + } + } else { + unsafe { + debug_print("set result KO\n"); + *(params.result) = 0i32; + } + } + } + ledger_device_sdk::libcall::LibCallCommand::GetPrintableAmount => { + let params = ledger_device_sdk::libcall::get_printable_amount_params(arg0); + + let amount = u128::from_be_bytes(params.amount); + let near_token = NearToken::from_yoctonear(amount); + let mut near_token_buffer = TokenBuffer::new(); + near_token.display_as_buffer(&mut near_token_buffer); + + let s = near_token_buffer.as_str(); + + unsafe { + debug_print("set amount_str\n"); + for (i, c) in s.chars().enumerate() { + *(params.amount_str.add(i)) = c as i8; + } + *(params.amount_str.add(s.len())) = '\0' as i8; + } } _ => { ledger_device_sdk::testing::debug_print("Unknown command\n"); From f4cd890f988f360c5765c13f40092cc3fa53167b Mon Sep 17 00:00:00 2001 From: GroM Date: Thu, 5 Dec 2024 17:47:21 +0100 Subject: [PATCH 04/30] Handle swap module from SDK --- src/main.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index 9ae3dcd..6a04b33 100644 --- a/src/main.rs +++ b/src/main.rs @@ -245,7 +245,6 @@ use ledger_device_sdk::nbgl::init_comm; extern "C" fn sample_main(arg0: u32) { if arg0 != 0 { use crate::utils::types::base58_buf::Base58Buf; - use fmt_buffer::Buffer; use near_token::{NearToken, TokenBuffer}; ledger_device_sdk::testing::debug_print("call app as a lib\n"); @@ -253,8 +252,8 @@ extern "C" fn sample_main(arg0: u32) { let cmd = ledger_device_sdk::libcall::get_command(arg0); match cmd { - ledger_device_sdk::libcall::LibCallCommand::CheckAddress => { - let mut params = ledger_device_sdk::libcall::get_check_address_params(arg0); + ledger_device_sdk::libcall::LibCallCommand::SwapCheckAddress => { + let params = ledger_device_sdk::libcall::swap::get_check_address_params(arg0); let path = match utils::crypto::PathBip32::parse(¶ms.dpath[..params.dpath_len * 4]) { @@ -313,8 +312,8 @@ extern "C" fn sample_main(arg0: u32) { } } } - ledger_device_sdk::libcall::LibCallCommand::GetPrintableAmount => { - let params = ledger_device_sdk::libcall::get_printable_amount_params(arg0); + ledger_device_sdk::libcall::LibCallCommand::SwapGetPrintableAmount => { + let params = ledger_device_sdk::libcall::swap::get_printable_amount_params(arg0); let amount = u128::from_be_bytes(params.amount); let near_token = NearToken::from_yoctonear(amount); From dd16dc46e7279df29fa12a288c61d09851c7b971 Mon Sep 17 00:00:00 2001 From: GroM Date: Tue, 10 Dec 2024 11:31:40 +0100 Subject: [PATCH 05/30] Signing Tx: get params from exchange app and returns always OK --- src/main.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 6a04b33..0f73468 100644 --- a/src/main.rs +++ b/src/main.rs @@ -330,8 +330,23 @@ extern "C" fn sample_main(arg0: u32) { *(params.amount_str.add(s.len())) = '\0' as i8; } } - _ => { - ledger_device_sdk::testing::debug_print("Unknown command\n"); + ledger_device_sdk::libcall::LibCallCommand::SwapSignTransaction => { + let params = ledger_device_sdk::libcall::swap::sign_tx_params(arg0); + + { + let mut comm = Comm::new().set_expected_cla(CLA); + + debug_print("Wait for APDU\n"); + + // Wait for an APDU command + //let ins = comm.next_command(); + //let _ = handle_apdu(&mut comm, ins); + } + + unsafe { + debug_print("set result OK\n"); + *(params.result) = 1u8; + } } } unsafe { From fdc6f9eb07dee1b7726e18806e17fa8efccb0241 Mon Sep 17 00:00:00 2001 From: GroM Date: Thu, 12 Dec 2024 16:27:53 +0100 Subject: [PATCH 06/30] Swap complete --- src/handlers/common/action/transfer.rs | 2 + src/handlers/common/finalize_sign.rs | 11 ++- src/handlers/sign_tx.rs | 93 ++++++++++++++++++++++++++ src/main.rs | 67 ++++++++++++++++--- 4 files changed, 163 insertions(+), 10 deletions(-) diff --git a/src/handlers/common/action/transfer.rs b/src/handlers/common/action/transfer.rs index e3c6b5e..0a29fc5 100644 --- a/src/handlers/common/action/transfer.rs +++ b/src/handlers/common/action/transfer.rs @@ -13,6 +13,8 @@ pub fn handle( ) -> Result<(), AppSW> { let transfer = Transfer::deserialize_reader(stream).map_err(|_err| AppSW::TxParsingFail)?; + ledger_device_sdk::testing::debug_print("displaying transfer info\n"); + if !sign_ui::action::ui_display_transfer(&transfer, params) { return Err(AppSW::Deny); } diff --git a/src/handlers/common/finalize_sign.rs b/src/handlers/common/finalize_sign.rs index 275af26..1badea9 100644 --- a/src/handlers/common/finalize_sign.rs +++ b/src/handlers/common/finalize_sign.rs @@ -14,15 +14,24 @@ pub fn end( ) -> Result { // test no redundant bytes left in stream let mut buf = [0u8; 1]; + ledger_device_sdk::testing::debug_print("finalize signing\n"); match stream.read_exact(&mut buf) { Err(f) if f.kind() == ErrorKind::UnexpectedEof => { // ok } - _ => return Err(AppSW::TxParsingFail), + _ => { + return { + ledger_device_sdk::testing::debug_print("finalize signing failed\n"); + Err(AppSW::TxParsingFail) + } + } } let digest = stream.finalize()?; let private_key = Ed25519::derive_from_path_slip10(&path.0); + + ledger_device_sdk::testing::debug_print("sign Tx \n"); + let (sig, _len) = private_key.sign(&digest.0).map_err(|_| AppSW::TxSignFail)?; Ok(Signature(sig)) diff --git a/src/handlers/sign_tx.rs b/src/handlers/sign_tx.rs index e4670f4..6a01e8c 100644 --- a/src/handlers/sign_tx.rs +++ b/src/handlers/sign_tx.rs @@ -77,3 +77,96 @@ pub fn handler(mut stream: SingleTxStream<'_>) -> Result { finalize_sign::end(stream, &path) } + +use ledger_device_sdk::libcall::swap::CreateTxParams; + +pub fn handler_swap( + mut stream: SingleTxStream<'_>, + tx_params: &CreateTxParams, +) -> Result { + ledger_device_sdk::testing::debug_print("sign_tx.rs: handler_swap()\n"); + + let path = ::deserialize_reader(&mut stream) + .map_err(|_| AppSW::Bip32PathParsingFail)?; + + ledger_device_sdk::testing::debug_print("sign_tx.rs: path computed\n"); + + let mut stream = HashingStream::new(stream)?; + + ledger_device_sdk::testing::debug_print("sign_tx.rs: hashing stream instantiated\n"); + + let mut tx_prefix = parsing::types::transaction::prefix::Prefix::new(); + + tx_prefix + .deserialize_reader_in_place(&mut stream) + .map_err(|_err| AppSW::TxParsingFail)?; + + let tx_public_key = match PublicKeyBe::try_from(tx_prefix.public_key) { + Ok(tx_public_key) => tx_public_key, + Err(_) => return Err(AppSW::PublicKeyMismatch), + }; + + let matching_private_key = { + let pk = ledger_device_sdk::ecc::Ed25519::derive_from_path_slip10(&path.0) + .public_key() + .map_err(|_| AppSW::KeyDeriveFail)?; + PublicKeyBe::from_little_endian(pk) + }; + + if tx_public_key != matching_private_key { + return Err(AppSW::PublicKeyMismatch); + } + + match tx_prefix.number_of_actions { + 1 => { + let action = crate::parsing::types::Action::deserialize_reader(&mut stream) + .map_err(|_err| AppSW::TxParsingFail)?; + + match action { + crate::parsing::types::Action::Transfer => { + let transfer = crate::parsing::types::Transfer::deserialize_reader(&mut stream) + .map_err(|_err| AppSW::TxParsingFail)?; + + let amount_match = near_token::NearToken::from_yoctonear(u128::from_be_bytes( + tx_params.amount, + )) == transfer.deposit; + + if !amount_match { + ledger_device_sdk::testing::debug_print( + "sign_tx.rs: amounts do not not match\n", + ); + return Err(AppSW::TxSignFail); + } + + let dest_address_match = tx_prefix.receiver_id.as_str() + == core::str::from_utf8( + tx_params.dest_address[..tx_params.dest_address_len].as_ref(), + ) + .unwrap(); + + if !dest_address_match { + ledger_device_sdk::testing::debug_print( + "sign_tx.rs: receiver_id does not match with dest_address\n", + ); + ledger_device_sdk::testing::debug_print("Tx dest address: "); + ledger_device_sdk::testing::debug_print(tx_prefix.receiver_id.as_str()); + ledger_device_sdk::testing::debug_print("\n"); + ledger_device_sdk::testing::debug_print("Exchange dest address: "); + ledger_device_sdk::testing::debug_print( + core::str::from_utf8( + tx_params.dest_address[..tx_params.dest_address_len].as_ref(), + ) + .unwrap(), + ); + ledger_device_sdk::testing::debug_print("\n"); + return Err(AppSW::TxSignFail); + } + + finalize_sign::end(stream, &path) + } + _ => return Err(AppSW::TxSignFail), + } + } + _ => return Err(AppSW::TxSignFail), + } +} diff --git a/src/main.rs b/src/main.rs index 0f73468..c230346 100644 --- a/src/main.rs +++ b/src/main.rs @@ -125,6 +125,7 @@ use handlers::{ use ledger_device_sdk::testing; use ledger_device_sdk::{ io::{ApduHeader, Comm, Event, Reply, StatusWords}, + libcall::swap::CreateTxParams, testing::debug_print, }; use parsing::SingleTxStream; @@ -304,11 +305,13 @@ extern "C" fn sample_main(arg0: u32) { unsafe { debug_print("set result OK\n"); *(params.result) = 1i32; + ledger_secure_sdk_sys::os_lib_end(); } } else { unsafe { debug_print("set result KO\n"); *(params.result) = 0i32; + ledger_secure_sdk_sys::os_lib_end(); } } } @@ -328,6 +331,7 @@ extern "C" fn sample_main(arg0: u32) { *(params.amount_str.add(i)) = c as i8; } *(params.amount_str.add(s.len())) = '\0' as i8; + ledger_secure_sdk_sys::os_lib_end(); } } ledger_device_sdk::libcall::LibCallCommand::SwapSignTransaction => { @@ -339,19 +343,36 @@ extern "C" fn sample_main(arg0: u32) { debug_print("Wait for APDU\n"); // Wait for an APDU command - //let ins = comm.next_command(); - //let _ = handle_apdu(&mut comm, ins); - } + let ins: Instruction = comm.next_command(); - unsafe { - debug_print("set result OK\n"); - *(params.result) = 1u8; + debug_print("APDU received\n"); + + match handle_swap_apdu(&mut comm, ins, ¶ms) { + Ok(sig) => { + debug_print("send back signature APDU\n"); + comm.append(&sig); + comm.swap_reply_ok(); + unsafe { + debug_print("set result OK\n"); + *(params.result) = 1u8; + ledger_secure_sdk_sys::os_lib_end(); + } + } + Err(sw) => { + comm.swap_reply(sw); + unsafe { + debug_print("set result KO\n"); + *(params.result) = 0u8; + ledger_secure_sdk_sys::os_lib_end(); + } + } + } } } } - unsafe { - ledger_secure_sdk_sys::os_lib_end(); - } + // unsafe { + // ledger_secure_sdk_sys::os_lib_end(); + // } } ledger_device_sdk::testing::debug_print("call app-near as a standalone\n"); @@ -382,6 +403,7 @@ fn handle_apdu(comm: &mut Comm, ins: Instruction) -> Result<(), AppSW> { is_last_chunk, sign_mode, } => { + ledger_device_sdk::testing::debug_print("handle_apdu => Sign Tx\n"); let stream = SingleTxStream::new(comm, is_last_chunk, sign_mode); let signature = match sign_mode { SignMode::Transaction => sign_tx::handler(stream)?, @@ -393,3 +415,30 @@ fn handle_apdu(comm: &mut Comm, ins: Instruction) -> Result<(), AppSW> { } } } + +fn handle_swap_apdu( + comm: &mut Comm, + ins: Instruction, + tx_params: &CreateTxParams, +) -> Result<[u8; 64], AppSW> { + match ins { + Instruction::SignTx { + is_last_chunk, + sign_mode, + } => { + ledger_device_sdk::testing::debug_print("handle_swap_apdu => Sign Tx\n"); + let stream = SingleTxStream::new(comm, is_last_chunk, sign_mode); + match sign_mode { + SignMode::Transaction => { + let signature = sign_tx::handler_swap(stream, tx_params); + match signature { + Ok(sig) => Ok(sig.0), + Err(sw) => return Err(sw), + } + } + _ => Err(AppSW::TxSignFail), + } + } + _ => Err(AppSW::InsNotSupported), + } +} From aaa9988f2eba010c630171126c3dacf567ad2ee9 Mon Sep 17 00:00:00 2001 From: GroM Date: Thu, 12 Dec 2024 17:07:34 +0100 Subject: [PATCH 07/30] Add debug feature --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index 48cfb8a..8510fb9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,7 @@ icon = "icons/app_near_40px.gif" [features] default = [] +debug = ["ledger_device_sdk/debug"] speculos = ["ledger_device_sdk/speculos"] [patch.crates-io] From b38613dcd083b58931d9837eba8e835f8ff8b0c8 Mon Sep 17 00:00:00 2001 From: GroM Date: Fri, 13 Dec 2024 11:55:54 +0100 Subject: [PATCH 08/30] Add swap module --- src/main.rs | 194 +++++----------------------------------------------- src/swap.rs | 164 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 183 insertions(+), 175 deletions(-) create mode 100644 src/swap.rs diff --git a/src/main.rs b/src/main.rs index c230346..df613af 100644 --- a/src/main.rs +++ b/src/main.rs @@ -121,13 +121,9 @@ use app_ui::menu::ui_menu_main; use handlers::{ get_public_key, get_version, get_wallet_id, sign_nep366_delegate, sign_nep413_msg, sign_tx, }; +use ledger_device_sdk::io::{ApduHeader, Comm, Event, Reply, StatusWords}; #[cfg(feature = "speculos")] use ledger_device_sdk::testing; -use ledger_device_sdk::{ - io::{ApduHeader, Comm, Event, Reply, StatusWords}, - libcall::swap::CreateTxParams, - testing::debug_print, -}; use parsing::SingleTxStream; ledger_device_sdk::set_panic!(ledger_device_sdk::exiting_panic); @@ -242,155 +238,30 @@ impl TryFrom for Instruction { #[cfg(any(target_os = "stax", target_os = "flex"))] use ledger_device_sdk::nbgl::init_comm; +mod swap; + #[no_mangle] extern "C" fn sample_main(arg0: u32) { if arg0 != 0 { - use crate::utils::types::base58_buf::Base58Buf; - use near_token::{NearToken, TokenBuffer}; - - ledger_device_sdk::testing::debug_print("call app as a lib\n"); - - let cmd = ledger_device_sdk::libcall::get_command(arg0); - - match cmd { - ledger_device_sdk::libcall::LibCallCommand::SwapCheckAddress => { - let params = ledger_device_sdk::libcall::swap::get_check_address_params(arg0); - - let path = - match utils::crypto::PathBip32::parse(¶ms.dpath[..params.dpath_len * 4]) { - Ok(path) => path, - Err(_) => { - debug_print("Derivation path failure\n"); - unsafe { - *(params.result) = 0i32; - ledger_secure_sdk_sys::os_lib_end(); - } - } - }; - - let pk = match ledger_device_sdk::ecc::Ed25519::derive_from_path_slip10(&path.0) - .public_key() - { - Ok(pk) => pk, - Err(_) => { - debug_print("Public key derivation failure\n"); - unsafe { - *(params.result) = 0i32; - ledger_secure_sdk_sys::os_lib_end(); - } - } - }; - - let pk = utils::crypto::PublicKeyBe::from_little_endian(pk); - - let mut bs58_buf: Base58Buf<50> = Base58Buf::new(); - match bs58_buf.encode(&pk.0) { - Ok(_) => { - debug_print("PK base58 encoding ok\n"); - } - Err(_) => { - debug_print("PK base58 encoding failure\n"); - unsafe { - *(params.result) = 0i32; - ledger_secure_sdk_sys::os_lib_end(); - } - } - } - - if bs58_buf.as_str().eq(core::str::from_utf8( - ¶ms.ref_address[..params.ref_address_len], - ) - .unwrap()) - { - unsafe { - debug_print("set result OK\n"); - *(params.result) = 1i32; - ledger_secure_sdk_sys::os_lib_end(); - } - } else { - unsafe { - debug_print("set result KO\n"); - *(params.result) = 0i32; - ledger_secure_sdk_sys::os_lib_end(); - } - } - } - ledger_device_sdk::libcall::LibCallCommand::SwapGetPrintableAmount => { - let params = ledger_device_sdk::libcall::swap::get_printable_amount_params(arg0); - - let amount = u128::from_be_bytes(params.amount); - let near_token = NearToken::from_yoctonear(amount); - let mut near_token_buffer = TokenBuffer::new(); - near_token.display_as_buffer(&mut near_token_buffer); - - let s = near_token_buffer.as_str(); - - unsafe { - debug_print("set amount_str\n"); - for (i, c) in s.chars().enumerate() { - *(params.amount_str.add(i)) = c as i8; - } - *(params.amount_str.add(s.len())) = '\0' as i8; - ledger_secure_sdk_sys::os_lib_end(); - } - } - ledger_device_sdk::libcall::LibCallCommand::SwapSignTransaction => { - let params = ledger_device_sdk::libcall::swap::sign_tx_params(arg0); - - { - let mut comm = Comm::new().set_expected_cla(CLA); - - debug_print("Wait for APDU\n"); - - // Wait for an APDU command - let ins: Instruction = comm.next_command(); - - debug_print("APDU received\n"); - - match handle_swap_apdu(&mut comm, ins, ¶ms) { - Ok(sig) => { - debug_print("send back signature APDU\n"); - comm.append(&sig); - comm.swap_reply_ok(); - unsafe { - debug_print("set result OK\n"); - *(params.result) = 1u8; - ledger_secure_sdk_sys::os_lib_end(); - } - } - Err(sw) => { - comm.swap_reply(sw); - unsafe { - debug_print("set result KO\n"); - *(params.result) = 0u8; - ledger_secure_sdk_sys::os_lib_end(); - } - } - } + swap::swap_main(arg0); + } else { + ledger_device_sdk::testing::debug_print("call app-near as a standalone\n"); + + let mut comm = Comm::new(); + + #[cfg(any(target_os = "stax", target_os = "flex"))] + init_comm(&mut comm); + + loop { + // Wait for either a specific button push to exit the app + // or an APDU command + if let Event::Command(ins) = ui_menu_main(&mut comm) { + match handle_apdu(&mut comm, ins) { + Ok(()) => comm.reply_ok(), + Err(sw) => comm.reply(sw), } } } - // unsafe { - // ledger_secure_sdk_sys::os_lib_end(); - // } - } - - ledger_device_sdk::testing::debug_print("call app-near as a standalone\n"); - - let mut comm = Comm::new(); - - #[cfg(any(target_os = "stax", target_os = "flex"))] - init_comm(&mut comm); - - loop { - // Wait for either a specific button push to exit the app - // or an APDU command - if let Event::Command(ins) = ui_menu_main(&mut comm) { - match handle_apdu(&mut comm, ins) { - Ok(()) => comm.reply_ok(), - Err(sw) => comm.reply(sw), - } - } } } @@ -415,30 +286,3 @@ fn handle_apdu(comm: &mut Comm, ins: Instruction) -> Result<(), AppSW> { } } } - -fn handle_swap_apdu( - comm: &mut Comm, - ins: Instruction, - tx_params: &CreateTxParams, -) -> Result<[u8; 64], AppSW> { - match ins { - Instruction::SignTx { - is_last_chunk, - sign_mode, - } => { - ledger_device_sdk::testing::debug_print("handle_swap_apdu => Sign Tx\n"); - let stream = SingleTxStream::new(comm, is_last_chunk, sign_mode); - match sign_mode { - SignMode::Transaction => { - let signature = sign_tx::handler_swap(stream, tx_params); - match signature { - Ok(sig) => Ok(sig.0), - Err(sw) => return Err(sw), - } - } - _ => Err(AppSW::TxSignFail), - } - } - _ => Err(AppSW::InsNotSupported), - } -} diff --git a/src/swap.rs b/src/swap.rs new file mode 100644 index 0000000..0efc345 --- /dev/null +++ b/src/swap.rs @@ -0,0 +1,164 @@ +use crate::utils::{ + crypto::{PathBip32, PublicKeyBe}, + types::base58_buf::Base58Buf, +}; +use near_token::{NearToken, TokenBuffer}; + +use ledger_device_sdk::{ + ecc, + io::Comm, + libcall::{self, swap, swap::CreateTxParams}, + testing::debug_print, +}; + +use crate::parsing::transaction_stream_reader::SingleTxStream; + +pub fn swap_main(arg0: u32) { + debug_print("call app for swap \n"); + + let cmd = libcall::get_command(arg0); + + match cmd { + libcall::LibCallCommand::SwapCheckAddress => { + let mut params = swap::get_check_address_params(arg0); + + let mut res = 0i32; + match PathBip32::parse(¶ms.dpath[..params.dpath_len * 4]) { + Ok(path) => match ecc::Ed25519::derive_from_path_slip10(&path.0).public_key() { + Ok(pk) => { + let pk = PublicKeyBe::from_little_endian(pk); + let mut bs58_buf: Base58Buf<50> = Base58Buf::new(); + match bs58_buf.encode(&pk.0) { + Ok(_) => { + if bs58_buf.as_str().eq(core::str::from_utf8( + ¶ms.ref_address[..params.ref_address_len], + ) + .unwrap()) + { + res = 1i32; + } + } + Err(_) => { + debug_print("PK base58 encoding failure\n"); + } + } + } + Err(_) => { + debug_print("Public key derivation failure\n"); + } + }, + Err(_) => { + debug_print("Derivation path failure\n"); + } + } + swap::swap_return(swap::SwapResult::CheckAddressResult(&mut params, res)); + + // let path = + // match crate::utils::crypto::PathBip32::parse(¶ms.dpath[..params.dpath_len * 4]) + // { + // Ok(path) => path, + // Err(_) => { + // debug_print("Derivation path failure\n"); + // swap::swap_return(swap::SwapResult::CheckAddressResult(&mut params, 0i32)); + // PathBip32 { 0: [0; 5] } + // } + // }; + + // let pk = match ecc::Ed25519::derive_from_path_slip10(&path.0).public_key() { + // Ok(pk) => pk, + // Err(_) => { + // debug_print("Public key derivation failure\n"); + // swap::swap_return(swap::SwapResult::CheckAddressResult(&mut params, 0i32)); + // ECPublicKey::<65, 'E'>::new(ecc::CurvesId::Ed25519) + // } + // }; + + // let pk = crate::utils::crypto::PublicKeyBe::from_little_endian(pk); + + // let mut bs58_buf: Base58Buf<50> = Base58Buf::new(); + // match bs58_buf.encode(&pk.0) { + // Ok(_) => { + // debug_print("PK base58 encoding ok\n"); + // } + // Err(_) => { + // debug_print("PK base58 encoding failure\n"); + // swap::swap_return(swap::SwapResult::CheckAddressResult(&mut params, 0i32)); + // } + // } + + // if bs58_buf + // .as_str() + // .eq(core::str::from_utf8(¶ms.ref_address[..params.ref_address_len]).unwrap()) + // { + // swap::swap_return(swap::SwapResult::CheckAddressResult(&mut params, 1i32)); + // } else { + // swap::swap_return(swap::SwapResult::CheckAddressResult(&mut params, 0i32)); + // } + } + libcall::LibCallCommand::SwapGetPrintableAmount => { + let mut params = swap::get_printable_amount_params(arg0); + + let amount = u128::from_be_bytes(params.amount); + let near_token = NearToken::from_yoctonear(amount); + let mut near_token_buffer = TokenBuffer::new(); + near_token.display_as_buffer(&mut near_token_buffer); + let s = near_token_buffer.as_str(); + + swap::swap_return(swap::SwapResult::PrintableAmountResult(&mut params, s)); + } + libcall::LibCallCommand::SwapSignTransaction => { + let mut params = swap::sign_tx_params(arg0); + + { + let mut comm = Comm::new().set_expected_cla(super::CLA); + + debug_print("Wait for APDU\n"); + + // Wait for an APDU command + let ins: super::Instruction = comm.next_command(); + + debug_print("APDU received\n"); + + match handle_apdu(&mut comm, ins, ¶ms) { + Ok(sig) => { + debug_print("send back signature APDU\n"); + comm.append(&sig); + comm.swap_reply_ok(); + swap::swap_return(swap::SwapResult::CreateTxResult(&mut params, 1)); + } + Err(sw) => { + comm.swap_reply(sw); + swap::swap_return(swap::SwapResult::CreateTxResult(&mut params, 0)); + } + } + } + } + } +} + +fn handle_apdu( + comm: &mut Comm, + ins: super::Instruction, + tx_params: &CreateTxParams, +) -> Result<[u8; 64], crate::AppSW> { + match ins { + super::Instruction::SignTx { + is_last_chunk, + sign_mode, + } => { + debug_print("handle_swap_apdu => Sign Tx\n"); + let stream = SingleTxStream::new(comm, is_last_chunk, sign_mode); + match sign_mode { + super::SignMode::Transaction => { + let signature = crate::handlers::sign_tx::handler_swap(stream, tx_params); + match signature { + Ok(sig) => Ok(sig.0), + Err(sw) => return Err(sw), + } + } + _ => Err(crate::AppSW::TxSignFail), + } + } + _ => Err(crate::AppSW::InsNotSupported), + } +} From adff200647b486f93ca38df9a8d9e11f7f10a466 Mon Sep 17 00:00:00 2001 From: GroM Date: Fri, 13 Dec 2024 15:50:52 +0100 Subject: [PATCH 09/30] remove comments --- src/swap.rs | 42 ------------------------------------------ 1 file changed, 42 deletions(-) diff --git a/src/swap.rs b/src/swap.rs index 0efc345..38008c2 100644 --- a/src/swap.rs +++ b/src/swap.rs @@ -52,48 +52,6 @@ pub fn swap_main(arg0: u32) { } } swap::swap_return(swap::SwapResult::CheckAddressResult(&mut params, res)); - - // let path = - // match crate::utils::crypto::PathBip32::parse(¶ms.dpath[..params.dpath_len * 4]) - // { - // Ok(path) => path, - // Err(_) => { - // debug_print("Derivation path failure\n"); - // swap::swap_return(swap::SwapResult::CheckAddressResult(&mut params, 0i32)); - // PathBip32 { 0: [0; 5] } - // } - // }; - - // let pk = match ecc::Ed25519::derive_from_path_slip10(&path.0).public_key() { - // Ok(pk) => pk, - // Err(_) => { - // debug_print("Public key derivation failure\n"); - // swap::swap_return(swap::SwapResult::CheckAddressResult(&mut params, 0i32)); - // ECPublicKey::<65, 'E'>::new(ecc::CurvesId::Ed25519) - // } - // }; - - // let pk = crate::utils::crypto::PublicKeyBe::from_little_endian(pk); - - // let mut bs58_buf: Base58Buf<50> = Base58Buf::new(); - // match bs58_buf.encode(&pk.0) { - // Ok(_) => { - // debug_print("PK base58 encoding ok\n"); - // } - // Err(_) => { - // debug_print("PK base58 encoding failure\n"); - // swap::swap_return(swap::SwapResult::CheckAddressResult(&mut params, 0i32)); - // } - // } - - // if bs58_buf - // .as_str() - // .eq(core::str::from_utf8(¶ms.ref_address[..params.ref_address_len]).unwrap()) - // { - // swap::swap_return(swap::SwapResult::CheckAddressResult(&mut params, 1i32)); - // } else { - // swap::swap_return(swap::SwapResult::CheckAddressResult(&mut params, 0i32)); - // } } libcall::LibCallCommand::SwapGetPrintableAmount => { let mut params = swap::get_printable_amount_params(arg0); From 2dc1aa70ec9f2b238f889491ba39b730b94c079b Mon Sep 17 00:00:00 2001 From: GroM Date: Fri, 13 Dec 2024 15:57:17 +0100 Subject: [PATCH 10/30] Remove traces --- src/handlers/common/action/transfer.rs | 2 -- src/handlers/common/finalize_sign.rs | 11 +---------- src/main.rs | 1 - 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/src/handlers/common/action/transfer.rs b/src/handlers/common/action/transfer.rs index 0a29fc5..e3c6b5e 100644 --- a/src/handlers/common/action/transfer.rs +++ b/src/handlers/common/action/transfer.rs @@ -13,8 +13,6 @@ pub fn handle( ) -> Result<(), AppSW> { let transfer = Transfer::deserialize_reader(stream).map_err(|_err| AppSW::TxParsingFail)?; - ledger_device_sdk::testing::debug_print("displaying transfer info\n"); - if !sign_ui::action::ui_display_transfer(&transfer, params) { return Err(AppSW::Deny); } diff --git a/src/handlers/common/finalize_sign.rs b/src/handlers/common/finalize_sign.rs index 1badea9..275af26 100644 --- a/src/handlers/common/finalize_sign.rs +++ b/src/handlers/common/finalize_sign.rs @@ -14,24 +14,15 @@ pub fn end( ) -> Result { // test no redundant bytes left in stream let mut buf = [0u8; 1]; - ledger_device_sdk::testing::debug_print("finalize signing\n"); match stream.read_exact(&mut buf) { Err(f) if f.kind() == ErrorKind::UnexpectedEof => { // ok } - _ => { - return { - ledger_device_sdk::testing::debug_print("finalize signing failed\n"); - Err(AppSW::TxParsingFail) - } - } + _ => return Err(AppSW::TxParsingFail), } let digest = stream.finalize()?; let private_key = Ed25519::derive_from_path_slip10(&path.0); - - ledger_device_sdk::testing::debug_print("sign Tx \n"); - let (sig, _len) = private_key.sign(&digest.0).map_err(|_| AppSW::TxSignFail)?; Ok(Signature(sig)) diff --git a/src/main.rs b/src/main.rs index df613af..062002e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -274,7 +274,6 @@ fn handle_apdu(comm: &mut Comm, ins: Instruction) -> Result<(), AppSW> { is_last_chunk, sign_mode, } => { - ledger_device_sdk::testing::debug_print("handle_apdu => Sign Tx\n"); let stream = SingleTxStream::new(comm, is_last_chunk, sign_mode); let signature = match sign_mode { SignMode::Transaction => sign_tx::handler(stream)?, From bbec71409f663eb1f4b144b267eb356372be7dbd Mon Sep 17 00:00:00 2001 From: GroM Date: Fri, 13 Dec 2024 16:02:38 +0100 Subject: [PATCH 11/30] Delete verbose traces --- src/handlers/sign_tx.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/handlers/sign_tx.rs b/src/handlers/sign_tx.rs index 6a01e8c..9ab3787 100644 --- a/src/handlers/sign_tx.rs +++ b/src/handlers/sign_tx.rs @@ -148,17 +148,6 @@ pub fn handler_swap( ledger_device_sdk::testing::debug_print( "sign_tx.rs: receiver_id does not match with dest_address\n", ); - ledger_device_sdk::testing::debug_print("Tx dest address: "); - ledger_device_sdk::testing::debug_print(tx_prefix.receiver_id.as_str()); - ledger_device_sdk::testing::debug_print("\n"); - ledger_device_sdk::testing::debug_print("Exchange dest address: "); - ledger_device_sdk::testing::debug_print( - core::str::from_utf8( - tx_params.dest_address[..tx_params.dest_address_len].as_ref(), - ) - .unwrap(), - ); - ledger_device_sdk::testing::debug_print("\n"); return Err(AppSW::TxSignFail); } From 94b8da984d543984f063c117f63e0ae6bae609b1 Mon Sep 17 00:00:00 2001 From: GroM Date: Mon, 16 Dec 2024 16:37:12 +0100 Subject: [PATCH 12/30] Use last published Rust SDK --- Cargo.lock | 6 ++++++ Cargo.toml | 9 ++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 84a4f54..dfd7277 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -315,6 +315,8 @@ dependencies = [ [[package]] name = "include_gif" version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8511434ad4b61bf0be7c61707d0172b6ad091519da93bf95d66555f3f0d994ac" dependencies = [ "flate2", "image", @@ -351,6 +353,8 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "ledger_device_sdk" version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce8ddbdbd543abc191017a4603c7f9f17a01891654212d3b81f1ba356fb1bf0" dependencies = [ "const-zero", "include_gif", @@ -364,6 +368,8 @@ dependencies = [ [[package]] name = "ledger_secure_sdk_sys" version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cad3662994c734990d2d799546530dae3645fd49aec895b98868e5ba077cccb" dependencies = [ "bindgen", "cc", diff --git a/Cargo.toml b/Cargo.toml index 8510fb9..932c181 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,8 +5,8 @@ authors = ["dj8yf0μl", "polyprogrammist"] edition = "2021" [dependencies] -ledger_device_sdk = "1.18.4" -ledger_secure_sdk_sys = { version = "1.5.3", features = ["heap"]} +ledger_device_sdk = "1.19.0" +ledger_secure_sdk_sys = { version = "1.6.0", features = ["heap"]} include_gif = "1.2.0" hex = { version = "0.4.3", default-features = false, features = ["serde"] } bs58 = { version = "0.5.0", default-features = false } @@ -46,8 +46,3 @@ icon = "icons/app_near_40px.gif" default = [] debug = ["ledger_device_sdk/debug"] speculos = ["ledger_device_sdk/speculos"] - -[patch.crates-io] -ledger_device_sdk = { path = "../ledger-device-rust-sdk/ledger_device_sdk" } -ledger_secure_sdk_sys = { path = "../ledger-device-rust-sdk/ledger_secure_sdk_sys" } -include_gif = { path = "../ledger-device-rust-sdk/include_gif" } \ No newline at end of file From a24605fa9bb9063af8165f68ef482ed9de4a843d Mon Sep 17 00:00:00 2001 From: GroM Date: Mon, 16 Dec 2024 16:48:44 +0100 Subject: [PATCH 13/30] Remove Rust SDK sys crate dependency --- Cargo.lock | 3 +-- Cargo.toml | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dfd7277..c4e9aaf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 4 +version = 3 [[package]] name = "adler" @@ -454,7 +454,6 @@ dependencies = [ "hex", "include_gif", "ledger_device_sdk", - "ledger_secure_sdk_sys", "near_gas", "near_token", "numtoa", diff --git a/Cargo.toml b/Cargo.toml index 932c181..839a205 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,6 @@ edition = "2021" [dependencies] ledger_device_sdk = "1.19.0" -ledger_secure_sdk_sys = { version = "1.6.0", features = ["heap"]} include_gif = "1.2.0" hex = { version = "0.4.3", default-features = false, features = ["serde"] } bs58 = { version = "0.5.0", default-features = false } From e0055a04d2b25d09a17e3df4ec6627749367b41c Mon Sep 17 00:00:00 2001 From: GroM Date: Mon, 16 Dec 2024 17:00:55 +0100 Subject: [PATCH 14/30] Fix Clippy errors --- src/handlers/sign_tx.rs | 4 ++-- src/swap.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/handlers/sign_tx.rs b/src/handlers/sign_tx.rs index 9ab3787..608ecba 100644 --- a/src/handlers/sign_tx.rs +++ b/src/handlers/sign_tx.rs @@ -153,9 +153,9 @@ pub fn handler_swap( finalize_sign::end(stream, &path) } - _ => return Err(AppSW::TxSignFail), + _ => Err(AppSW::TxSignFail), } } - _ => return Err(AppSW::TxSignFail), + _ => Err(AppSW::TxSignFail), } } diff --git a/src/swap.rs b/src/swap.rs index 38008c2..70e4372 100644 --- a/src/swap.rs +++ b/src/swap.rs @@ -111,7 +111,7 @@ fn handle_apdu( let signature = crate::handlers::sign_tx::handler_swap(stream, tx_params); match signature { Ok(sig) => Ok(sig.0), - Err(sw) => return Err(sw), + Err(sw) => Err(sw), } } _ => Err(crate::AppSW::TxSignFail), From e6813717ccaf8e66f19dedd7cc227c8352527207 Mon Sep 17 00:00:00 2001 From: GroM Date: Tue, 17 Dec 2024 09:46:31 +0100 Subject: [PATCH 15/30] Bump version --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c4e9aaf..08badca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -446,7 +446,7 @@ dependencies = [ [[package]] name = "near" -version = "2.2.1" +version = "2.3.0" dependencies = [ "borsh", "bs58", diff --git a/Cargo.toml b/Cargo.toml index 839a205..2394117 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "near" -version = "2.2.1" +version = "2.3.0" authors = ["dj8yf0μl", "polyprogrammist"] edition = "2021" From 3239626f6bbad0e770b218254eb2de4dd7b4e6f3 Mon Sep 17 00:00:00 2001 From: GroM Date: Tue, 17 Dec 2024 09:53:02 +0100 Subject: [PATCH 16/30] Fix test --- tests/test_version_cmd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_version_cmd.py b/tests/test_version_cmd.py index 63383e4..8c426b5 100644 --- a/tests/test_version_cmd.py +++ b/tests/test_version_cmd.py @@ -9,4 +9,4 @@ def test_get_version_cmd(backend): version = client.get_version().data assert len(version) == 3 # Assert that we have received the correct app version compared as Makefile data - assert (version[0], version[1], version[2]) == (2, 2, 1) + assert (version[0], version[1], version[2]) == (2, 3, 0) From d80821db53d3790d15e5d7193f5cedb580f1bfe2 Mon Sep 17 00:00:00 2001 From: GroM Date: Thu, 19 Dec 2024 10:32:01 +0100 Subject: [PATCH 17/30] Update app name to NEAR and set proper appflags (see ledger-secure-sdk/include /appflags.h) --- Cargo.lock | 30 +++++++++++++++--------------- Cargo.toml | 6 +++--- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 08badca..554ed36 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "NEAR" +version = "2.3.1" +dependencies = [ + "borsh", + "bs58", + "fmt_buffer", + "hex", + "include_gif", + "ledger_device_sdk", + "near_gas", + "near_token", + "numtoa", +] + [[package]] name = "adler" version = "1.0.2" @@ -444,21 +459,6 @@ dependencies = [ "simd-adler32", ] -[[package]] -name = "near" -version = "2.3.0" -dependencies = [ - "borsh", - "bs58", - "fmt_buffer", - "hex", - "include_gif", - "ledger_device_sdk", - "near_gas", - "near_token", - "numtoa", -] - [[package]] name = "near_gas" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 2394117..d1b0ac5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "near" -version = "2.3.0" +name = "NEAR" +version = "2.3.1" authors = ["dj8yf0μl", "polyprogrammist"] edition = "2021" @@ -22,7 +22,7 @@ lto = true [package.metadata.ledger] curve = ["ed25519"] -flags = "0" +flags = "800" path = ["44'/397'"] name = "NEAR" From 24c779400ee790403306ac900af085beeb564b15 Mon Sep 17 00:00:00 2001 From: GroM Date: Thu, 19 Dec 2024 10:54:42 +0100 Subject: [PATCH 18/30] Keep package name to near, app name is defined in metadata.ledger --- Cargo.lock | 30 +++++++++++++++--------------- Cargo.toml | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 554ed36..635277f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,21 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "NEAR" -version = "2.3.1" -dependencies = [ - "borsh", - "bs58", - "fmt_buffer", - "hex", - "include_gif", - "ledger_device_sdk", - "near_gas", - "near_token", - "numtoa", -] - [[package]] name = "adler" version = "1.0.2" @@ -459,6 +444,21 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "near" +version = "2.3.1" +dependencies = [ + "borsh", + "bs58", + "fmt_buffer", + "hex", + "include_gif", + "ledger_device_sdk", + "near_gas", + "near_token", + "numtoa", +] + [[package]] name = "near_gas" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index d1b0ac5..9ad554b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "NEAR" +name = "near" version = "2.3.1" authors = ["dj8yf0μl", "polyprogrammist"] edition = "2021" From 5e9113496358cc68718fd8664edfc5d3225e0d33 Mon Sep 17 00:00:00 2001 From: GroM Date: Thu, 19 Dec 2024 11:58:24 +0100 Subject: [PATCH 19/30] Update get version test --- tests/test_version_cmd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_version_cmd.py b/tests/test_version_cmd.py index 8c426b5..40bd822 100644 --- a/tests/test_version_cmd.py +++ b/tests/test_version_cmd.py @@ -9,4 +9,4 @@ def test_get_version_cmd(backend): version = client.get_version().data assert len(version) == 3 # Assert that we have received the correct app version compared as Makefile data - assert (version[0], version[1], version[2]) == (2, 3, 0) + assert (version[0], version[1], version[2]) == (2, 3, 1) From 6f893f1f1dc62a0a1011535476130c1c0c3e07ff Mon Sep 17 00:00:00 2001 From: GroM Date: Fri, 20 Dec 2024 10:12:25 +0100 Subject: [PATCH 20/30] Swap: Check address is in hex (32 bytes) and not in base58 --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/swap.rs | 33 +++++++++++++-------------------- tests/test_version_cmd.py | 2 +- 4 files changed, 16 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 635277f..8a1c687 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -446,7 +446,7 @@ dependencies = [ [[package]] name = "near" -version = "2.3.1" +version = "2.3.2" dependencies = [ "borsh", "bs58", diff --git a/Cargo.toml b/Cargo.toml index 9ad554b..4fea02f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "near" -version = "2.3.1" +version = "2.3.2" authors = ["dj8yf0μl", "polyprogrammist"] edition = "2021" diff --git a/src/swap.rs b/src/swap.rs index 70e4372..2c3bfa9 100644 --- a/src/swap.rs +++ b/src/swap.rs @@ -1,13 +1,13 @@ -use crate::utils::{ - crypto::{PathBip32, PublicKeyBe}, - types::base58_buf::Base58Buf, -}; +use crate::utils::crypto::{PathBip32, PublicKeyBe}; use near_token::{NearToken, TokenBuffer}; use ledger_device_sdk::{ ecc, io::Comm, - libcall::{self, swap, swap::CreateTxParams}, + libcall::{ + self, + swap::{self, CreateTxParams}, + }, testing::debug_print, }; @@ -27,20 +27,14 @@ pub fn swap_main(arg0: u32) { Ok(path) => match ecc::Ed25519::derive_from_path_slip10(&path.0).public_key() { Ok(pk) => { let pk = PublicKeyBe::from_little_endian(pk); - let mut bs58_buf: Base58Buf<50> = Base58Buf::new(); - match bs58_buf.encode(&pk.0) { - Ok(_) => { - if bs58_buf.as_str().eq(core::str::from_utf8( - ¶ms.ref_address[..params.ref_address_len], - ) - .unwrap()) - { - res = 1i32; - } - } - Err(_) => { - debug_print("PK base58 encoding failure\n"); - } + + let mut buf = [0u8; 64]; + let address = pk.display_str_hex(&mut buf); + let ref_address = + core::str::from_utf8(¶ms.ref_address[..params.ref_address_len]); + + if address.eq(ref_address.unwrap()) { + res = 1i32; } } Err(_) => { @@ -79,7 +73,6 @@ pub fn swap_main(arg0: u32) { match handle_apdu(&mut comm, ins, ¶ms) { Ok(sig) => { - debug_print("send back signature APDU\n"); comm.append(&sig); comm.swap_reply_ok(); swap::swap_return(swap::SwapResult::CreateTxResult(&mut params, 1)); diff --git a/tests/test_version_cmd.py b/tests/test_version_cmd.py index 40bd822..983ee5e 100644 --- a/tests/test_version_cmd.py +++ b/tests/test_version_cmd.py @@ -9,4 +9,4 @@ def test_get_version_cmd(backend): version = client.get_version().data assert len(version) == 3 # Assert that we have received the correct app version compared as Makefile data - assert (version[0], version[1], version[2]) == (2, 3, 1) + assert (version[0], version[1], version[2]) == (2, 3, 2) From 9d43b57d809dc33646fe9fe185e2ed79a2c6eb24 Mon Sep 17 00:00:00 2001 From: GroM Date: Fri, 20 Dec 2024 16:27:57 +0100 Subject: [PATCH 21/30] set appflags in hexa --- Cargo.toml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4fea02f..c17797a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,13 +22,10 @@ lto = true [package.metadata.ledger] curve = ["ed25519"] -flags = "800" +flags = "0x800" path = ["44'/397'"] name = "NEAR" -[package.metadata.ledger.nanos] -icon = "icons/app_near_16px.gif" - [package.metadata.ledger.nanox] icon = "icons/app_near_14px.gif" From 0e08ef85fc571344d5097bdd6482dd26f4b25ae8 Mon Sep 17 00:00:00 2001 From: GroM Date: Mon, 6 Jan 2025 16:08:36 +0100 Subject: [PATCH 22/30] Bump SDK version --- Cargo.lock | 10 +++++----- Cargo.toml | 5 ++++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8a1c687..6526bcf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "adler" @@ -352,9 +352,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "ledger_device_sdk" -version = "1.19.0" +version = "1.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce8ddbdbd543abc191017a4603c7f9f17a01891654212d3b81f1ba356fb1bf0" +checksum = "86980cdfca74b94db326557e3c6246c7a7c63331aa2a96f193f826cd04613fd5" dependencies = [ "const-zero", "include_gif", @@ -367,9 +367,9 @@ dependencies = [ [[package]] name = "ledger_secure_sdk_sys" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cad3662994c734990d2d799546530dae3645fd49aec895b98868e5ba077cccb" +checksum = "b046c4ef3859a4e693bd6a49b2e9ee3295d7bf5c3ae7b6bb5cd8b358b1a6cb61" dependencies = [ "bindgen", "cc", diff --git a/Cargo.toml b/Cargo.toml index c17797a..0377a3c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ authors = ["dj8yf0μl", "polyprogrammist"] edition = "2021" [dependencies] -ledger_device_sdk = "1.19.0" +ledger_device_sdk = "1.19.1" include_gif = "1.2.0" hex = { version = "0.4.3", default-features = false, features = ["serde"] } bs58 = { version = "0.5.0", default-features = false } @@ -42,3 +42,6 @@ icon = "icons/app_near_40px.gif" default = [] debug = ["ledger_device_sdk/debug"] speculos = ["ledger_device_sdk/speculos"] + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("stax", "flex", "nanos", "nanox", "nanosplus"))'] } \ No newline at end of file From 71f3cb2c86d55007abda10b3507af07c60f07f1b Mon Sep 17 00:00:00 2001 From: GroM Date: Mon, 6 Jan 2025 16:19:39 +0100 Subject: [PATCH 23/30] Fix Clippy issues --- src/app_ui/fields_writer.rs | 3 --- src/parsing/transaction_stream_reader/mod.rs | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/app_ui/fields_writer.rs b/src/app_ui/fields_writer.rs index b209320..5f0ef12 100644 --- a/src/app_ui/fields_writer.rs +++ b/src/app_ui/fields_writer.rs @@ -15,9 +15,6 @@ pub struct FieldsWriter<'a, const N: usize> { #[cfg(feature = "speculos")] use ledger_device_sdk::testing; -#[derive(Debug)] -pub struct FieldsOverflow; - impl<'a, const N: usize> FieldsWriter<'a, N> { pub fn new() -> Self { let max_fields = [(); N].map(|_| Field { diff --git a/src/parsing/transaction_stream_reader/mod.rs b/src/parsing/transaction_stream_reader/mod.rs index 94f3a27..64b7d0e 100644 --- a/src/parsing/transaction_stream_reader/mod.rs +++ b/src/parsing/transaction_stream_reader/mod.rs @@ -76,7 +76,7 @@ impl io::Read for HashingStream { } } -impl<'a> SingleTxStream<'a> { +impl SingleTxStream<'_> { pub fn peek_u8(&mut self) -> io::Result> { let data = self .comm @@ -132,7 +132,7 @@ impl<'a> SingleTxStream<'a> { } } -impl<'a> io::Read for SingleTxStream<'a> { +impl io::Read for SingleTxStream<'_> { fn read(&mut self, buf: &mut [u8]) -> io::Result { let data = self .comm From 45bed9d8604a5274a3644370ce7be8521b030452 Mon Sep 17 00:00:00 2001 From: GroM Date: Tue, 7 Jan 2025 11:58:54 +0100 Subject: [PATCH 24/30] Process GetPubKey instruction in swap mode --- src/swap.rs | 49 +++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/src/swap.rs b/src/swap.rs index 2c3bfa9..f2061f4 100644 --- a/src/swap.rs +++ b/src/swap.rs @@ -66,32 +66,20 @@ pub fn swap_main(arg0: u32) { debug_print("Wait for APDU\n"); - // Wait for an APDU command - let ins: super::Instruction = comm.next_command(); + loop { + // Wait for an APDU command + let ins: super::Instruction = comm.next_command(); - debug_print("APDU received\n"); + debug_print("APDU received\n"); - match handle_apdu(&mut comm, ins, ¶ms) { - Ok(sig) => { - comm.append(&sig); - comm.swap_reply_ok(); - swap::swap_return(swap::SwapResult::CreateTxResult(&mut params, 1)); - } - Err(sw) => { - comm.swap_reply(sw); - swap::swap_return(swap::SwapResult::CreateTxResult(&mut params, 0)); - } + handle_apdu(&mut comm, ins, &mut params); } } } } } -fn handle_apdu( - comm: &mut Comm, - ins: super::Instruction, - tx_params: &CreateTxParams, -) -> Result<[u8; 64], crate::AppSW> { +fn handle_apdu(comm: &mut Comm, ins: super::Instruction, tx_params: &mut CreateTxParams) { match ins { super::Instruction::SignTx { is_last_chunk, @@ -103,13 +91,30 @@ fn handle_apdu( super::SignMode::Transaction => { let signature = crate::handlers::sign_tx::handler_swap(stream, tx_params); match signature { - Ok(sig) => Ok(sig.0), - Err(sw) => Err(sw), + Ok(sig) => { + comm.append(&sig.0); + comm.swap_reply_ok(); + swap::swap_return(swap::SwapResult::CreateTxResult(tx_params, 1)); + } + Err(sw) => { + comm.swap_reply(sw); + swap::swap_return(swap::SwapResult::CreateTxResult(tx_params, 0)); + } } } - _ => Err(crate::AppSW::TxSignFail), + _ => { + comm.swap_reply(crate::AppSW::TxSignFail); + swap::swap_return(swap::SwapResult::CreateTxResult(tx_params, 0)); + } } } - _ => Err(crate::AppSW::InsNotSupported), + super::Instruction::GetPubkey { display } => match display { + true => comm.swap_reply(crate::AppSW::InsNotSupported), + false => match crate::handlers::get_public_key::handler(comm, display) { + Ok(()) => comm.swap_reply_ok(), + Err(sw) => comm.swap_reply(sw), + }, + }, + _ => comm.swap_reply(crate::AppSW::InsNotSupported), } } From 17571c8025343ebed43421810d68ecdcfecaeb4c Mon Sep 17 00:00:00 2001 From: GroM Date: Tue, 7 Jan 2025 12:11:35 +0100 Subject: [PATCH 25/30] Bump version --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6526bcf..b49706b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -446,7 +446,7 @@ dependencies = [ [[package]] name = "near" -version = "2.3.2" +version = "2.3.3" dependencies = [ "borsh", "bs58", diff --git a/Cargo.toml b/Cargo.toml index 0377a3c..e557dc0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "near" -version = "2.3.2" +version = "2.3.3" authors = ["dj8yf0μl", "polyprogrammist"] edition = "2021" From 3c9bf0a60e90789d7e084527257dc04ea692a2a7 Mon Sep 17 00:00:00 2001 From: GroM Date: Wed, 8 Jan 2025 11:40:54 +0100 Subject: [PATCH 26/30] Update version in version test --- tests/test_version_cmd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_version_cmd.py b/tests/test_version_cmd.py index 983ee5e..d9f8393 100644 --- a/tests/test_version_cmd.py +++ b/tests/test_version_cmd.py @@ -9,4 +9,4 @@ def test_get_version_cmd(backend): version = client.get_version().data assert len(version) == 3 # Assert that we have received the correct app version compared as Makefile data - assert (version[0], version[1], version[2]) == (2, 3, 2) + assert (version[0], version[1], version[2]) == (2, 3, 3) From 1487624bc539d2bdbe00b86c755a737812ceeb4b Mon Sep 17 00:00:00 2001 From: GroM Date: Tue, 14 Jan 2025 15:28:21 +0100 Subject: [PATCH 27/30] Update after PR review --- Cargo.lock | 6 +- Cargo.toml | 4 +- src/handlers/sign_tx.rs | 90 ++++++++++++-------------- src/parsing/types/common/action/mod.rs | 1 + src/swap.rs | 81 +++++++++++++---------- tests/test_version_cmd.py | 9 ++- 6 files changed, 100 insertions(+), 91 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b49706b..96b08e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -352,9 +352,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "ledger_device_sdk" -version = "1.19.1" +version = "1.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86980cdfca74b94db326557e3c6246c7a7c63331aa2a96f193f826cd04613fd5" +checksum = "30342b34b6e011b9fc8dd67bbf29bf321ab47f7f0bd381277ab65445996a9a45" dependencies = [ "const-zero", "include_gif", @@ -446,7 +446,7 @@ dependencies = [ [[package]] name = "near" -version = "2.3.3" +version = "2.3.4" dependencies = [ "borsh", "bs58", diff --git a/Cargo.toml b/Cargo.toml index e557dc0..f4bdbb7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "near" -version = "2.3.3" +version = "2.3.4" authors = ["dj8yf0μl", "polyprogrammist"] edition = "2021" [dependencies] -ledger_device_sdk = "1.19.1" +ledger_device_sdk = "1.19.2" include_gif = "1.2.0" hex = { version = "0.4.3", default-features = false, features = ["serde"] } bs58 = { version = "0.5.0", default-features = false } diff --git a/src/handlers/sign_tx.rs b/src/handlers/sign_tx.rs index 608ecba..3590412 100644 --- a/src/handlers/sign_tx.rs +++ b/src/handlers/sign_tx.rs @@ -80,82 +80,74 @@ pub fn handler(mut stream: SingleTxStream<'_>) -> Result { use ledger_device_sdk::libcall::swap::CreateTxParams; -pub fn handler_swap( +/// Sign handler for the swap transaction +/// This handler is called when the user wants to sign a swap transaction +/// The swap transaction is a transfer transaction with a specific amount and destination address +/// The handler checks the transaction parameters and signs the transaction +pub fn swap_handler( mut stream: SingleTxStream<'_>, tx_params: &CreateTxParams, ) -> Result { - ledger_device_sdk::testing::debug_print("sign_tx.rs: handler_swap()\n"); + ledger_device_sdk::testing::debug_print("sign_tx.rs: swap_handler()\n"); let path = ::deserialize_reader(&mut stream) .map_err(|_| AppSW::Bip32PathParsingFail)?; ledger_device_sdk::testing::debug_print("sign_tx.rs: path computed\n"); + // Get the public key from the transaction let mut stream = HashingStream::new(stream)?; - - ledger_device_sdk::testing::debug_print("sign_tx.rs: hashing stream instantiated\n"); - let mut tx_prefix = parsing::types::transaction::prefix::Prefix::new(); - tx_prefix .deserialize_reader_in_place(&mut stream) .map_err(|_err| AppSW::TxParsingFail)?; - let tx_public_key = match PublicKeyBe::try_from(tx_prefix.public_key) { Ok(tx_public_key) => tx_public_key, Err(_) => return Err(AppSW::PublicKeyMismatch), }; - let matching_private_key = { + // Derive the public key from the path and compare it with the transaction public key + let dpath_public_key = { let pk = ledger_device_sdk::ecc::Ed25519::derive_from_path_slip10(&path.0) .public_key() .map_err(|_| AppSW::KeyDeriveFail)?; PublicKeyBe::from_little_endian(pk) }; - if tx_public_key != matching_private_key { + if tx_public_key != dpath_public_key { return Err(AppSW::PublicKeyMismatch); } - match tx_prefix.number_of_actions { - 1 => { - let action = crate::parsing::types::Action::deserialize_reader(&mut stream) - .map_err(|_err| AppSW::TxParsingFail)?; - - match action { - crate::parsing::types::Action::Transfer => { - let transfer = crate::parsing::types::Transfer::deserialize_reader(&mut stream) - .map_err(|_err| AppSW::TxParsingFail)?; - - let amount_match = near_token::NearToken::from_yoctonear(u128::from_be_bytes( - tx_params.amount, - )) == transfer.deposit; - - if !amount_match { - ledger_device_sdk::testing::debug_print( - "sign_tx.rs: amounts do not not match\n", - ); - return Err(AppSW::TxSignFail); - } - - let dest_address_match = tx_prefix.receiver_id.as_str() - == core::str::from_utf8( - tx_params.dest_address[..tx_params.dest_address_len].as_ref(), - ) - .unwrap(); - - if !dest_address_match { - ledger_device_sdk::testing::debug_print( - "sign_tx.rs: receiver_id does not match with dest_address\n", - ); - return Err(AppSW::TxSignFail); - } - - finalize_sign::end(stream, &path) - } - _ => Err(AppSW::TxSignFail), - } - } - _ => Err(AppSW::TxSignFail), + // Check nb of actions (shall be == 1 == Transfer in swap context) + if tx_prefix.number_of_actions != 1 { + return Err(AppSW::TxSignFail); + } + let action = crate::parsing::types::Action::deserialize_reader(&mut stream) + .map_err(|_err| AppSW::TxParsingFail)?; + if action != crate::parsing::types::Action::Transfer { + return Err(AppSW::TxSignFail); + } + + // Check the tx parameters match with the ones previously validated in Exchange app (tx_params) + let transfer = crate::parsing::types::Transfer::deserialize_reader(&mut stream) + .map_err(|_err| AppSW::TxParsingFail)?; + + let amount_match = near_token::NearToken::from_yoctonear(u128::from_be_bytes(tx_params.amount)) + == transfer.deposit; + if !amount_match { + ledger_device_sdk::testing::debug_print("sign_tx.rs: amounts do not not match\n"); + return Err(AppSW::TxSignFail); } + + let dest_address_match = tx_prefix.receiver_id.as_str() + == core::str::from_utf8(tx_params.dest_address[..tx_params.dest_address_len].as_ref()) + .unwrap(); + if !dest_address_match { + ledger_device_sdk::testing::debug_print( + "sign_tx.rs: receiver_id does not match with dest_address\n", + ); + return Err(AppSW::TxSignFail); + } + + finalize_sign::end(stream, &path) } diff --git a/src/parsing/types/common/action/mod.rs b/src/parsing/types/common/action/mod.rs index 3e49b85..3c24bda 100644 --- a/src/parsing/types/common/action/mod.rs +++ b/src/parsing/types/common/action/mod.rs @@ -16,6 +16,7 @@ pub mod function_call; pub mod stake; pub mod transfer; +#[derive(PartialEq)] pub enum Action { CreateAccount, DeployContract, diff --git a/src/swap.rs b/src/swap.rs index f2061f4..e2f7147 100644 --- a/src/swap.rs +++ b/src/swap.rs @@ -1,4 +1,5 @@ use crate::utils::crypto::{PathBip32, PublicKeyBe}; +use fmt_buffer::Buffer; use near_token::{NearToken, TokenBuffer}; use ledger_device_sdk::{ @@ -6,7 +7,7 @@ use ledger_device_sdk::{ io::Comm, libcall::{ self, - swap::{self, CreateTxParams}, + swap::{self, CheckAddressParams, CreateTxParams, PrintableAmountParams}, }, testing::debug_print, }; @@ -21,42 +22,22 @@ pub fn swap_main(arg0: u32) { match cmd { libcall::LibCallCommand::SwapCheckAddress => { let mut params = swap::get_check_address_params(arg0); - - let mut res = 0i32; - match PathBip32::parse(¶ms.dpath[..params.dpath_len * 4]) { - Ok(path) => match ecc::Ed25519::derive_from_path_slip10(&path.0).public_key() { - Ok(pk) => { - let pk = PublicKeyBe::from_little_endian(pk); - - let mut buf = [0u8; 64]; - let address = pk.display_str_hex(&mut buf); - let ref_address = - core::str::from_utf8(¶ms.ref_address[..params.ref_address_len]); - - if address.eq(ref_address.unwrap()) { - res = 1i32; - } - } - Err(_) => { - debug_print("Public key derivation failure\n"); - } - }, - Err(_) => { - debug_print("Derivation path failure\n"); + let res = match check_address(¶ms) { + Ok(_) => 1, + Err(err) => { + debug_print(err); + 0 } - } + }; swap::swap_return(swap::SwapResult::CheckAddressResult(&mut params, res)); } libcall::LibCallCommand::SwapGetPrintableAmount => { let mut params = swap::get_printable_amount_params(arg0); - - let amount = u128::from_be_bytes(params.amount); - let near_token = NearToken::from_yoctonear(amount); - let mut near_token_buffer = TokenBuffer::new(); - near_token.display_as_buffer(&mut near_token_buffer); - let s = near_token_buffer.as_str(); - - swap::swap_return(swap::SwapResult::PrintableAmountResult(&mut params, s)); + let mut s = get_printable_amount(¶ms); + swap::swap_return(swap::SwapResult::PrintableAmountResult( + &mut params, + s.as_str(), + )); } libcall::LibCallCommand::SwapSignTransaction => { let mut params = swap::sign_tx_params(arg0); @@ -72,14 +53,14 @@ pub fn swap_main(arg0: u32) { debug_print("APDU received\n"); - handle_apdu(&mut comm, ins, &mut params); + swap_handle_apdu(&mut comm, ins, &mut params); } } } } } -fn handle_apdu(comm: &mut Comm, ins: super::Instruction, tx_params: &mut CreateTxParams) { +fn swap_handle_apdu(comm: &mut Comm, ins: super::Instruction, tx_params: &mut CreateTxParams) { match ins { super::Instruction::SignTx { is_last_chunk, @@ -89,7 +70,7 @@ fn handle_apdu(comm: &mut Comm, ins: super::Instruction, tx_params: &mut CreateT let stream = SingleTxStream::new(comm, is_last_chunk, sign_mode); match sign_mode { super::SignMode::Transaction => { - let signature = crate::handlers::sign_tx::handler_swap(stream, tx_params); + let signature = crate::handlers::sign_tx::swap_handler(stream, tx_params); match signature { Ok(sig) => { comm.append(&sig.0); @@ -118,3 +99,33 @@ fn handle_apdu(comm: &mut Comm, ins: super::Instruction, tx_params: &mut CreateT _ => comm.swap_reply(crate::AppSW::InsNotSupported), } } + +fn check_address(params: &CheckAddressParams) -> Result<(), &'static str> { + let path = PathBip32::parse(¶ms.dpath[..params.dpath_len * 4]) + .map_err(|_| "Derivation path failure")?; + + let pk = ecc::Ed25519::derive_from_path_slip10(&path.0) + .public_key() + .map_err(|_| "Public key derivation failure")?; + + let pk = PublicKeyBe::from_little_endian(pk); + let mut buf = [0u8; 64]; + let address = pk.display_str_hex(&mut buf); + + let ref_address = core::str::from_utf8(¶ms.ref_address[..params.ref_address_len]) + .map_err(|_| "Invalid UTF-8 in reference address")?; + + if address == ref_address { + Ok(()) + } else { + Err("Address mismatch") + } +} + +fn get_printable_amount(params: &PrintableAmountParams) -> Buffer<30> { + let amount = u128::from_be_bytes(params.amount); + let near_token = NearToken::from_yoctonear(amount); + let mut near_token_buffer = TokenBuffer::new(); + near_token.display_as_buffer(&mut near_token_buffer); + near_token_buffer +} diff --git a/tests/test_version_cmd.py b/tests/test_version_cmd.py index d9f8393..909d146 100644 --- a/tests/test_version_cmd.py +++ b/tests/test_version_cmd.py @@ -1,4 +1,5 @@ from application_client.client import Nearbackend +import toml # In this test we check that the get_version replies the right application version @@ -8,5 +9,9 @@ def test_get_version_cmd(backend): # Send the get_version instruction to the app version = client.get_version().data assert len(version) == 3 - # Assert that we have received the correct app version compared as Makefile data - assert (version[0], version[1], version[2]) == (2, 3, 3) + # Read version from Cargo.toml + with open('Cargo.toml', 'r') as f: + config = toml.load(f) + version = config['package']['version'] + major, minor, patch = version.split('.') + assert (version[0], version[1], version[2]) == (int(major), int(minor), int(patch)) \ No newline at end of file From 1357cd983ed4865c702c91e893bfd57578458981 Mon Sep 17 00:00:00 2001 From: GroM Date: Tue, 14 Jan 2025 15:37:48 +0100 Subject: [PATCH 28/30] Fix get_version test --- tests/test_version_cmd.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_version_cmd.py b/tests/test_version_cmd.py index 909d146..f70cddd 100644 --- a/tests/test_version_cmd.py +++ b/tests/test_version_cmd.py @@ -12,6 +12,6 @@ def test_get_version_cmd(backend): # Read version from Cargo.toml with open('Cargo.toml', 'r') as f: config = toml.load(f) - version = config['package']['version'] - major, minor, patch = version.split('.') - assert (version[0], version[1], version[2]) == (int(major), int(minor), int(patch)) \ No newline at end of file + v = config['package']['version'] + major, minor, patch = v.split('.') + assert (version[0], version[1], version[2]) == (int(major), int(minor), int(patch)) \ No newline at end of file From 0d29b66904fa53834ef5be03c8082c2d02689926 Mon Sep 17 00:00:00 2001 From: GroM Date: Tue, 14 Jan 2025 17:14:33 +0100 Subject: [PATCH 29/30] return constant fees when swapping (sending) Near (0.450 Tgas) --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- src/swap.rs | 21 ++++++++++++++++----- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 96b08e9..ead43a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -352,9 +352,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "ledger_device_sdk" -version = "1.19.2" +version = "1.19.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30342b34b6e011b9fc8dd67bbf29bf321ab47f7f0bd381277ab65445996a9a45" +checksum = "4b814011ef9b769b1baa3ac6e53c0b4b2c6d42312798b5a63aede9de65d8f1e0" dependencies = [ "const-zero", "include_gif", diff --git a/Cargo.toml b/Cargo.toml index f4bdbb7..021139b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ authors = ["dj8yf0μl", "polyprogrammist"] edition = "2021" [dependencies] -ledger_device_sdk = "1.19.2" +ledger_device_sdk = "1.19.3" include_gif = "1.2.0" hex = { version = "0.4.3", default-features = false, features = ["serde"] } bs58 = { version = "0.5.0", default-features = false } diff --git a/src/swap.rs b/src/swap.rs index e2f7147..4bc79dc 100644 --- a/src/swap.rs +++ b/src/swap.rs @@ -1,5 +1,6 @@ use crate::utils::crypto::{PathBip32, PublicKeyBe}; use fmt_buffer::Buffer; +use near_gas::{GasBuffer, NearGas}; use near_token::{NearToken, TokenBuffer}; use ledger_device_sdk::{ @@ -123,9 +124,19 @@ fn check_address(params: &CheckAddressParams) -> Result<(), &'static str> { } fn get_printable_amount(params: &PrintableAmountParams) -> Buffer<30> { - let amount = u128::from_be_bytes(params.amount); - let near_token = NearToken::from_yoctonear(amount); - let mut near_token_buffer = TokenBuffer::new(); - near_token.display_as_buffer(&mut near_token_buffer); - near_token_buffer + match params.is_fee { + true => { + let gas = NearGas::from_gas(450_000_000_000); + let mut near_gas_buffer = GasBuffer::new(); + gas.display_as_buffer(&mut near_gas_buffer); + near_gas_buffer + } + false => { + let amount = u128::from_be_bytes(params.amount); + let near_token = NearToken::from_yoctonear(amount); + let mut near_token_buffer = TokenBuffer::new(); + near_token.display_as_buffer(&mut near_token_buffer); + near_token_buffer + } + } } From 1771c38fee31d83cf90ad3af312e8043b5dddc6b Mon Sep 17 00:00:00 2001 From: GroM Date: Thu, 16 Jan 2025 11:55:43 +0100 Subject: [PATCH 30/30] Bump Rust SDK version --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ead43a2..d8c2d12 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -352,9 +352,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "ledger_device_sdk" -version = "1.19.3" +version = "1.19.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b814011ef9b769b1baa3ac6e53c0b4b2c6d42312798b5a63aede9de65d8f1e0" +checksum = "b70a36808a9688592bc11f852fbd466c371ebe81c1e53c3e6f87404b02c3f202" dependencies = [ "const-zero", "include_gif", diff --git a/Cargo.toml b/Cargo.toml index 021139b..cc9551a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ authors = ["dj8yf0μl", "polyprogrammist"] edition = "2021" [dependencies] -ledger_device_sdk = "1.19.3" +ledger_device_sdk = "1.19.4" include_gif = "1.2.0" hex = { version = "0.4.3", default-features = false, features = ["serde"] } bs58 = { version = "0.5.0", default-features = false }