Skip to content

Commit

Permalink
App size (#146)
Browse files Browse the repository at this point in the history
* avoid indexing to reduce binary size

use try call to avoid panic machinery to be added by the compiler

optimize for binary size and remove debug symbols

* update tests

* bump app version and update snapshots

* Derive Debug only under test

* Remove panic-halt to reduce app size

* Reduce calls to procedures that can cause panics

* Rename LedgerPanic to ApduPanic

* fix format

* use unreachable_unchecked

* some improvements in size

* fix return value

* Update zxlib

* use copy_from_slice and better error report
  • Loading branch information
neithanmo committed Feb 21, 2023
1 parent 2360349 commit 5f40d62
Show file tree
Hide file tree
Showing 32 changed files with 222 additions and 90 deletions.
1 change: 1 addition & 0 deletions app/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ APP_SOURCE_PATH += $(MY_DIR)/src
APP_SOURCE_PATH += $(MY_DIR)/glyphs
APP_SOURCE_PATH += $(MY_DIR)/rust/include
APP_SOURCE_PATH += $(MY_DIR)/../deps/ledger-zxlib/include
APP_SOURCE_PATH += $(MY_DIR)/../deps/ledger-zxlib/app/ui
APP_SOURCE_PATH += $(MY_DIR)/../deps/ledger-zxlib/src
APP_SOURCE_PATH += $(MY_DIR)/../deps/ledger-zxlib/app/common
APP_SOURCE_PATH += $(MY_DIR)/../deps/sha512
Expand Down
2 changes: 1 addition & 1 deletion app/Makefile.version
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
APPVERSION_M=0
APPVERSION_N=23
APPVERSION_P=7
APPVERSION_P=8
7 changes: 0 additions & 7 deletions app/rust/Cargo.lock

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

7 changes: 2 additions & 5 deletions app/rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ default-features = false
version = "0.5.1"
default-features = false

[target.thumbv6m-none-eabi.dev-dependencies]
panic-halt = "0.2.0"

[dev-dependencies]
no-std-compat = { version = "0.4.1", features = ["std"] }
serde_json = "1.0.56"
Expand All @@ -48,8 +45,8 @@ no-std-compat = { version = "0.4.1", features = ["std"] }
[profile.release]
lto=false
codegen-units = 1
debug=true
opt-level = "s"
debug=false
opt-level = "z"

[profile.dev]
panic = "abort"
2 changes: 0 additions & 2 deletions app/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ mod bolos;
pub mod parser;
mod zxformat;

fn debug(_msg: &str) {}

#[cfg(not(any(test, fuzzing)))]
use core::panic::PanicInfo;

Expand Down
38 changes: 28 additions & 10 deletions app/rust/src/parser/c32.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#[cfg(not(any(test, fuzzing)))]
use crate::parser::utils::ApduPanic;
use crate::parser::{
error::ParserError,
parser_common::{C32_ENCODED_ADDRS_LENGTH, HASH160_LEN},
Expand Down Expand Up @@ -64,55 +66,71 @@ fn double_sha256_checksum(data: &mut [u8; SHA256_LEN]) {
fn double_sha256_checksum(data: &mut [u8; SHA256_LEN]) {
let mut output = [0u8; SHA256_LEN];
// safe to unwrap as we are passing the right len
sha256(&data[..21], &mut output[..]).unwrap();
sha256(&data[..21], &mut output[..]).apdu_unwrap();
data.copy_from_slice(output.as_ref());
// safe to unwrap as we are passing the right len
sha256(&data[..], &mut output).unwrap();
data[20..24].copy_from_slice(&output[..4])
sha256(&data[..], &mut output).apdu_unwrap();
let d = data.get_mut(20..24).apdu_unwrap();
let o = output.get(..4).apdu_unwrap();
d.copy_from_slice(o);
}

#[inline(never)]
fn c32_encode(input_bytes: &[u8], result: &mut ArrayVec<[u8; C32_ENCODED_ADDRS_LENGTH]>) {
fn c32_encode(
input_bytes: &[u8],
result: &mut ArrayVec<[u8; C32_ENCODED_ADDRS_LENGTH]>,
) -> Result<(), ParserError> {
let mut carry = 0;
let mut carry_bits = 0;

for current_value in input_bytes.iter().rev() {
let low_bits_to_take = 5 - carry_bits;
let low_bits = current_value & ((1 << low_bits_to_take) - 1);
let c32_value = (low_bits << carry_bits) + carry;
result.push(C32_CHARACTERS[c32_value as usize]);
result
.try_push(C32_CHARACTERS[c32_value as usize])
.map_err(|_| ParserError::parser_unexpected_buffer_end)?;
carry_bits = (8 + carry_bits) - 5;
carry = current_value >> (8 - carry_bits);

if carry_bits >= 5 {
let c32_value = carry & ((1 << 5) - 1);
result.push(C32_CHARACTERS[c32_value as usize]);
result
.try_push(C32_CHARACTERS[c32_value as usize])
.map_err(|_| ParserError::parser_unexpected_buffer_end)?;
carry_bits -= 5;
carry >>= 5;
}
}

if carry_bits > 0 {
result.push(C32_CHARACTERS[carry as usize]);
result
.try_push(C32_CHARACTERS[carry as usize])
.map_err(|_| ParserError::parser_unexpected_buffer_end)?;
}

// remove leading zeros from c32 encoding
while let Some(v) = result.pop() {
if v != C32_CHARACTERS[0] {
result.push(v);
result
.try_push(v)
.map_err(|_| ParserError::parser_unexpected_buffer_end)?;
break;
}
}

// add leading zeros from input.
for current_value in input_bytes.iter() {
if *current_value == 0 {
result.push(C32_CHARACTERS[0]);
result
.try_push(C32_CHARACTERS[0])
.map_err(|_| ParserError::parser_unexpected_buffer_end)?;
} else {
break;
}
}
result.reverse();
Ok(())
}

#[inline(never)]
Expand All @@ -137,7 +155,7 @@ fn c32_check_encode(
check_data[..20].copy_from_slice(data);

// here we use only the 24-bytes
c32_encode(&check_data[..24], c32_string);
c32_encode(&check_data[..24], c32_string)?;
let version_char = C32_CHARACTERS[version as usize];
c32_string.insert(0, version_char);
Ok(())
Expand Down
5 changes: 4 additions & 1 deletion app/rust/src/parser/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,10 @@ impl<'a> ByteString<'a> {
});

let mut copy_len = if self.0.len() > MAX_ASCII_LEN {
msg[MAX_ASCII_LEN..MAX_ASCII_LEN + suffix.len()].copy_from_slice(&suffix[..]);
let m = msg
.get_mut(MAX_ASCII_LEN..MAX_ASCII_LEN + suffix.len())
.ok_or(ParserError::parser_unexpected_buffer_end)?;
m.copy_from_slice(&suffix[..]);
MAX_ASCII_LEN
} else {
self.0.len()
Expand Down
3 changes: 2 additions & 1 deletion app/rust/src/parser/parsed_obj.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use super::{Jwt, StructuredMsg};
use core::mem::ManuallyDrop;

#[repr(u8)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[derive(Copy, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(Debug))]
pub enum Tag {
Transaction,
Message,
Expand Down
24 changes: 16 additions & 8 deletions app/rust/src/parser/parser_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ pub const MAX_DEPTH: u8 = 20;

/// Stacks transaction versions
#[repr(u8)]
#[derive(Debug, Clone, PartialEq, Copy)]
#[derive(Clone, PartialEq, Copy)]
#[cfg_attr(test, derive(Debug))]
pub enum TransactionVersion {
Mainnet = 0x00,
Testnet = 0x80,
Expand Down Expand Up @@ -60,7 +61,8 @@ impl TransactionVersion {
}

#[repr(u8)]
#[derive(Clone, PartialEq, Copy, Debug)]
#[derive(Clone, PartialEq, Copy)]
#[cfg_attr(test, derive(Debug))]
pub enum AssetInfoId {
STX = 0,
FungibleAsset = 1,
Expand All @@ -82,7 +84,8 @@ impl TryFrom<u8> for AssetInfoId {
}

#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq)]
#[cfg_attr(test, derive(Debug))]
pub struct AssetInfo<'a> {
pub address: StacksAddress<'a>,
pub contract_name: ContractName<'a>,
Expand Down Expand Up @@ -121,7 +124,8 @@ impl<'a> AssetInfo<'a> {
}

#[repr(u8)]
#[derive(Debug, Clone, PartialEq, Copy)]
#[derive(Clone, PartialEq, Copy)]
#[cfg_attr(test, derive(Debug))]
// Flag used to know if the signer is valid and
// who is
pub enum SignerId {
Expand All @@ -133,7 +137,8 @@ pub enum SignerId {
// tag address hash modes as "singlesig" or "multisig" so we can't accidentally construct an
// invalid spending condition
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq)]
#[cfg_attr(test, derive(Debug))]
pub enum HashMode {
P2PKH = 0x00,
P2SH = 0x01,
Expand Down Expand Up @@ -175,7 +180,8 @@ impl HashMode {
// contract name with valid charactes being
// ^[a-zA-Z]([a-zA-Z0-9]|[-_])*$
#[repr(C)]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
#[derive(Clone, Copy, Eq, PartialEq)]
#[cfg_attr(test, derive(Debug))]
pub struct ContractName<'a>(ClarityName<'a>);

impl<'a> ContractName<'a> {
Expand Down Expand Up @@ -204,7 +210,8 @@ impl<'a> ContractName<'a> {

// A clarity value used in tuples
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(test, derive(Debug))]
pub struct ClarityName<'a>(pub &'a [u8]);

impl<'a> ClarityName<'a> {
Expand Down Expand Up @@ -239,7 +246,8 @@ impl<'a> ClarityName<'a> {
}

#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq)]
#[cfg_attr(test, derive(Debug))]
// we take HASH160_LEN + 1-byte hash mode
pub struct StacksAddress<'a>(pub &'a [u8; STACKS_ADDR_LEN]);

Expand Down
12 changes: 8 additions & 4 deletions app/rust/src/parser/post_condition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ impl TryFrom<u8> for PostConditionPrincipalId {
}

#[repr(C)]
#[derive(Clone, Copy, PartialEq, Debug)]
#[derive(Clone, Copy, PartialEq)]
#[cfg_attr(test, derive(Debug))]
pub enum PostConditionPrincipal<'a> {
Origin,
Standard(StacksAddress<'a>),
Expand Down Expand Up @@ -127,7 +128,8 @@ impl<'a> PostConditionPrincipal<'a> {
}

#[repr(u8)]
#[derive(Clone, PartialEq, Copy, Debug)]
#[derive(Clone, PartialEq, Copy)]
#[cfg_attr(test, derive(Debug))]
pub enum FungibleConditionCode {
SentEq = 0x01,
SentGt = 0x02,
Expand Down Expand Up @@ -160,7 +162,8 @@ impl FungibleConditionCode {
}

#[repr(u8)]
#[derive(Clone, PartialEq, Copy, Debug)]
#[derive(Clone, PartialEq, Copy)]
#[cfg_attr(test, derive(Debug))]
pub enum NonfungibleConditionCode {
Sent = 0x10,
NotSent = 0x11,
Expand Down Expand Up @@ -208,7 +211,8 @@ impl TryFrom<u8> for PostConditionType {

/// Post-condition on a transaction
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq)]
#[derive(Clone, Copy, PartialEq)]
#[cfg_attr(test, derive(Debug))]
pub enum TransactionPostCondition<'a> {
STX(&'a [u8]),
Fungible(&'a [u8]),
Expand Down
9 changes: 6 additions & 3 deletions app/rust/src/parser/principal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use nom::bytes::complete::take;
use super::{c32, ContractName, ParserError, C32_ENCODED_ADDRS_LENGTH, HASH160_LEN};

#[repr(C)]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
#[derive(Clone, Copy, Eq, PartialEq)]
#[cfg_attr(test, derive(Debug))]
pub struct StandardPrincipal<'a>(pub &'a [u8]);

impl<'a> StandardPrincipal<'a> {
Expand All @@ -18,7 +19,8 @@ impl<'a> StandardPrincipal<'a> {
}

#[repr(C)]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
#[derive(Clone, Copy, Eq, PartialEq)]
#[cfg_attr(test, derive(Debug))]
pub struct ContractPrincipal<'a>(StandardPrincipal<'a>, ContractName<'a>);
impl<'a> ContractPrincipal<'a> {
#[inline(never)]
Expand All @@ -37,7 +39,8 @@ impl<'a> ContractPrincipal<'a> {
}

#[repr(C)]
#[derive(Debug, Clone, Eq, PartialEq)]
#[derive(Clone, Eq, PartialEq)]
#[cfg_attr(test, derive(Debug))]
pub struct PrincipalData<'a> {
pub data: (StandardPrincipal<'a>, Option<ContractName<'a>>),
}
Expand Down
Loading

0 comments on commit 5f40d62

Please sign in to comment.