Skip to content

Commit

Permalink
Merge pull request #58 from LedgerHQ/feat/heap
Browse files Browse the repository at this point in the history
Use of heap feature for simpler code
  • Loading branch information
agrojean-ledger authored Jun 12, 2024
2 parents 57d01bd + 6589826 commit 755ef1b
Show file tree
Hide file tree
Showing 14 changed files with 81 additions and 117 deletions.
2 changes: 1 addition & 1 deletion .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ runner = "speculos -a=1 --model=nanosp"
target = "nanosplus"

[unstable]
build-std = ["core"]
build-std = ["core", "alloc"]
build-std-features = ["compiler-builtins-mem"]
42 changes: 33 additions & 9 deletions Cargo.lock

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

11 changes: 4 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
[package]
name = "app-boilerplate-rust"
version = "1.3.0"
version = "1.4.0"
authors = ["yhql", "agrojean-ledger"]
edition = "2021"

[dependencies]
ledger_device_sdk = "1.9.2"
ledger_device_sdk = { version="1.10.1", features = ["heap"] }
include_gif = "1.1.0"
serde = {version="1.0.192", default_features = false, features = ["derive"]}
serde-json-core = { git = "https://github.com/rust-embedded-community/serde-json-core"}
hex = { version = "0.4.3", default-features = false, features = ["serde"] }
hex = { version = "0.4.3", default-features = false, features = ["serde", "alloc"] }
numtoa = "0.2.4"

[profile.release]
Expand All @@ -26,9 +26,6 @@ flags = "0"
path = ["44'/1'"]
name = "Rust Boilerplate"

[package.metadata.ledger.nanos]
icon = "crab.gif"

[package.metadata.ledger.nanox]
icon = "crab_14x14.gif"

Expand All @@ -39,4 +36,4 @@ icon = "crab_14x14.gif"
icon = "crab_32x32.gif"

[package.metadata.ledger.flex]
icon = "crab_40x40.gif"
icon = "crab_40x40.gif"
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

![Rule enforcer](https://github.com/LedgerHQ/app-boilerplate-rust/actions/workflows/guidelines_enforcer.yml/badge.svg) ![Build and tests](https://github.com/LedgerHQ/app-boilerplate-rust/actions/workflows/build_and_functional_tests.yml/badge.svg)

This is a boilerplate application written in Rust which can be forked to start a new project for the Ledger Nano S/X/SP, Stax and Flex devices.
This is a boilerplate application written in Rust which can be forked to start a new project for the Ledger Nano X/SP, Stax and Flex devices.

:warning: Nano S is not supported

* Implements standard features (display address, transaction signature...),
* Has functional tests using [Ragger](https://github.com/LedgerHQ/ragger),
Expand Down Expand Up @@ -82,7 +84,7 @@ Now that you have followed the [prerequisites](#prerequisites) guide, you can bu
cargo ledger build nanox
```

This command will build the app for the Nano X, but you can use any supported device (`nanos`, `nanox`, `nanosplus`)
This command will build the app for the Nano X, but you can use any supported device (`nanox`, `nanosplus`, `stax`, `flex`)

### Loading

Expand All @@ -94,7 +96,7 @@ This command will build the app for the Nano X, but you can use any supported de
cargo ledger build nanox --load
```

As for the build command, you can replace `nanos` with `nanox` or `nanosplus`.
As for the build command, you can replace `nanox` with `nanosplus`, `stax` or `flex`.

## Test

Expand All @@ -111,7 +113,7 @@ pip install -r tests/requirements.txt
* Run the functional tests :

```shell
pytest tests/ --tb=short -v --device {nanos | nanosp | nanox}
pytest tests/ --tb=short -v --device {nanosp | nanox | stax | flex}
```

### Emulator
Expand Down
2 changes: 1 addition & 1 deletion ledger_app.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[app]
build_directory = "./"
sdk = "Rust"
devices = ["nanos", "nanox", "nanos+", "stax", "flex"]
devices = ["nanox", "nanos+", "stax", "flex"]

[tests]
pytest_directory = "./tests/"
19 changes: 7 additions & 12 deletions src/app_ui/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*****************************************************************************/

use crate::AppSW;
use core::str::from_utf8_mut;
use alloc::format;

#[cfg(not(any(target_os = "stax", target_os = "flex")))]
use ledger_device_sdk::ui::{
Expand All @@ -34,21 +34,16 @@ use include_gif::include_gif;
const DISPLAY_ADDR_BYTES_LEN: usize = 20;

pub fn ui_display_pk(addr: &[u8]) -> Result<bool, AppSW> {
let mut addr_hex = [0u8; DISPLAY_ADDR_BYTES_LEN * 2 + 2];
addr_hex[..2].copy_from_slice("0x".as_bytes());
hex::encode_to_slice(
&addr[addr.len() - DISPLAY_ADDR_BYTES_LEN..],
&mut addr_hex[2..],
)
.unwrap();
let addr_hex = from_utf8_mut(&mut addr_hex).unwrap();
addr_hex[2..].make_ascii_uppercase();
let addr_hex = format!(
"0x{}",
hex::encode(&addr[addr.len() - DISPLAY_ADDR_BYTES_LEN..]).to_uppercase()
);

#[cfg(not(any(target_os = "stax", target_os = "flex")))]
{
let my_field = [Field {
name: "Address",
value: addr_hex,
value: addr_hex.as_str(),
}];

let my_review = MultiFieldReview::new(
Expand All @@ -72,6 +67,6 @@ pub fn ui_display_pk(addr: &[u8]) -> Result<bool, AppSW> {
Ok(NbglAddressReview::new()
.glyph(&FERRIS)
.verify_str("Verify CRAB address")
.show(addr_hex))
.show(&addr_hex))
}
}
26 changes: 5 additions & 21 deletions src/app_ui/sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
* limitations under the License.
*****************************************************************************/
use crate::handlers::sign_tx::Tx;
use crate::utils::concatenate;
use crate::AppSW;

#[cfg(not(any(target_os = "stax", target_os = "flex")))]
Expand All @@ -31,9 +30,7 @@ use include_gif::include_gif;
#[cfg(any(target_os = "stax", target_os = "flex"))]
use ledger_device_sdk::nbgl::{Field, NbglGlyph, NbglReview};

use numtoa::NumToA;

const MAX_COIN_LENGTH: usize = 10;
use alloc::format;

/// Displays a transaction and returns true if user approved it.
///
Expand All @@ -43,31 +40,18 @@ const MAX_COIN_LENGTH: usize = 10;
///
/// * `tx` - Transaction to be displayed for validation
pub fn ui_display_tx(tx: &Tx) -> Result<bool, AppSW> {
// Generate string for amount
let mut numtoa_buf = [0u8; 20];
let mut value_buf = [0u8; 20 + MAX_COIN_LENGTH + 1];

let value_str = concatenate(
&[tx.coin, " ", tx.value.numtoa_str(10, &mut numtoa_buf)],
&mut value_buf,
)
.map_err(|_| AppSW::TxDisplayFail)?; // Fails if value_buf is too small

// Generate destination address string in hexadecimal format.
let mut to_str = [0u8; 42];
to_str[..2].copy_from_slice("0x".as_bytes());
hex::encode_to_slice(tx.to, &mut to_str[2..]).unwrap();
to_str[2..].make_ascii_uppercase();
let value_str = format!("{} {}", tx.coin, tx.value);
let to_str = format!("0x{}", hex::encode(tx.to).to_uppercase());

// Define transaction review fields
let my_fields = [
Field {
name: "Amount",
value: value_str,
value: value_str.as_str(),
},
Field {
name: "Destination",
value: core::str::from_utf8(&to_str).unwrap(),
value: to_str.as_str(),
},
Field {
name: "Memo",
Expand Down
20 changes: 8 additions & 12 deletions src/handlers/sign_tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use crate::app_ui::sign::ui_display_tx;
use crate::utils::Bip32Path;
use crate::AppSW;
use alloc::vec::Vec;
use ledger_device_sdk::ecc::{Secp256k1, SeedDerive};
use ledger_device_sdk::hash::{sha3::Keccak256, HashInit};
use ledger_device_sdk::io::Comm;
Expand All @@ -38,24 +39,21 @@ pub struct Tx<'a> {
}

pub struct TxContext {
raw_tx: [u8; MAX_TRANSACTION_LEN], // raw transaction serialized
raw_tx_len: usize, // length of raw transaction
raw_tx: Vec<u8>,
path: Bip32Path,
}

// Implement constructor for TxInfo with default values
impl TxContext {
pub fn new() -> TxContext {
TxContext {
raw_tx: [0u8; MAX_TRANSACTION_LEN],
raw_tx_len: 0,
raw_tx: Vec::new(),
path: Default::default(),
}
}
// Implement reset for TxInfo
fn reset(&mut self) {
self.raw_tx = [0u8; MAX_TRANSACTION_LEN];
self.raw_tx_len = 0;
self.raw_tx.clear();
self.path = Default::default();
}
}
Expand All @@ -78,22 +76,20 @@ pub fn handler_sign_tx(
// Next chunks, append data to raw_tx and return or parse
// the transaction if it is the last chunk.
} else {
if ctx.raw_tx_len + data.len() > MAX_TRANSACTION_LEN {
if ctx.raw_tx.len() + data.len() > MAX_TRANSACTION_LEN {
return Err(AppSW::TxWrongLength);
}

// Append data to raw_tx
ctx.raw_tx[ctx.raw_tx_len..ctx.raw_tx_len + data.len()].copy_from_slice(data);
ctx.raw_tx_len += data.len();
ctx.raw_tx.extend(data);

// If we expect more chunks, return
if more {
Ok(())
// Otherwise, try to parse the transaction
} else {
// Try to deserialize the transaction
let (tx, _): (Tx, usize) =
from_slice(&ctx.raw_tx[..ctx.raw_tx_len]).map_err(|_| AppSW::TxParsingFail)?;
let (tx, _): (Tx, usize) = from_slice(&ctx.raw_tx).map_err(|_| AppSW::TxParsingFail)?;
// Display transaction. If user approves
// the transaction, sign it. Otherwise,
// return a "deny" status word.
Expand All @@ -110,7 +106,7 @@ fn compute_signature_and_append(comm: &mut Comm, ctx: &mut TxContext) -> Result<
let mut keccak256 = Keccak256::new();
let mut message_hash: [u8; 32] = [0u8; 32];

let _ = keccak256.hash(&ctx.raw_tx[..ctx.raw_tx_len], &mut message_hash);
let _ = keccak256.hash(&ctx.raw_tx, &mut message_hash);

let (sig, siglen, parity) = Secp256k1::derive_from_path(ctx.path.as_ref())
.deterministic_sign(&message_hash)
Expand Down
5 changes: 4 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,12 @@ use ledger_device_sdk::io::{ApduHeader, Comm, Event, Reply, StatusWords};
#[cfg(feature = "pending_review_screen")]
#[cfg(not(any(target_os = "stax", target_os = "flex")))]
use ledger_device_sdk::ui::gadgets::display_pending_review;
#[cfg(not(any(target_os = "stax", target_os = "flex")))]

ledger_device_sdk::set_panic!(ledger_device_sdk::exiting_panic);

// Required for using String, Vec, format!...
extern crate alloc;

#[cfg(any(target_os = "stax", target_os = "flex"))]
use ledger_device_sdk::nbgl::init_comm;

Expand Down
Loading

0 comments on commit 755ef1b

Please sign in to comment.