Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add swap support #17

Merged
merged 38 commits into from
Feb 17, 2025
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
d39b1ad
swap impl first steps
Fingolfin69 Dec 25, 2024
31a78b4
swap fix bugs
Fingolfin69 Dec 30, 2024
1ef2c6a
fix fmt
Fingolfin69 Dec 30, 2024
c29f9c4
swap signing works
Fingolfin69 Jan 1, 2025
20c4eb6
Update swap params parsing
Fingolfin69 Jan 9, 2025
7d9ec2d
Support fee validation for swap
Fingolfin69 Jan 9, 2025
4704510
Refactor extend parser const generic, refactor run mode
Fingolfin69 Jan 9, 2025
10281bf
Handle panic/usb quirkcs
Fingolfin69 Jan 9, 2025
8af40f3
Enable release lto, update features
Fingolfin69 Jan 9, 2025
9d4cba0
Clean up
Fingolfin69 Jan 10, 2025
abf9a8c
Refactor, get rid of global state
Fingolfin69 Jan 11, 2025
b059542
Use rust-sdk get_params*
Fingolfin69 Jan 12, 2025
d022f77
Add `TxParamsAccessor`
Fingolfin69 Jan 12, 2025
6aa60a6
Fix naming
Fingolfin69 Jan 12, 2025
3b4f3f7
Fixes after rebase, initial support stax, flex targets
Fingolfin69 Jan 12, 2025
d407f45
Fix swap exit condition on stax,flex targets
Fingolfin69 Jan 12, 2025
5231f93
Rework panic, error handling
Fingolfin69 Jan 12, 2025
730148b
Fixup
Fingolfin69 Jan 12, 2025
dcb2c7f
Update docs
Fingolfin69 Jan 12, 2025
cc5075f
Merge branch 'develop' into bn-add-swap-support
Fingolfin69 Feb 3, 2025
7916ea4
Bump sdk deps
Fingolfin69 Feb 3, 2025
a80734a
Update test snapshots due to adding watermark in sdk
Fingolfin69 Feb 4, 2025
56a0104
Bump app version, update CHANGELOG
Fingolfin69 Feb 4, 2025
f72b22f
Update test snapshots
Fingolfin69 Feb 4, 2025
51eb1f9
Add lib flag
Fingolfin69 Feb 5, 2025
cfd0f36
Add swap CI
Fingolfin69 Feb 5, 2025
3b3a76b
Trigger CI
Fingolfin69 Feb 5, 2025
b374d4a
Set branch for exchange in swap workflow
Fingolfin69 Feb 5, 2025
8d3a518
Set repo for exchange in swap workflow
Fingolfin69 Feb 5, 2025
6c38869
Trigger CI
Fingolfin69 Feb 5, 2025
3b7bfb4
Trigger CI
Fingolfin69 Feb 5, 2025
57df32f
Trigger CI
Fingolfin69 Feb 5, 2025
a219599
Use fork enforcer workflow
Fingolfin69 Feb 5, 2025
3c3f037
Bump SDK versions
Fingolfin69 Feb 10, 2025
03085c7
Revert "Use fork enforcer workflow"
Fingolfin69 Feb 10, 2025
cefd793
Trigger CI
Fingolfin69 Feb 10, 2025
0293e1d
Trigger CI
Fingolfin69 Feb 10, 2025
56790c7
Use original swap test workflow
Fingolfin69 Feb 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Change Log

## 0.2.4
* Add swap support
* Bump SDK version

## 0.2.1

* Update SDK
Expand Down
1 change: 1 addition & 0 deletions docs/apdu.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,5 @@ Sign a Transaction, using the key for the given derivation path
| 0x6D00 | `SW_ERROR` | Error has occured due to bad input or user rejectected |
| 0x6E00 | `SW_CLA_OR_INS_NOT_SUPPORTED` | No command exists for the `CLA` and `INS` |
| 0x6E01 | `SW_BAD_LEN` | Length mismatch in inputs |
| 0x6E05 | `SW_SWAP_TX_PARAM_MISMATCH` | Swap transaction parameters check failed |
| 0x9000 | `SW_OK` | Success, or continue if more input from client is expected |
Binary file modified ragger-tests/snapshots/flex/test_app_mainmenu/00002.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified ragger-tests/snapshots/flex/test_sign_tx_blind_sign_1/00000.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified ragger-tests/snapshots/nanosp/test_app_mainmenu/00001.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified ragger-tests/snapshots/nanox/test_app_mainmenu/00001.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified ragger-tests/snapshots/stax/test_app_mainmenu/00002.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified ragger-tests/snapshots/stax/test_sign_tx_blind_sign_1/00000.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 20 additions & 6 deletions rust-app/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 8 additions & 5 deletions rust-app/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "sui"
version = "0.2.3"
version = "0.2.4"
authors = ["Obsidian Systems"]
edition = "2018"
autobins = false
Expand All @@ -17,25 +17,27 @@ num_enum = { version = "0.5", default-features = false }
pin-cell = "0.2.0"
pin-project = "1.0.10"
include_gif = "1.0.1"
hex = { version = "0.4.3", default-features = false }
defer = "0.2.1"

# Pass --features speculos,ledger-log/log_info (or log_trace, etc) to enable
# speculos logging and change log level.
[features]
default = [ ]
# Pass --features speculos,ledger-log/log_info (or log_trace, etc) to enable speculos logging and change log level.
speculos = [ "ledger_device_sdk/speculos", "ledger-log/speculos", "ledger-log/log_error", "ledger-parser-combinators/logging" ]
speculos = [ "ledger_device_sdk/debug", "ledger_device_sdk/speculos", "ledger-log/speculos", "ledger-log/log_error", "ledger-parser-combinators/logging" ]
extra_debug = ["ledger-log/log_trace"]
pending_review_screen = []

[target.'cfg(target_family = "bolos")'.dependencies]
ledger_device_sdk = "1.19.5"
ledger_secure_sdk_sys = "1.6.2"
ledger_device_sdk = "1.20.1"
ledger_secure_sdk_sys = "1.6.4"

[target.'cfg(any(target_os = "nanosplus", target_os = "nanox"))'.dependencies]
ledger-prompts-ui = { git = "https://github.com/alamgu/ledger-prompts-ui" }

[target.'cfg(target_family = "bolos")'.dev-dependencies.ledger_device_sdk]
version = "1.19.5"
version = "1.20.1"
features = [ "speculos" ]

[[bin]]
Expand All @@ -52,6 +54,7 @@ overflow-checks = false
[profile.release]
opt-level = 3
overflow-checks = false
lto = "fat"

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("nanos", "flex", "stax"))'] }
Expand Down
31 changes: 28 additions & 3 deletions rust-app/bin-src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,34 @@ use sui::main_nanos::*;
#[cfg(any(target_os = "stax", target_os = "flex"))]
use sui::main_stax::*;

ledger_device_sdk::set_panic!(ledger_device_sdk::exiting_panic);
use sui::{
ctx::RunCtx,
swap::{lib_main, panic_handler::get_swap_panic_handler},
};

pub fn custom_panic(info: &PanicInfo) -> ! {
use ledger_device_sdk::io;

if let Some(swap_panic_handler) = get_swap_panic_handler() {
// This handler is no-return
swap_panic_handler(info);
}

ledger_log::error!("Panic happened! {:#?}", info);

let mut comm = io::Comm::new();
comm.reply(io::StatusWords::Panic);

ledger_secure_sdk_sys::exit_app(0);
}

ledger_device_sdk::set_panic!(custom_panic);

#[no_mangle]
extern "C" fn sample_main() {
app_main()
extern "C" fn sample_main(arg0: u32) {
if arg0 == 0 {
app_main(&RunCtx::app());
} else {
lib_main(arg0);
}
}
66 changes: 66 additions & 0 deletions rust-app/src/ctx.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use core::cell::Cell;

use crate::swap::params::TxParams;

#[derive(Clone, Copy)]
#[repr(u8)]
pub enum State {
App = 0x00,
LibSwapIdle,
LibSwapSignSuccess,
LibSwapSignFailure,
}

pub struct RunCtx {
state: Cell<State>,
tx_params: TxParams,
}

impl RunCtx {
pub fn app() -> Self {
RunCtx {
state: Cell::new(State::App),
tx_params: TxParams::default(),
}
}

pub fn lib_swap(tx_params: TxParams) -> Self {
RunCtx {
state: Cell::new(State::LibSwapIdle),
tx_params,
}
}

pub fn is_swap(&self) -> bool {
!matches!(self.state.get(), State::App)
}

pub fn is_swap_finished(&self) -> bool {
matches!(
self.state.get(),
State::LibSwapSignSuccess | State::LibSwapSignFailure,
)
}

pub fn is_swap_sign_succeeded(&self) -> bool {
matches!(self.state.get(), State::LibSwapSignSuccess)
}

pub fn set_swap_sign_success(&self) {
if self.is_swap() {
self.state.set(State::LibSwapSignSuccess);
}
}

pub fn set_swap_sign_failure(&self) {
if self.is_swap() {
self.state.set(State::LibSwapSignFailure);
}
}

// Panics if not in swap mode
pub fn get_swap_tx_params(&self) -> &TxParams {
assert!(self.is_swap(), "attempt to get swap tx params in app mode");
&self.tx_params
}
}
7 changes: 5 additions & 2 deletions rust-app/src/handle_apdu.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::ctx::RunCtx;
use crate::implementation::*;
use crate::interface::*;
use crate::settings::*;
Expand All @@ -9,12 +10,13 @@ use arrayvec::ArrayVec;
use core::future::Future;
use ledger_log::trace;

pub type APDUsFuture = impl Future<Output = ()>;
pub type APDUsFuture<'ctx> = impl Future<Output = ()> + 'ctx;

#[inline(never)]
pub fn handle_apdu_async(
io: HostIO,
ins: Ins,
ctx: &RunCtx,
settings: Settings,
ui: UserInterface,
) -> APDUsFuture {
Expand All @@ -39,9 +41,10 @@ pub fn handle_apdu_async(
}
Ins::Sign => {
trace!("Handling sign");
NoinlineFut(sign_apdu(io, settings, ui)).await;
NoinlineFut(sign_apdu(io, ctx, settings, ui)).await;
}
Ins::GetVersionStr => {}
Ins::Exit if ctx.is_swap() => unsafe { ledger_secure_sdk_sys::os_lib_end() },
Ins::Exit => ledger_device_sdk::exit_app(0),
}
}
Expand Down
63 changes: 52 additions & 11 deletions rust-app/src/implementation.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use crate::ctx::RunCtx;
use crate::interface::*;
use crate::settings::*;
use crate::swap;
use crate::swap::params::TxParams;
use crate::ui::*;
use crate::utils::*;
use alamgu_async_block::*;
Expand Down Expand Up @@ -627,7 +630,38 @@ const fn tx_parser<BS: Clone + Readable>(
Action((intent_parser(), TransactionData), |(_, d)| Some(d))
}

pub async fn sign_apdu(io: HostIO, settings: Settings, ui: UserInterface) {
async fn prompt_tx_params(
ui: &UserInterface,
path: &[u32],
TxParams {
amount,
fee,
destination_address,
}: TxParams,
) {
if with_public_keys(path, true, |_, address: &SuiPubKeyAddress| {
try_option(ui.confirm_sign_tx(address, destination_address, amount, fee))
})
.ok()
.is_none()
{
reject::<()>(StatusWords::UserCancelled as u16).await;
};
}
async fn check_tx_params(expected: &TxParams, received: &TxParams) {
if !swap::check_tx_params(expected, received) {
reject::<()>(SW_SWAP_TX_PARAM_MISMATCH).await;
}
}

pub async fn sign_apdu(io: HostIO, ctx: &RunCtx, settings: Settings, ui: UserInterface) {
let _on_failure = defer::defer(|| {
// In case of a swap, we need to communicate that signing failed
if ctx.is_swap() && !ctx.is_swap_sign_succeeded() {
ctx.set_swap_sign_failure();
}
});

let mut input = match io.get_params::<2>() {
Some(v) => v,
None => reject(SyscallError::InvalidParameter as u16).await,
Expand Down Expand Up @@ -655,16 +689,20 @@ pub async fn sign_apdu(io: HostIO, settings: Settings, ui: UserInterface) {
reject::<()>(SyscallError::InvalidParameter as u16).await;
}

// Show prompts after all inputs have been parsed
if with_public_keys(&path, true, |_, address: &SuiPubKeyAddress| {
try_option(ui.confirm_sign_tx(address, recipient, total_amount, gas_budget))
})
.ok()
.is_none()
{
reject::<()>(StatusWords::UserCancelled as u16).await;
let tx_params = TxParams {
amount: total_amount,
fee: gas_budget,
destination_address: recipient,
};
} else if !settings.get_blind_sign() {

if ctx.is_swap() {
let expected = ctx.get_swap_tx_params();
check_tx_params(expected, &tx_params).await;
} else {
// Show prompts after all inputs have been parsed
prompt_tx_params(&ui, path.as_slice(), tx_params).await;
}
} else if !settings.get_blind_sign() || ctx.is_swap() {
ui.warn_tx_not_recognized();
reject::<()>(SyscallError::NotSupported as u16).await;
}
Expand Down Expand Up @@ -701,5 +739,8 @@ pub async fn sign_apdu(io: HostIO, settings: Settings, ui: UserInterface) {
reject::<()>(SyscallError::Unspecified as u16).await;
}
})
.await
.await;

// Does nothing if not a swap mode
ctx.set_swap_sign_success();
}
12 changes: 12 additions & 0 deletions rust-app/src/interface.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
use core::convert::TryFrom;
use core::marker::ConstParamTy;
use ledger_device_sdk::io::{ApduHeader, StatusWords};
use ledger_parser_combinators::bcs::async_parser::*;
use ledger_parser_combinators::core_parsers::*;
use ledger_parser_combinators::endianness::*;
use num_enum::TryFromPrimitive;

#[derive(ConstParamTy, PartialEq, Eq)]
#[repr(u8)]
pub enum ParseChecks {
None,
PromptUser,
CheckSwapTx,
}

// Payload for a public key request
pub type Bip32Key = DArray<Byte, U32<{ Endianness::Little }>, 10>;

Expand Down Expand Up @@ -134,3 +143,6 @@ impl TryFrom<ApduHeader> for Ins {
}
}
}

// Status word used when swap transaction parameters check failed
pub const SW_SWAP_TX_PARAM_MISMATCH: u16 = 0x6e05;
Loading
Loading