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

Ravencoin: fixed signing and added more chain functionality #197

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Expand Up @@ -179,7 +179,7 @@ APPNAME ="Resistance"
APP_LOAD_PARAMS += --path $(APP_PATH)
else ifeq ($(COIN),ravencoin)
# Ravencoin
DEFINES += BIP44_COIN_TYPE=175 BIP44_COIN_TYPE_2=175 COIN_P2PKH_VERSION=60 COIN_P2SH_VERSION=122 COIN_FAMILY=1 COIN_COINID=\"Ravencoin\" COIN_COINID_HEADER=\"RAVENCOIN\" COIN_COLOR_HDR=0x2E4A80 COIN_COLOR_DB=0x74829E COIN_COINID_NAME=\"Ravencoin\" COIN_COINID_SHORT=\"RVN\" COIN_KIND=COIN_KIND_RAVENCOIN
DEFINES += BIP44_COIN_TYPE=175 BIP44_COIN_TYPE_2=175 COIN_P2PKH_VERSION=60 COIN_P2SH_VERSION=122 COIN_FAMILY=1 COIN_COINID=\"Raven\" COIN_COINID_HEADER=\"RAVENCOIN\" COIN_COLOR_HDR=0x2E4A80 COIN_COLOR_DB=0x74829E COIN_COINID_NAME=\"Ravencoin\" COIN_COINID_SHORT=\"RVN\" COIN_KIND=COIN_KIND_RAVENCOIN
APPNAME ="Ravencoin"
APP_LOAD_PARAMS += --path $(APP_PATH)
else
Expand Down
2 changes: 1 addition & 1 deletion include/btchip_context.h
Expand Up @@ -24,7 +24,7 @@
#include "btchip_secure_value.h"
#include "btchip_filesystem_tx.h"

#define MAX_OUTPUT_TO_CHECK 100
#define MAX_OUTPUT_TO_CHECK 120 //Ravencoin asset max
#define MAX_COIN_ID 13
#define MAX_SHORT_COIN_ID 5

Expand Down
7 changes: 7 additions & 0 deletions include/btchip_helpers.h
Expand Up @@ -31,7 +31,9 @@
#define OUTPUT_SCRIPT_NATIVE_WITNESS_PROGRAM_OFFSET 3

unsigned char btchip_output_script_is_regular(unsigned char *buffer);
unsigned char btchip_output_script_is_regular_ravencoin_asset(unsigned char *buffer);
unsigned char btchip_output_script_is_p2sh(unsigned char *buffer);
unsigned char btchip_output_script_is_p2sh_ravencoin_asset(unsigned char *buffer);
unsigned char btchip_output_script_is_op_return(unsigned char *buffer);
unsigned char btchip_output_script_is_native_witness(unsigned char *buffer);

Expand All @@ -40,6 +42,9 @@ unsigned char btchip_output_script_is_op_create(unsigned char *buffer,
unsigned char btchip_output_script_is_op_call(unsigned char *buffer,
size_t size);

signed char btchip_output_script_try_get_ravencoin_asset_tag_type(unsigned char *buffer);
unsigned char btchip_output_script_get_ravencoin_asset_ptr(unsigned char *buffer, size_t size, int *ptr);

void btchip_sleep16(unsigned short delay);
void btchip_sleep32(unsigned long int delayEach, unsigned long int delayRepeat);

Expand Down Expand Up @@ -80,6 +85,8 @@ unsigned char bip32_print_path(unsigned char *bip32Path, char* out, unsigned cha
#define btchip_set_check_internal_structure_integrity(x)
void btchip_swap_bytes(unsigned char *target, unsigned char *source,
unsigned char size);
void btchip_swap_bytes_reversed(unsigned char *target, unsigned char *source,
unsigned char size);

void btchip_sign_finalhash(void *keyContext,
unsigned char *in, unsigned short inlen,
Expand Down
59 changes: 51 additions & 8 deletions src/btchip_apdu_hash_input_finalize_full.c
Expand Up @@ -42,6 +42,8 @@ void btchip_apdu_hash_input_finalize_full_reset(void) {

static bool check_output_displayable() {
bool displayable = true;
bool invalid_script = false;
int dummy;
unsigned char amount[8], isOpReturn, isP2sh, isNativeSegwit, j,
nullAmount = 1;
unsigned char isOpCreate, isOpCall;
Expand All @@ -52,14 +54,23 @@ static bool check_output_displayable() {
break;
}
}

if (!nullAmount) {
btchip_swap_bytes(amount, btchip_context_D.currentOutput, 8);
transaction_amount_add_be(btchip_context_D.totalOutputAmount,
btchip_context_D.totalOutputAmount, amount);
}

isOpReturn =
btchip_output_script_is_op_return(btchip_context_D.currentOutput + 8);
isP2sh = btchip_output_script_is_p2sh(btchip_context_D.currentOutput + 8);

if (nullAmount && G_coin_config->kind==COIN_KIND_RAVENCOIN){
isP2sh = btchip_output_script_is_p2sh_ravencoin_asset(btchip_context_D.currentOutput + 8);
}
else {
isP2sh = btchip_output_script_is_p2sh(btchip_context_D.currentOutput + 8);
}

isNativeSegwit = btchip_output_script_is_native_witness(
btchip_context_D.currentOutput + 8);
isOpCreate =
Expand All @@ -68,13 +79,45 @@ static bool check_output_displayable() {
isOpCall =
btchip_output_script_is_op_call(btchip_context_D.currentOutput + 8,
sizeof(btchip_context_D.currentOutput) - 8);
if (((G_coin_config->kind == COIN_KIND_QTUM) &&
!btchip_output_script_is_regular(btchip_context_D.currentOutput + 8) &&
!isP2sh && !(nullAmount && isOpReturn) && !isOpCreate && !isOpCall) ||
(!(G_coin_config->kind == COIN_KIND_QTUM) &&
!btchip_output_script_is_regular(btchip_context_D.currentOutput + 8) &&
!isP2sh && !(nullAmount && isOpReturn))) {
PRINTF("Error : Unrecognized output script");

if (G_coin_config->kind == COIN_KIND_RAVENCOIN) {
PRINTF("Asset script value: %d\n", btchip_output_script_get_ravencoin_asset_ptr(
btchip_context_D.currentOutput + 8,
sizeof(btchip_context_D.currentOutput) - 8,
&dummy
));
PRINTF("Null asset script value: %d\n", btchip_output_script_try_get_ravencoin_asset_tag_type(btchip_context_D.currentOutput + 8));
PRINTF("Null amount: %d\n", nullAmount);
}

if (G_coin_config->kind == COIN_KIND_QTUM) {
invalid_script =
!btchip_output_script_is_regular(btchip_context_D.currentOutput + 8) &&
!isP2sh && !(nullAmount && isOpReturn) && !isOpCreate && !isOpCall;
}
else if (nullAmount && G_coin_config->kind == COIN_KIND_RAVENCOIN) {
// Ravencoin assets only come into play when there is a null amount
invalid_script =
(!btchip_output_script_get_ravencoin_asset_ptr(
btchip_context_D.currentOutput + 8,
sizeof(btchip_context_D.currentOutput) - 8,
&dummy)
||
(!btchip_output_script_is_regular_ravencoin_asset(btchip_context_D.currentOutput + 8)
&&
!isP2sh
)
)
&& !isOpReturn
&& -1 == btchip_output_script_try_get_ravencoin_asset_tag_type(btchip_context_D.currentOutput + 8);
}
else {
invalid_script =
!btchip_output_script_is_regular(btchip_context_D.currentOutput + 8) &&
!isP2sh && !(nullAmount && isOpReturn);
}
if (invalid_script) {
PRINTF("Error : Unrecognized output script\n");
THROW(EXCEPTION);
}
if (btchip_context_D.tmpCtx.output.changeInitialized && !isOpReturn) {
Expand Down
5 changes: 3 additions & 2 deletions src/btchip_display_variables.h
Expand Up @@ -22,9 +22,10 @@ union display_variables {
struct {
// char addressSummary[40]; // beginning of the output address ... end
// of

char fullAddress[65]; // the address
char fullAmount[20]; // full amount
//Ravencoin: max asset length (32) + space (1) + max amt whole (11) + decimal (1) + max amt decimal (8) + \0 (1)
char fullAmount[54];
//char fullAmount[20]; // full amount
char feesAmount[20]; // fees
} tmp;

Expand Down
122 changes: 121 additions & 1 deletion src/btchip_helpers.c
Expand Up @@ -59,6 +59,7 @@ const unsigned char ZEN_OUTPUT_SCRIPT_POST[] = {
}; // BIP0115 Replay Protection

unsigned char btchip_output_script_is_regular(unsigned char *buffer) {
int i;
if (G_coin_config->native_segwit_prefix) {
if ((os_memcmp(buffer, TRANSACTION_OUTPUT_SCRIPT_P2WPKH_PRE,
sizeof(TRANSACTION_OUTPUT_SCRIPT_P2WPKH_PRE)) == 0) ||
Expand All @@ -75,7 +76,8 @@ unsigned char btchip_output_script_is_regular(unsigned char *buffer) {
sizeof(ZEN_OUTPUT_SCRIPT_POST)) == 0)) {
return 1;
}
} else {
}
else {
if ((os_memcmp(buffer, TRANSACTION_OUTPUT_SCRIPT_PRE,
sizeof(TRANSACTION_OUTPUT_SCRIPT_PRE)) == 0) &&
(os_memcmp(buffer + sizeof(TRANSACTION_OUTPUT_SCRIPT_PRE) + 20,
Expand All @@ -87,6 +89,19 @@ unsigned char btchip_output_script_is_regular(unsigned char *buffer) {
return 0;
}

unsigned char btchip_output_script_is_regular_ravencoin_asset(unsigned char *buffer) {
if (G_coin_config->kind == COIN_KIND_RAVENCOIN) {
if ((os_memcmp(buffer + 1, TRANSACTION_OUTPUT_SCRIPT_PRE + 1,
sizeof(TRANSACTION_OUTPUT_SCRIPT_PRE) - 1) == 0) &&
(os_memcmp(buffer + sizeof(TRANSACTION_OUTPUT_SCRIPT_PRE) + 20,
TRANSACTION_OUTPUT_SCRIPT_POST,
sizeof(TRANSACTION_OUTPUT_SCRIPT_POST)) == 0)) {
return 1;
}
}
return 0;
}

unsigned char btchip_output_script_is_p2sh(unsigned char *buffer) {
if (G_coin_config->kind == COIN_KIND_HORIZEN) {
if ((os_memcmp(buffer, ZEN_TRANSACTION_OUTPUT_SCRIPT_P2SH_PRE,
Expand All @@ -108,6 +123,19 @@ unsigned char btchip_output_script_is_p2sh(unsigned char *buffer) {
return 0;
}

unsigned char btchip_output_script_is_p2sh_ravencoin_asset(unsigned char *buffer) {
if (G_coin_config->kind == COIN_KIND_RAVENCOIN) {
if ((os_memcmp(buffer + 1, TRANSACTION_OUTPUT_SCRIPT_P2SH_PRE + 1,
sizeof(TRANSACTION_OUTPUT_SCRIPT_P2SH_PRE) - 1) == 0) &&
(os_memcmp(buffer + sizeof(TRANSACTION_OUTPUT_SCRIPT_P2SH_PRE) + 20,
TRANSACTION_OUTPUT_SCRIPT_P2SH_POST,
sizeof(TRANSACTION_OUTPUT_SCRIPT_P2SH_POST)) == 0)) {
return 1;
}
}
return 0;
}

unsigned char btchip_output_script_is_native_witness(unsigned char *buffer) {
if (G_coin_config->native_segwit_prefix) {
if ((os_memcmp(buffer, TRANSACTION_OUTPUT_SCRIPT_P2WPKH_PRE,
Expand Down Expand Up @@ -149,6 +177,90 @@ unsigned char btchip_output_script_is_op_call(unsigned char *buffer,
return output_script_is_op_create_or_call(buffer, size, 0xC2);
}

signed char btchip_output_script_try_get_ravencoin_asset_tag_type(unsigned char *buffer) {
if (btchip_output_script_is_regular(buffer) ||
btchip_output_script_is_p2sh(buffer) ||
btchip_output_script_is_op_return(buffer) ||
(buffer[1] != 0xC0)) {
return -1;
}
if (buffer[2] == 0x50) {
if (buffer[3] == 0x50) {
return 2;
}
return 1;
}
return 0;
}

unsigned char btchip_output_script_get_ravencoin_asset_ptr(unsigned char *buffer, size_t size, int *ptr) {
// This method is also used in check_output_displayable and needs to ensure no overflows happen from bad scripts
unsigned int script_ptr = 1; // Skip the first pushdata op
unsigned int op = -1;
unsigned int final_op = buffer[0];
unsigned char asset_len;

if (final_op >= size || buffer[final_op] != 0x75) {
PRINTF("Ravencoin pointer quick return\n");
return 0;
}
while (script_ptr < final_op - 7) { // Definitely a bad asset script; too short
op = buffer[script_ptr++];
if (op == 0xC0) {
// Verifying script
if ((buffer[script_ptr+1] == 0x72) &&
(buffer[script_ptr+2] == 0x76) &&
(buffer[script_ptr+3] == 0x6E)) {
asset_len = buffer[script_ptr+5];
if (asset_len > 32) { // Invalid script
return 0;
}
if (buffer[script_ptr+4] == 0x6F) {
// Ownership assets will not have an amount
if (script_ptr+5+asset_len >= final_op) {
return 0; // Too small
}
}
else {
if (script_ptr+5+asset_len+8 >= final_op) {
return 0; // Too small
}
}
*ptr = script_ptr + 4;
} else {
asset_len = buffer[script_ptr+6];
if (asset_len > 32) { // Invalid script
return 0;
}
if (buffer[script_ptr+5] == 0x6F) {
// Ownership assets will not have an amount
if (script_ptr+6+asset_len >= final_op) {
return 0; // Too small
}
}
else {
if (script_ptr+6+asset_len+8 >= final_op) {
return 0; // Too small
}
}
*ptr = script_ptr + 5;
}
return 1;
}
else if (op <= 0x4E) {
if (op < 0x4C) {
script_ptr += op;
}
else {
script_ptr += (buffer[script_ptr] + 1);
}
//There shouldn't be anything pushed larger than 256 bytes in an asset transfer script
}
}
PRINTF("Ravencoin pointer end\n");
return 0;
}

unsigned char btchip_rng_u8_modulo(unsigned char modulo) {
unsigned int rng_max = 256 % modulo;
unsigned int rng_limit = 256 - rng_max;
Expand Down Expand Up @@ -265,6 +377,14 @@ void btchip_swap_bytes(unsigned char *target, unsigned char *source,
}
}

void btchip_swap_bytes_reversed(unsigned char *target, unsigned char *source,
unsigned char size) {
unsigned char i;
for (i = 0; i < size; i++) {
target[i] = source[i];
}
}

unsigned short btchip_decode_base58_address(unsigned char *in,
unsigned short inlen,
unsigned char *out,
Expand Down