mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-26 09:28:13 +00:00
implement TXEXTRADATA transaction RequestType
This commit is contained in:
parent
68a1bcc908
commit
c288a0e328
@ -21,6 +21,7 @@ TxOutputBinType.script_pubkey max_size:520
|
||||
TransactionType.inputs max_count:1
|
||||
TransactionType.bin_outputs max_count:1
|
||||
TransactionType.outputs max_count:1
|
||||
TransactionType.extra_data max_size:1024
|
||||
|
||||
TxRequestDetailsType.tx_hash max_size:32
|
||||
|
||||
|
@ -75,7 +75,7 @@ const pb_field_t TxOutputBinType_fields[3] = {
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
const pb_field_t TransactionType_fields[8] = {
|
||||
const pb_field_t TransactionType_fields[10] = {
|
||||
PB_FIELD2( 1, UINT32 , OPTIONAL, STATIC , FIRST, TransactionType, version, version, 0),
|
||||
PB_FIELD2( 2, MESSAGE , REPEATED, STATIC , OTHER, TransactionType, inputs, version, &TxInputType_fields),
|
||||
PB_FIELD2( 3, MESSAGE , REPEATED, STATIC , OTHER, TransactionType, bin_outputs, inputs, &TxOutputBinType_fields),
|
||||
@ -83,12 +83,16 @@ const pb_field_t TransactionType_fields[8] = {
|
||||
PB_FIELD2( 5, MESSAGE , REPEATED, STATIC , OTHER, TransactionType, outputs, lock_time, &TxOutputType_fields),
|
||||
PB_FIELD2( 6, UINT32 , OPTIONAL, STATIC , OTHER, TransactionType, inputs_cnt, outputs, 0),
|
||||
PB_FIELD2( 7, UINT32 , OPTIONAL, STATIC , OTHER, TransactionType, outputs_cnt, inputs_cnt, 0),
|
||||
PB_FIELD2( 8, BYTES , OPTIONAL, STATIC , OTHER, TransactionType, extra_data, outputs_cnt, 0),
|
||||
PB_FIELD2( 9, UINT32 , OPTIONAL, STATIC , OTHER, TransactionType, extra_data_len, extra_data, 0),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
const pb_field_t TxRequestDetailsType_fields[3] = {
|
||||
const pb_field_t TxRequestDetailsType_fields[5] = {
|
||||
PB_FIELD2( 1, UINT32 , OPTIONAL, STATIC , FIRST, TxRequestDetailsType, request_index, request_index, 0),
|
||||
PB_FIELD2( 2, BYTES , OPTIONAL, STATIC , OTHER, TxRequestDetailsType, tx_hash, request_index, 0),
|
||||
PB_FIELD2( 3, UINT32 , OPTIONAL, STATIC , OTHER, TxRequestDetailsType, extra_data_len, tx_hash, 0),
|
||||
PB_FIELD2( 4, UINT32 , OPTIONAL, STATIC , OTHER, TxRequestDetailsType, extra_data_offset, extra_data_len, 0),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
|
@ -45,7 +45,8 @@ typedef enum _RequestType {
|
||||
RequestType_TXINPUT = 0,
|
||||
RequestType_TXOUTPUT = 1,
|
||||
RequestType_TXMETA = 2,
|
||||
RequestType_TXFINISHED = 3
|
||||
RequestType_TXFINISHED = 3,
|
||||
RequestType_TXEXTRADATA = 4
|
||||
} RequestType;
|
||||
|
||||
typedef enum _ButtonRequestType {
|
||||
@ -149,6 +150,10 @@ typedef struct _TxRequestDetailsType {
|
||||
uint32_t request_index;
|
||||
bool has_tx_hash;
|
||||
TxRequestDetailsType_tx_hash_t tx_hash;
|
||||
bool has_extra_data_len;
|
||||
uint32_t extra_data_len;
|
||||
bool has_extra_data_offset;
|
||||
uint32_t extra_data_offset;
|
||||
} TxRequestDetailsType;
|
||||
|
||||
typedef struct {
|
||||
@ -235,6 +240,11 @@ typedef struct _TxOutputType {
|
||||
TxOutputType_op_return_data_t op_return_data;
|
||||
} TxOutputType;
|
||||
|
||||
typedef struct {
|
||||
size_t size;
|
||||
uint8_t bytes[1024];
|
||||
} TransactionType_extra_data_t;
|
||||
|
||||
typedef struct _TransactionType {
|
||||
bool has_version;
|
||||
uint32_t version;
|
||||
@ -250,6 +260,10 @@ typedef struct _TransactionType {
|
||||
uint32_t inputs_cnt;
|
||||
bool has_outputs_cnt;
|
||||
uint32_t outputs_cnt;
|
||||
bool has_extra_data;
|
||||
TransactionType_extra_data_t extra_data;
|
||||
bool has_extra_data_len;
|
||||
uint32_t extra_data_len;
|
||||
} TransactionType;
|
||||
|
||||
/* Extensions */
|
||||
@ -275,8 +289,8 @@ extern const uint32_t IdentityType_index_default;
|
||||
#define TxInputType_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}, {0, {0}}, 0, false, {0, {0}}, false, 4294967295u, false, InputScriptType_SPENDADDRESS, false, MultisigRedeemScriptType_init_default, false, 0}
|
||||
#define TxOutputType_init_default {false, "", 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, (OutputScriptType)0, false, MultisigRedeemScriptType_init_default, false, {0, {0}}}
|
||||
#define TxOutputBinType_init_default {0, {0, {0}}}
|
||||
#define TransactionType_init_default {false, 0, 0, {TxInputType_init_default}, 0, {TxOutputBinType_init_default}, false, 0, 0, {TxOutputType_init_default}, false, 0, false, 0}
|
||||
#define TxRequestDetailsType_init_default {false, 0, false, {0, {0}}}
|
||||
#define TransactionType_init_default {false, 0, 0, {TxInputType_init_default}, 0, {TxOutputBinType_init_default}, false, 0, 0, {TxOutputType_init_default}, false, 0, false, 0, false, {0, {0}}, false, 0}
|
||||
#define TxRequestDetailsType_init_default {false, 0, false, {0, {0}}, false, 0, false, 0}
|
||||
#define TxRequestSerializedType_init_default {false, 0, false, {0, {0}}, false, {0, {0}}}
|
||||
#define IdentityType_init_default {false, "", false, "", false, "", false, "", false, "", false, 0u}
|
||||
#define HDNodeType_init_zero {0, 0, 0, {0, {0}}, false, {0, {0}}, false, {0, {0}}}
|
||||
@ -286,8 +300,8 @@ extern const uint32_t IdentityType_index_default;
|
||||
#define TxInputType_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}, {0, {0}}, 0, false, {0, {0}}, false, 0, false, (InputScriptType)0, false, MultisigRedeemScriptType_init_zero, false, 0}
|
||||
#define TxOutputType_init_zero {false, "", 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, (OutputScriptType)0, false, MultisigRedeemScriptType_init_zero, false, {0, {0}}}
|
||||
#define TxOutputBinType_init_zero {0, {0, {0}}}
|
||||
#define TransactionType_init_zero {false, 0, 0, {TxInputType_init_zero}, 0, {TxOutputBinType_init_zero}, false, 0, 0, {TxOutputType_init_zero}, false, 0, false, 0}
|
||||
#define TxRequestDetailsType_init_zero {false, 0, false, {0, {0}}}
|
||||
#define TransactionType_init_zero {false, 0, 0, {TxInputType_init_zero}, 0, {TxOutputBinType_init_zero}, false, 0, 0, {TxOutputType_init_zero}, false, 0, false, 0, false, {0, {0}}, false, 0}
|
||||
#define TxRequestDetailsType_init_zero {false, 0, false, {0, {0}}, false, 0, false, 0}
|
||||
#define TxRequestSerializedType_init_zero {false, 0, false, {0, {0}}, false, {0, {0}}}
|
||||
#define IdentityType_init_zero {false, "", false, "", false, "", false, "", false, "", false, 0}
|
||||
|
||||
@ -316,6 +330,8 @@ extern const uint32_t IdentityType_index_default;
|
||||
#define TxOutputBinType_script_pubkey_tag 2
|
||||
#define TxRequestDetailsType_request_index_tag 1
|
||||
#define TxRequestDetailsType_tx_hash_tag 2
|
||||
#define TxRequestDetailsType_extra_data_len_tag 3
|
||||
#define TxRequestDetailsType_extra_data_offset_tag 4
|
||||
#define TxRequestSerializedType_signature_index_tag 1
|
||||
#define TxRequestSerializedType_signature_tag 2
|
||||
#define TxRequestSerializedType_serialized_tx_tag 3
|
||||
@ -345,6 +361,8 @@ extern const uint32_t IdentityType_index_default;
|
||||
#define TransactionType_lock_time_tag 4
|
||||
#define TransactionType_inputs_cnt_tag 6
|
||||
#define TransactionType_outputs_cnt_tag 7
|
||||
#define TransactionType_extra_data_tag 8
|
||||
#define TransactionType_extra_data_len_tag 9
|
||||
#define wire_in_tag 50002
|
||||
#define wire_out_tag 50003
|
||||
#define wire_debug_in_tag 50004
|
||||
@ -358,8 +376,8 @@ extern const pb_field_t MultisigRedeemScriptType_fields[4];
|
||||
extern const pb_field_t TxInputType_fields[9];
|
||||
extern const pb_field_t TxOutputType_fields[7];
|
||||
extern const pb_field_t TxOutputBinType_fields[3];
|
||||
extern const pb_field_t TransactionType_fields[8];
|
||||
extern const pb_field_t TxRequestDetailsType_fields[3];
|
||||
extern const pb_field_t TransactionType_fields[10];
|
||||
extern const pb_field_t TxRequestDetailsType_fields[5];
|
||||
extern const pb_field_t TxRequestSerializedType_fields[4];
|
||||
extern const pb_field_t IdentityType_fields[7];
|
||||
|
||||
@ -371,8 +389,8 @@ extern const pb_field_t IdentityType_fields[7];
|
||||
#define TxInputType_size 5508
|
||||
#define TxOutputType_size 3934
|
||||
#define TxOutputBinType_size 534
|
||||
#define TransactionType_size 10009
|
||||
#define TxRequestDetailsType_size 40
|
||||
#define TransactionType_size 11042
|
||||
#define TxRequestDetailsType_size 52
|
||||
#define TxRequestSerializedType_size 2132
|
||||
#define IdentityType_size 416
|
||||
|
||||
|
@ -38,6 +38,7 @@ enum {
|
||||
STAGE_REQUEST_2_PREV_META,
|
||||
STAGE_REQUEST_2_PREV_INPUT,
|
||||
STAGE_REQUEST_2_PREV_OUTPUT,
|
||||
STAGE_REQUEST_2_PREV_EXTRADATA,
|
||||
STAGE_REQUEST_3_OUTPUT,
|
||||
STAGE_REQUEST_4_INPUT,
|
||||
STAGE_REQUEST_4_OUTPUT,
|
||||
@ -85,6 +86,7 @@ foreach I (idx1):
|
||||
foreach prevhash O (idx2):
|
||||
Request prevhash O STAGE_REQUEST_2_PREV_OUTPUT
|
||||
Add amount of prevhash O (which is amount of I)
|
||||
Request prevhash extra data (if applicable) STAGE_REQUEST_2_PREV_EXTRADATA
|
||||
Calculate hash of streamed tx, compare to prevhash I
|
||||
foreach O (idx1):
|
||||
Request O STAGE_REQUEST_3_OUTPUT
|
||||
@ -173,6 +175,22 @@ void send_req_2_prev_output(void)
|
||||
msg_write(MessageType_MessageType_TxRequest, &resp);
|
||||
}
|
||||
|
||||
void send_req_2_prev_extradata(uint32_t chunk_offset, uint32_t chunk_len)
|
||||
{
|
||||
signing_stage = STAGE_REQUEST_2_PREV_EXTRADATA;
|
||||
resp.has_request_type = true;
|
||||
resp.request_type = RequestType_TXEXTRADATA;
|
||||
resp.has_details = true;
|
||||
resp.details.has_extra_data_offset = true;
|
||||
resp.details.extra_data_offset = chunk_offset;
|
||||
resp.details.has_extra_data_len = true;
|
||||
resp.details.extra_data_len = chunk_len;
|
||||
resp.details.has_tx_hash = true;
|
||||
resp.details.tx_hash.size = input.prev_hash.size;
|
||||
memcpy(resp.details.tx_hash.bytes, input.prev_hash.bytes, resp.details.tx_hash.size);
|
||||
msg_write(MessageType_MessageType_TxRequest, &resp);
|
||||
}
|
||||
|
||||
void send_req_3_output(void)
|
||||
{
|
||||
signing_stage = STAGE_REQUEST_3_OUTPUT;
|
||||
@ -249,7 +267,7 @@ void signing_init(uint32_t _inputs_count, uint32_t _outputs_count, const CoinTyp
|
||||
multisig_fp_set = false;
|
||||
multisig_fp_mismatch = false;
|
||||
|
||||
tx_init(&to, inputs_count, outputs_count, version, lock_time, false);
|
||||
tx_init(&to, inputs_count, outputs_count, version, lock_time, 0, false);
|
||||
sha256_Init(&tc);
|
||||
sha256_Update(&tc, (const uint8_t *)&inputs_count, sizeof(inputs_count));
|
||||
sha256_Update(&tc, (const uint8_t *)&outputs_count, sizeof(outputs_count));
|
||||
@ -261,6 +279,8 @@ void signing_init(uint32_t _inputs_count, uint32_t _outputs_count, const CoinTyp
|
||||
send_req_1_input();
|
||||
}
|
||||
|
||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
|
||||
void signing_txack(TransactionType *tx)
|
||||
{
|
||||
if (!signing) {
|
||||
@ -311,7 +331,7 @@ void signing_txack(TransactionType *tx)
|
||||
send_req_2_prev_meta();
|
||||
return;
|
||||
case STAGE_REQUEST_2_PREV_META:
|
||||
tx_init(&tp, tx->inputs_cnt, tx->outputs_cnt, tx->version, tx->lock_time, false);
|
||||
tx_init(&tp, tx->inputs_cnt, tx->outputs_cnt, tx->version, tx->lock_time, tx->extra_data_len, false);
|
||||
progress_meta_step = progress_step / (tp.inputs_len + tp.outputs_len);
|
||||
idx2 = 0;
|
||||
send_req_2_prev_input();
|
||||
@ -345,8 +365,35 @@ void signing_txack(TransactionType *tx)
|
||||
/* Check prevtx of next input */
|
||||
idx2++;
|
||||
send_req_2_prev_output();
|
||||
} else { // last output
|
||||
if (tp.extra_data_len > 0) { // has extra data
|
||||
send_req_2_prev_extradata(0, MIN(1024, tp.extra_data_len));
|
||||
return;
|
||||
}
|
||||
tx_hash_final(&tp, hash, true);
|
||||
if (memcmp(hash, input.prev_hash.bytes, 32) != 0) {
|
||||
fsm_sendFailure(FailureType_Failure_Other, "Encountered invalid prevhash");
|
||||
signing_abort();
|
||||
return;
|
||||
}
|
||||
if (idx1 < inputs_count - 1) {
|
||||
idx1++;
|
||||
send_req_1_input();
|
||||
} else {
|
||||
idx1 = 0;
|
||||
send_req_3_output();
|
||||
}
|
||||
}
|
||||
return;
|
||||
case STAGE_REQUEST_2_PREV_EXTRADATA:
|
||||
if (!tx_serialize_extra_data_hash(&tp, tx->extra_data.bytes, tx->extra_data.size)) {
|
||||
fsm_sendFailure(FailureType_Failure_Other, "Failed to serialize extra data");
|
||||
signing_abort();
|
||||
return;
|
||||
}
|
||||
if (tp.extra_data_received < tp.extra_data_len) { // still some data remanining
|
||||
send_req_2_prev_extradata(tp.extra_data_received, MIN(1024, tp.extra_data_len - tp.extra_data_received));
|
||||
} else {
|
||||
/* Check next output */
|
||||
tx_hash_final(&tp, hash, true);
|
||||
if (memcmp(hash, input.prev_hash.bytes, 32) != 0) {
|
||||
fsm_sendFailure(FailureType_Failure_Other, "Encountered invalid prevhash");
|
||||
@ -453,7 +500,7 @@ void signing_txack(TransactionType *tx)
|
||||
case STAGE_REQUEST_4_INPUT:
|
||||
progress = 500 + ((idx1 * progress_step + idx2 * progress_meta_step) >> PROGRESS_PRECISION);
|
||||
if (idx2 == 0) {
|
||||
tx_init(&ti, inputs_count, outputs_count, version, lock_time, true);
|
||||
tx_init(&ti, inputs_count, outputs_count, version, lock_time, 0, true);
|
||||
sha256_Init(&tc);
|
||||
sha256_Update(&tc, (const uint8_t *)&inputs_count, sizeof(inputs_count));
|
||||
sha256_Update(&tc, (const uint8_t *)&outputs_count, sizeof(outputs_count));
|
||||
|
@ -407,7 +407,27 @@ uint32_t tx_serialize_output_hash(TxStruct *tx, const TxOutputBinType *output)
|
||||
return r;
|
||||
}
|
||||
|
||||
void tx_init(TxStruct *tx, uint32_t inputs_len, uint32_t outputs_len, uint32_t version, uint32_t lock_time, bool add_hash_type)
|
||||
uint32_t tx_serialize_extra_data_hash(TxStruct *tx, const uint8_t *data, uint32_t datalen)
|
||||
{
|
||||
if (tx->have_inputs < tx->inputs_len) {
|
||||
// not all inputs provided
|
||||
return 0;
|
||||
}
|
||||
if (tx->have_outputs < tx->outputs_len) {
|
||||
// not all inputs provided
|
||||
return 0;
|
||||
}
|
||||
if (tx->extra_data_received + datalen > tx->extra_data_len) {
|
||||
// we are receiving too much data
|
||||
return 0;
|
||||
}
|
||||
sha256_Update(&(tx->ctx), data, datalen);
|
||||
tx->extra_data_received += datalen;
|
||||
tx->size += datalen;
|
||||
return datalen;
|
||||
}
|
||||
|
||||
void tx_init(TxStruct *tx, uint32_t inputs_len, uint32_t outputs_len, uint32_t version, uint32_t lock_time, uint32_t extra_data_len, bool add_hash_type)
|
||||
{
|
||||
tx->inputs_len = inputs_len;
|
||||
tx->outputs_len = outputs_len;
|
||||
@ -416,6 +436,8 @@ void tx_init(TxStruct *tx, uint32_t inputs_len, uint32_t outputs_len, uint32_t v
|
||||
tx->add_hash_type = add_hash_type;
|
||||
tx->have_inputs = 0;
|
||||
tx->have_outputs = 0;
|
||||
tx->extra_data_len = extra_data_len;
|
||||
tx->extra_data_received = 0;
|
||||
tx->size = 0;
|
||||
sha256_Init(&(tx->ctx));
|
||||
}
|
||||
|
@ -36,6 +36,10 @@ typedef struct {
|
||||
|
||||
uint32_t have_inputs;
|
||||
uint32_t have_outputs;
|
||||
|
||||
uint32_t extra_data_len;
|
||||
uint32_t extra_data_received;
|
||||
|
||||
uint32_t size;
|
||||
|
||||
SHA256_CTX ctx;
|
||||
@ -50,9 +54,10 @@ int compile_output(const CoinType *coin, const HDNode *root, TxOutputType *in, T
|
||||
uint32_t tx_serialize_input(TxStruct *tx, const TxInputType *input, uint8_t *out);
|
||||
uint32_t tx_serialize_output(TxStruct *tx, const TxOutputBinType *output, uint8_t *out);
|
||||
|
||||
void tx_init(TxStruct *tx, uint32_t inputs_len, uint32_t outputs_len, uint32_t version, uint32_t lock_time, bool add_hash_type);
|
||||
void tx_init(TxStruct *tx, uint32_t inputs_len, uint32_t outputs_len, uint32_t version, uint32_t lock_time, uint32_t extra_data_len, bool add_hash_type);
|
||||
uint32_t tx_serialize_input_hash(TxStruct *tx, const TxInputType *input);
|
||||
uint32_t tx_serialize_output_hash(TxStruct *tx, const TxOutputBinType *output);
|
||||
uint32_t tx_serialize_extra_data_hash(TxStruct *tx, const uint8_t *data, uint32_t datalen);
|
||||
void tx_hash_final(TxStruct *t, uint8_t *hash, bool reverse);
|
||||
|
||||
uint32_t transactionEstimateSize(uint32_t inputs, uint32_t outputs);
|
||||
|
2
vendor/trezor-common
vendored
2
vendor/trezor-common
vendored
@ -1 +1 @@
|
||||
Subproject commit 1e749523593506f2f268c038225f2c847ad2d0ef
|
||||
Subproject commit 20c1d05f9de778e28726690c4969e6ce92296ce4
|
Loading…
Reference in New Issue
Block a user