Skip to content

Commit 07ec772

Browse files
timemarkovqtumicodefaceNeil
committed
Update qtum support
* Add op_sender and update op_call and op_create checks * Fix get for script size * Update functions names in the style of the app * Check op_call and op_create only for qtum * Update max output size to 500 for Qtum * Update Qtum to be standalone app * Add Qtum specific code between macros * Fix for op_sender output check * Add Sign OP_SENDER into UX FLOW * Add function to get script for sender address * Add function to check is exist sender sig in the output * Add size to sender address script * Add sign op_sender support * Release more memory for Qtum * Move the sign sender code in btchip_hash_sender_sign.c * Add sender signature checks The signature is empty when signing the output and not empty when signing the inputs. * Add Qtum specific code between macros * Increase the max output size from 450 to 500 as before op_sender Op_sender work well with 500 too after disable Blake2b (350 with Blake2b enabled), which is not used for hashing in Qtum. * add qtum testnet * add support for other derivation path * Do not use LIB * Display delegation/contract details Co-authored-by: timemarkovqtum <[email protected]> Co-authored-by: codeface <[email protected]> Co-authored-by: Neil <[email protected]>
1 parent bef1351 commit 07ec772

13 files changed

+683
-45
lines changed

Makefile

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,18 @@ else ifeq ($(COIN),qtum)
133133
# Qtum
134134
# Qtum can run significantly different code paths, thus is locked by the OS
135135
# using APP_LOAD_PARAMS instead of BIP44_COIN_TYPE
136-
DEFINES += BIP44_COIN_TYPE=0 BIP44_COIN_TYPE_2=0 COIN_P2PKH_VERSION=58 COIN_P2SH_VERSION=50 COIN_FAMILY=3 COIN_COINID=\"Qtum\" COIN_COINID_HEADER=\"QTUM\" COIN_COLOR_HDR=0x2E9AD0 COIN_COLOR_DB=0x97CDE8 COIN_COINID_NAME=\"QTUM\" COIN_COINID_SHORT=\"QTUM\" COIN_NATIVE_SEGWIT_PREFIX=\"qc\" COIN_KIND=COIN_KIND_QTUM COIN_FLAGS=FLAG_SEGWIT_CHANGE_SUPPORT
136+
DEFINES += BIP44_COIN_TYPE=0 BIP44_COIN_TYPE_2=0 COIN_P2PKH_VERSION=58 COIN_P2SH_VERSION=50 COIN_FAMILY=3 COIN_COINID=\"Qtum\" COIN_COINID_HEADER=\"QTUM\" COIN_COLOR_HDR=0x2E9AD0 COIN_COLOR_DB=0x97CDE8 COIN_COINID_NAME=\"QTUM\" COIN_COINID_SHORT=\"QTUM\" COIN_NATIVE_SEGWIT_PREFIX=\"qc\" COIN_KIND=COIN_KIND_QTUM COIN_FLAGS=FLAG_SEGWIT_CHANGE_SUPPORT MAX_OUTPUT_TO_CHECK=500 HAVE_QTUM_SUPPORT USE_NO_OVERWINTER
137137
APPNAME ="Qtum"
138-
APP_LOAD_PARAMS += --path "44'/88'" --path "49'/88'" --path "0'/45342'" --path "20698'/3053'/12648430'"
138+
DEFINES_LIB=# we're not using the lib :)
139+
APP_LOAD_PARAMS += --path $(APP_PATH) --path "44'/88'" --path "45'/88'" --path "48'/88'" --path "49'/88'" --path "84'/88'" --path "0'/45342'" --path "20698'/3053'/12648430'"
140+
APP_LOAD_FLAGS=--appFlags 0xa50
141+
else ifeq ($(COIN),qtum_testnet)
142+
# Qtum Testnet
143+
DEFINES += BIP44_COIN_TYPE=0 BIP44_COIN_TYPE_2=0 COIN_P2PKH_VERSION=120 COIN_P2SH_VERSION=110 COIN_FAMILY=3 COIN_COINID=\"Qtum\" COIN_COINID_HEADER=\"QTUM\" COIN_COLOR_HDR=0x2E9AD0 COIN_COLOR_DB=0x97CDE8 COIN_COINID_NAME=\"QTUM\" COIN_COINID_SHORT=\"QTUM\" COIN_NATIVE_SEGWIT_PREFIX=\"tq\" COIN_KIND=COIN_KIND_QTUM COIN_FLAGS=FLAG_SEGWIT_CHANGE_SUPPORT MAX_OUTPUT_TO_CHECK=500 HAVE_QTUM_SUPPORT USE_NO_OVERWINTER
144+
APPNAME ="Qtum Test"
145+
DEFINES_LIB=# we're not using the lib :)
146+
APP_LOAD_PARAMS += --path $(APP_PATH) --path "44'/1'" --path "45'/1'" --path "48'/1'" --path "49'/1'" --path "84'/1'" --path "0'/45342'" --path "20698'/3053'/12648430'"
147+
APP_LOAD_FLAGS=--appFlags 0xa50
139148
else ifeq ($(COIN),zcoin)
140149
DEFINES += BIP44_COIN_TYPE=136 BIP44_COIN_TYPE_2=136 COIN_P2PKH_VERSION=82 COIN_P2SH_VERSION=7 COIN_FAMILY=1 COIN_COINID=\"Zcoin\" COIN_COINID_HEADER=\"ZCOIN\" COIN_COLOR_HDR=0x3EAD54 COIN_COLOR_DB=0xA3DCAE COIN_COINID_NAME=\"Zcoin\" COIN_COINID_SHORT=\"ZCOIN\" COIN_KIND=COIN_KIND_ZCOIN
141150
APPNAME ="Zcoin"

include/btchip_context.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@
2424
#include "btchip_secure_value.h"
2525
#include "btchip_filesystem_tx.h"
2626

27+
#ifndef MAX_OUTPUT_TO_CHECK
2728
#define MAX_OUTPUT_TO_CHECK 100
29+
#endif
2830
#define MAX_COIN_ID 13
2931
#define MAX_SHORT_COIN_ID 5
3032

@@ -96,7 +98,9 @@ typedef enum btchip_output_parsing_state_e btchip_output_parsing_state_t;
9698

9799
typedef union multi_hash {
98100
cx_sha256_t sha256;
101+
#ifndef USE_NO_OVERWINTER
99102
cx_blake2b_t blake2b;
103+
#endif
100104
} multi_hash;
101105

102106
struct segwit_hash_s {
@@ -171,6 +175,9 @@ struct btchip_context_s {
171175
cx_sha256_t transactionHashAuthorization;
172176
/** Current hash to perform (TRANSACTION_HASH_) */
173177
unsigned char transactionHashOption;
178+
#ifdef HAVE_QTUM_SUPPORT
179+
cx_sha256_t transactionOutputHash;
180+
#endif
174181

175182
/* Segregated Witness changes */
176183

@@ -185,6 +192,9 @@ struct btchip_context_s {
185192
unsigned char segwitParsedOnce;
186193
/** Prevents display of segwit input warning at each InputHashStart APDU */
187194
unsigned char segwitWarningSeen;
195+
#ifdef HAVE_QTUM_SUPPORT
196+
unsigned char signOpSender;
197+
#endif
188198

189199
/* /Segregated Witness changes */
190200

include/btchip_helpers.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,26 @@ unsigned char btchip_output_script_is_p2sh(unsigned char *buffer);
3333
unsigned char btchip_output_script_is_op_return(unsigned char *buffer);
3434
unsigned char btchip_output_script_is_native_witness(unsigned char *buffer);
3535

36+
#ifdef HAVE_QTUM_SUPPORT
3637
unsigned char btchip_output_script_is_op_create(unsigned char *buffer,
3738
size_t size);
3839
unsigned char btchip_output_script_is_op_call(unsigned char *buffer,
3940
size_t size);
41+
unsigned char btchip_output_script_is_op_sender(unsigned char *buffer,
42+
size_t size);
43+
unsigned char btchip_get_script_size(unsigned char *buffer, size_t maxSize,
44+
unsigned int *scriptSize, unsigned int *discardSize);
45+
unsigned char btchip_get_script_sender_address(unsigned char *buffer,
46+
size_t size, unsigned char *script);
47+
unsigned char btchip_get_sender_sig(unsigned char *buffer,
48+
size_t size, unsigned char **sig, unsigned int *sigSize);
49+
#endif
4050

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

54+
unsigned long int btchip_read_u16(unsigned char *buffer, unsigned char be,
55+
unsigned char skipSign);
4456
unsigned long int btchip_read_u32(unsigned char *buffer, unsigned char be,
4557
unsigned char skipSign);
4658

src/btchip_apdu_get_trusted_input.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ unsigned short btchip_apdu_get_trusted_input() {
4949
btchip_context_D.transactionHashOption = TRANSACTION_HASH_FULL;
5050
btchip_context_D.usingSegwit = 0;
5151
btchip_context_D.usingOverwinter = 0;
52+
#ifdef HAVE_QTUM_SUPPORT
53+
btchip_context_D.signOpSender = 0;
54+
#endif
5255
} else if (G_io_apdu_buffer[ISO_OFFSET_P1] != GET_TRUSTED_INPUT_P1_NEXT) {
5356
return BTCHIP_SW_INCORRECT_P1_P2;
5457
}

src/btchip_apdu_hash_input_finalize_full.c

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ static bool check_output_displayable() {
4646
bool displayable = true;
4747
unsigned char amount[8], isOpReturn, isP2sh, isNativeSegwit, j,
4848
nullAmount = 1;
49-
unsigned char isOpCreate, isOpCall;
49+
unsigned char isOpCreate = 0, isOpCall = 0, isOpSender = 0;
5050

5151
for (j = 0; j < 8; j++) {
5252
if (btchip_context_D.currentOutput[j] != 0) {
@@ -64,12 +64,19 @@ static bool check_output_displayable() {
6464
isP2sh = btchip_output_script_is_p2sh(btchip_context_D.currentOutput + 8);
6565
isNativeSegwit = btchip_output_script_is_native_witness(
6666
btchip_context_D.currentOutput + 8);
67-
isOpCreate =
68-
btchip_output_script_is_op_create(btchip_context_D.currentOutput + 8,
69-
sizeof(btchip_context_D.currentOutput) - 8);
70-
isOpCall =
71-
btchip_output_script_is_op_call(btchip_context_D.currentOutput + 8,
72-
sizeof(btchip_context_D.currentOutput) - 8);
67+
#ifdef HAVE_QTUM_SUPPORT
68+
if(G_coin_config->kind == COIN_KIND_QTUM) {
69+
isOpCreate =
70+
btchip_output_script_is_op_create(btchip_context_D.currentOutput + 8,
71+
sizeof(btchip_context_D.currentOutput) - 8);
72+
isOpCall =
73+
btchip_output_script_is_op_call(btchip_context_D.currentOutput + 8,
74+
sizeof(btchip_context_D.currentOutput) - 8);
75+
isOpSender =
76+
btchip_output_script_is_op_sender(btchip_context_D.currentOutput + 8,
77+
sizeof(btchip_context_D.currentOutput) - 8);
78+
}
79+
#endif
7380
if (((G_coin_config->kind == COIN_KIND_QTUM) &&
7481
!btchip_output_script_is_regular(btchip_context_D.currentOutput + 8) &&
7582
!isP2sh && !(nullAmount && isOpReturn) && !isOpCreate && !isOpCall) ||
@@ -79,13 +86,32 @@ static bool check_output_displayable() {
7986
PRINTF("Error : Unrecognized output script");
8087
THROW(EXCEPTION);
8188
}
89+
#ifdef HAVE_QTUM_SUPPORT
90+
if((G_coin_config->kind == COIN_KIND_QTUM) && isOpSender && (isOpCreate || isOpCall))
91+
{
92+
unsigned char *sig = 0;
93+
unsigned int sigSize = 0;
94+
btchip_get_sender_sig(btchip_context_D.currentOutput + 8,
95+
sizeof(btchip_context_D.currentOutput) - 8, &sig, &sigSize);
96+
if(!btchip_context_D.signOpSender && sigSize == 0)
97+
{
98+
PRINTF("Error : No op_sender signature");
99+
THROW(EXCEPTION);
100+
}
101+
if(btchip_context_D.signOpSender && sigSize > 0)
102+
{
103+
PRINTF("Error : op_sender is already signed");
104+
THROW(EXCEPTION);
105+
}
106+
}
107+
#endif
82108
if (btchip_context_D.tmpCtx.output.changeInitialized && !isOpReturn) {
83109
bool changeFound = false;
84110
unsigned char addressOffset =
85111
(isNativeSegwit ? OUTPUT_SCRIPT_NATIVE_WITNESS_PROGRAM_OFFSET
86112
: isP2sh ? OUTPUT_SCRIPT_P2SH_PRE_LENGTH
87113
: OUTPUT_SCRIPT_REGULAR_PRE_LENGTH);
88-
if (!isP2sh &&
114+
if (!isP2sh && !isOpSender &&
89115
os_memcmp(btchip_context_D.currentOutput + 8 + addressOffset,
90116
btchip_context_D.tmpCtx.output.changeAddress,
91117
20) == 0) {
@@ -178,7 +204,7 @@ bool handle_output_state() {
178204
break;
179205
}
180206
scriptSize =
181-
btchip_read_u32(btchip_context_D.currentOutput + 9, 0, 0);
207+
btchip_read_u16(btchip_context_D.currentOutput + 9, 0, 0);
182208
discardSize = 3;
183209
} else {
184210
// Unrealistically large script
@@ -336,10 +362,13 @@ unsigned short btchip_apdu_hash_input_finalize_full_internal(
336362
sw = BTCHIP_SW_INCORRECT_DATA;
337363
goto discardTransaction;
338364
}
365+
#ifndef USE_NO_OVERWINTER
339366
if (btchip_context_D.usingOverwinter) {
340367
cx_hash(&btchip_context_D.transactionHashFull.blake2b.header, 0, G_io_apdu_buffer + ISO_OFFSET_CDATA + hashOffset, apduLength - hashOffset, NULL, 0);
341368
}
342-
else {
369+
else
370+
#endif
371+
{
343372
PRINTF("--- ADD TO HASH FULL:\n%.*H\n", apduLength - hashOffset, G_io_apdu_buffer + ISO_OFFSET_CDATA + hashOffset);
344373
cx_hash(&btchip_context_D.transactionHashFull.sha256.header, 0,
345374
G_io_apdu_buffer + ISO_OFFSET_CDATA + hashOffset,
@@ -396,10 +425,13 @@ unsigned short btchip_apdu_hash_input_finalize_full_internal(
396425

397426
if (btchip_context_D.usingSegwit) {
398427
if (!btchip_context_D.segwitParsedOnce) {
428+
#ifndef USE_NO_OVERWINTER
399429
if (btchip_context_D.usingOverwinter) {
400430
cx_hash(&btchip_context_D.transactionHashFull.blake2b.header, CX_LAST, btchip_context_D.segwit.cache.hashedOutputs, 0, btchip_context_D.segwit.cache.hashedOutputs, 32);
401431
}
402-
else {
432+
else
433+
#endif
434+
{
403435
cx_hash(&btchip_context_D.transactionHashFull.sha256.header,
404436
CX_LAST,
405437
btchip_context_D.segwit.cache.hashedOutputs, 0,
@@ -474,7 +506,11 @@ unsigned short btchip_apdu_hash_input_finalize_full_internal(
474506
}
475507

476508
if (btchip_context_D.usingSegwit &&
477-
!btchip_context_D.segwitParsedOnce) {
509+
!btchip_context_D.segwitParsedOnce
510+
#ifdef HAVE_QTUM_SUPPORT
511+
&& !btchip_context_D.signOpSender
512+
#endif
513+
) {
478514
// This input cannot be signed when using segwit - just restart.
479515
btchip_context_D.segwitParsedOnce = 1;
480516
PRINTF("Segwit parsed once\n");
@@ -596,7 +632,11 @@ unsigned char btchip_bagl_user_action(unsigned char confirming) {
596632
btchip_context_D.transactionContext.firstSigned = 0;
597633

598634
if (btchip_context_D.usingSegwit &&
599-
!btchip_context_D.segwitParsedOnce) {
635+
!btchip_context_D.segwitParsedOnce
636+
#ifdef HAVE_QTUM_SUPPORT
637+
&& !btchip_context_D.signOpSender
638+
#endif
639+
) {
600640
// This input cannot be signed when using segwit - just restart.
601641
btchip_context_D.segwitParsedOnce = 1;
602642
PRINTF("Segwit parsed once\n");

src/btchip_apdu_hash_input_start.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#define P2_NEW_SEGWIT_OVERWINTER 0x04
2828
#define P2_NEW_SEGWIT_SAPLING 0x05
2929
#define P2_CONTINUE 0x80
30+
#define P2_NEW_SENDER 0x81
3031

3132
#define IS_INPUT() \
3233
(G_io_apdu_buffer[ISO_OFFSET_LC] - 1 > 8 \
@@ -64,6 +65,9 @@ unsigned short btchip_apdu_hash_input_start() {
6465
}
6566

6667
if ((G_io_apdu_buffer[ISO_OFFSET_P2] == P2_NEW) ||
68+
#ifdef HAVE_QTUM_SUPPORT
69+
(G_io_apdu_buffer[ISO_OFFSET_P2] == P2_NEW_SENDER) ||
70+
#endif
6771
(G_io_apdu_buffer[ISO_OFFSET_P2] == P2_NEW_SEGWIT) ||
6872
(G_io_apdu_buffer[ISO_OFFSET_P2] == P2_NEW_SEGWIT_CASHADDR) ||
6973
(G_io_apdu_buffer[ISO_OFFSET_P2] == P2_NEW_SEGWIT_OVERWINTER) ||
@@ -78,6 +82,10 @@ unsigned short btchip_apdu_hash_input_start() {
7882
(G_io_apdu_buffer[ISO_OFFSET_P2] == P2_NEW_SEGWIT_SAPLING);
7983
unsigned char usingCashAddr =
8084
(G_io_apdu_buffer[ISO_OFFSET_P2] == P2_NEW_SEGWIT_CASHADDR);
85+
#ifdef HAVE_QTUM_SUPPORT
86+
unsigned char signOpSender =
87+
(G_io_apdu_buffer[ISO_OFFSET_P2] == P2_NEW_SENDER);
88+
#endif
8189
// Request PIN validation
8290
// Only request PIN validation (user presence) to start a new
8391
// transaction signing flow.
@@ -92,7 +100,14 @@ unsigned short btchip_apdu_hash_input_start() {
92100
btchip_context_D.transactionContext.firstSigned = 1;
93101
btchip_context_D.transactionContext.consumeP2SH = 0;
94102
btchip_context_D.transactionContext.relaxed = 0;
103+
#ifdef HAVE_QTUM_SUPPORT
104+
if(signOpSender)
105+
usingSegwit = 1;
106+
#endif
95107
btchip_context_D.usingSegwit = usingSegwit;
108+
#ifdef HAVE_QTUM_SUPPORT
109+
btchip_context_D.signOpSender = signOpSender;
110+
#endif
96111
btchip_context_D.usingCashAddr =
97112
(G_coin_config->kind == COIN_KIND_BITCOIN_CASH ? usingCashAddr
98113
: 0);

src/btchip_apdu_hash_sign.c

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ unsigned short btchip_apdu_hash_sign() {
5656

5757
// Zcash special - store parameters for later
5858

59+
#ifndef USE_NO_OVERWINTER
5960
if ((btchip_context_D.usingOverwinter) &&
6061
(!btchip_context_D.overwinterSignReady) &&
6162
(btchip_context_D.segwitParsedOnce) &&
@@ -75,6 +76,7 @@ unsigned short btchip_apdu_hash_sign() {
7576
CLOSE_TRY;
7677
return BTCHIP_SW_OK;
7778
}
79+
#endif
7880

7981
if (btchip_context_D.transactionContext.transactionState !=
8082
BTCHIP_TRANSACTION_SIGN_READY) {
@@ -83,11 +85,13 @@ unsigned short btchip_apdu_hash_sign() {
8385
goto discardTransaction;
8486
}
8587

88+
#ifndef USE_NO_OVERWINTER
8689
if (btchip_context_D.usingOverwinter && !btchip_context_D.overwinterSignReady) {
8790
PRINTF("Overwinter not ready to sign\n");
8891
sw = BTCHIP_SW_CONDITIONS_OF_USE_NOT_SATISFIED;
8992
goto discardTransaction;
9093
}
94+
#endif
9195

9296
// Read parameters
9397
if (G_io_apdu_buffer[ISO_OFFSET_CDATA] > MAX_BIP32_PATH) {
@@ -130,9 +134,18 @@ unsigned short btchip_apdu_hash_sign() {
130134
if (!btchip_context_D.usingOverwinter) {
131135
btchip_write_u32_le(dataBuffer, lockTime);
132136
btchip_write_u32_le(dataBuffer + 4, sighashType);
133-
PRINTF("--- ADD TO HASH FULL:\n%.*H\n", sizeof(dataBuffer), dataBuffer);
134-
cx_hash(&btchip_context_D.transactionHashFull.sha256.header, 0,
135-
dataBuffer, sizeof(dataBuffer), NULL, 0);
137+
#ifdef HAVE_QTUM_SUPPORT
138+
if(btchip_context_D.signOpSender)
139+
{
140+
btchip_hash_sender_finalize(dataBuffer, sizeof(dataBuffer));
141+
}
142+
else
143+
#endif
144+
{
145+
PRINTF("--- ADD TO HASH FULL:\n%.*H\n", sizeof(dataBuffer), dataBuffer);
146+
cx_hash(&btchip_context_D.transactionHashFull.sha256.header, 0,
147+
dataBuffer, sizeof(dataBuffer), NULL, 0);
148+
}
136149
}
137150

138151
// Check if the path needs to be enforced
@@ -179,13 +192,26 @@ void btchip_bagl_user_action_signtx(unsigned char confirming, unsigned char dire
179192
unsigned char hash[32];
180193
// Fetch the private key
181194
btchip_private_derive_keypair(btchip_context_D.transactionSummary.keyPath, 0, NULL, &private_key, NULL);
195+
#ifndef USE_NO_OVERWINTER
182196
if (btchip_context_D.usingOverwinter) {
183197
cx_hash(&btchip_context_D.transactionHashFull.blake2b.header, CX_LAST, hash, 0, hash, 32);
184198
}
185-
else {
199+
else
200+
#endif
201+
{
186202
cx_sha256_t localHash;
187-
cx_hash(&btchip_context_D.transactionHashFull.sha256.header, CX_LAST,
188-
hash, 0, hash, 32);
203+
#ifdef HAVE_QTUM_SUPPORT
204+
if(btchip_context_D.signOpSender)
205+
{
206+
cx_hash(&btchip_context_D.transactionOutputHash.header, CX_LAST,
207+
hash, 0, hash, 32);
208+
}
209+
else
210+
#endif
211+
{
212+
cx_hash(&btchip_context_D.transactionHashFull.sha256.header, CX_LAST,
213+
hash, 0, hash, 32);
214+
}
189215
PRINTF("Hash1\n%.*H\n", sizeof(hash), hash);
190216

191217
// Rehash

0 commit comments

Comments
 (0)