diff --git a/context.h b/context.h index 0552070..e7db0b4 100644 --- a/context.h +++ b/context.h @@ -246,6 +246,7 @@ typedef enum coin_kind_e { COIN_KIND_RESISTANCE, COIN_KIND_RAVENCOIN, COIN_KIND_HYDRA, + COIN_KIND_ECASH, COIN_KIND_UNUSED } coin_kind_t; diff --git a/display_utils.c b/display_utils.c index a871b8f..8e02586 100644 --- a/display_utils.c +++ b/display_utils.c @@ -1,3 +1,4 @@ +#include "context.h" #include "filesystem_tx.h" #include "ledger_assert.h" #include "read.h" @@ -42,6 +43,13 @@ static uint64_t div100000000(uint64_t n) { return res; } +static uint64_t div100(uint64_t n) { + uint64_t res = n; + res = div10(res); + res = div10(res); + return res; +} + static size_t n_digits(uint64_t number) { size_t count = 0; do { @@ -63,11 +71,21 @@ void format_sats_amount(const char *coin_name, uint64_t amount, char *amount_str = out + coin_name_len + 1; + uint64_t integral_part; + uint32_t fractional_part; + // HACK: avoid __udivmoddi4 - // uint64_t integral_part = amount / 100000000; - // uint32_t fractional_part = (uint32_t) (amount % 100000000); - uint64_t integral_part = div100000000(amount); - uint32_t fractional_part = (uint32_t)(amount - integral_part * 100000000); + if (COIN_KIND == COIN_KIND_ECASH) { + // integral_part = amount / 100; + // fractional_part = (uint32_t) (amount % 100); + integral_part = div100(amount); + fractional_part = (uint32_t)(amount - integral_part * 100); + } else { + // integral_part = amount / 100000000; + // fractional_part = (uint32_t) (amount % 100000000); + integral_part = div100000000(amount); + fractional_part = (uint32_t)(amount - integral_part * 100000000); + } // format the integral part, starting from the least significant digit size_t integral_part_digit_count = n_digits(integral_part); @@ -85,15 +103,23 @@ void format_sats_amount(const char *coin_name, uint64_t amount, if (fractional_part == 0) { amount_str[integral_part_digit_count] = '\0'; } else { - // format the fractional part (exactly 8 digits, possibly with trailing - // zeros) amount_str[integral_part_digit_count] = '.'; char *fract_part_str = amount_str + integral_part_digit_count + 1; - snprintf(fract_part_str, 8 + 1, "%08u", fractional_part); - - // drop trailing zeros - for (int i = 7; i > 0 && fract_part_str[i] == '0'; i--) { - fract_part_str[i] = '\0'; + if (COIN_KIND == COIN_KIND_ECASH) { + // format the fractional part (exactly 2 digits, possibly with trailing + // zeros). For eCash we don't need to drop the trailing zeros, there is a + // single one at most. + snprintf(fract_part_str, 2 + 1, "%02u", fractional_part); + + } else { + // format the fractional part (exactly 8 digits, possibly with trailing + // zeros) + snprintf(fract_part_str, 8 + 1, "%08u", fractional_part); + + // drop trailing zeros + for (int i = 7; i > 0 && fract_part_str[i] == '0'; i--) { + fract_part_str[i] = '\0'; + } } } } diff --git a/handler/get_wallet_public_key.c b/handler/get_wallet_public_key.c index ca04f95..6b63802 100644 --- a/handler/get_wallet_public_key.c +++ b/handler/get_wallet_public_key.c @@ -97,7 +97,7 @@ WEAK unsigned short handler_get_wallet_public_key(buffer_t *buffer, uint8_t p1, return io_send_sw(SW_INCORRECT_P1_P2); } - if (p2 == P2_CASHADDR && COIN_KIND != COIN_KIND_BITCOIN_CASH) { + if (p2 == P2_CASHADDR && COIN_KIND != COIN_KIND_BITCOIN_CASH && COIN_KIND != COIN_KIND_ECASH) { PRINTF("Wrong P2 value\n"); return io_send_sw(SW_INCORRECT_P1_P2); } diff --git a/handler/hash_input_start.c b/handler/hash_input_start.c index ad66296..301bb01 100644 --- a/handler/hash_input_start.c +++ b/handler/hash_input_start.c @@ -83,7 +83,7 @@ WEAK unsigned short handler_hash_input_start(buffer_t *buffer, uint8_t p1, context.transactionContext.relaxed = 0; context.usingSegwit = usingSegwit; - if (COIN_KIND == COIN_KIND_BITCOIN_CASH) { + if ((COIN_KIND == COIN_KIND_BITCOIN_CASH) || (COIN_KIND == COIN_KIND_ECASH)) { unsigned char usingCashAddr = (p2 == P2_NEW_SEGWIT_CASHADDR); context.usingCashAddr = usingCashAddr; } else { diff --git a/handler/hash_sign.c b/handler/hash_sign.c index 3d79239..4db35bf 100644 --- a/handler/hash_sign.c +++ b/handler/hash_sign.c @@ -117,8 +117,8 @@ WEAK unsigned short handler_hash_sign(buffer_t *buffer, uint8_t p1, sighashType = *(parameters++); context.transactionSummary.sighashType = sighashType; - // if bitcoin cash OR forkid is set, then use the fork id - if ((COIN_KIND == COIN_KIND_BITCOIN_CASH) || (COIN_FORKID != 0)) { + // if bitcoin cash OR eCash or forkid is set, then use the fork id + if ((COIN_KIND == COIN_KIND_BITCOIN_CASH) || (COIN_KIND == COIN_KIND_ECASH) || (COIN_FORKID != 0)) { #define SIGHASH_FORKID 0x40 if (sighashType != (SIGHASH_ALL | SIGHASH_FORKID)) { context.transactionContext.transactionState = TRANSACTION_NONE; diff --git a/utils/cashaddr.c b/utils/cashaddr.c index 3214af1..8f4173f 100644 --- a/utils/cashaddr.c +++ b/utils/cashaddr.c @@ -28,6 +28,7 @@ #include #include "cashaddr.h" +#include "context.h" static const char *charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"; @@ -81,7 +82,12 @@ static int convert_bits(uint8_t *out, size_t *outlen, int outbits, void create_checksum(uint8_t *payload, size_t payload_length, uint8_t *checksum) { - uint8_t *prefix = (uint8_t *)"bitcoincash"; + uint8_t *prefix; + if (COIN_KIND == COIN_KIND_ECASH) { + prefix = (uint8_t *)"ecash"; + } else { + prefix = (uint8_t *)"bitcoincash"; + } uint64_t mod = PolyMod(prefix, payload, payload_length); for (size_t i = 0; i < 8; ++i) { @@ -120,7 +126,7 @@ int cashaddr_encode(uint8_t *hash, const size_t hash_length, uint8_t *addr, convert_bits(payload, &payload_length, 5, tmp, hash_length + 1, 8, 1); create_checksum(payload, payload_length, - checksum); // Assume prefix is 'bitcoincash' + checksum); for (i = 0; i < payload_length; ++i) { if (*payload >> 5) { diff --git a/utils/cashaddr.h b/utils/cashaddr.h index 9eeb4bd..6422ff4 100644 --- a/utils/cashaddr.h +++ b/utils/cashaddr.h @@ -29,7 +29,7 @@ #define CASHADDR_P2PKH 0 #define CASHADDR_P2SH 1 -/** Encode a Bitcoin Cash address +/** Encode a Bitcoin Cash or eCash address * * In: hash: Pointer to the hash * hash_length: Length of hash (bytes). Only 20 bytes (160 bits)