1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-26 17:38:39 +00:00

update protobuf, disable SimpleSignTx

This commit is contained in:
Pavol Rusnak 2014-06-05 23:45:01 +02:00
parent 80ab3b40b4
commit 7cba60895d
13 changed files with 194 additions and 294 deletions

View File

@ -343,131 +343,6 @@ void fsm_msgSignTx(SignTx *msg)
signing_init(msg->inputs_count, msg->outputs_count, coin, node); signing_init(msg->inputs_count, msg->outputs_count, coin, node);
} }
void fsm_msgSimpleSignTx(SimpleSignTx *msg)
{
RESP_INIT(TxRequest);
if (msg->inputs_count < 1) {
fsm_sendFailure(FailureType_Failure_Other, "Transaction must have at least one input");
layoutHome();
return;
}
if (msg->outputs_count < 1) {
fsm_sendFailure(FailureType_Failure_Other, "Transaction must have at least one output");
layoutHome();
return;
}
if (!protectPin(true)) {
layoutHome();
return;
}
HDNode *node = fsm_getRootNode();
if (!node) return;
const CoinType *coin = coinByName(msg->coin_name);
if (!coin) {
fsm_sendFailure(FailureType_Failure_Other, "Invalid coin name");
layoutHome();
return;
}
uint32_t version = 1;
uint32_t lock_time = 0;
int tx_size = transactionSimpleSign(coin, node, msg->inputs, msg->inputs_count, msg->outputs, msg->outputs_count, version, lock_time, resp->serialized.serialized_tx.bytes);
if (tx_size < 0) {
fsm_sendFailure(FailureType_Failure_Other, "Signing cancelled by user");
layoutHome();
return;
}
if (tx_size == 0) {
fsm_sendFailure(FailureType_Failure_Other, "Error signing transaction");
layoutHome();
return;
}
size_t i, j;
// determine change address
uint64_t change_spend = 0;
for (i = 0; i < msg->outputs_count; i++) {
if (msg->outputs[i].address_n_count > 0) { // address_n set -> change address
if (change_spend == 0) { // not set
change_spend = msg->outputs[i].amount;
} else {
fsm_sendFailure(FailureType_Failure_Other, "Only one change output allowed");
layoutHome();
return;
}
}
}
// check origin transactions
uint8_t prev_hashes[ pb_arraysize(SimpleSignTx, transactions) ][32];
for (i = 0; i < msg->transactions_count; i++) {
if (!transactionHash(&(msg->transactions[i]), prev_hashes[i])) {
memset(prev_hashes[i], 0, 32);
}
}
// calculate spendings
uint64_t to_spend = 0;
bool found;
for (i = 0; i < msg->inputs_count; i++) {
found = false;
for (j = 0; j < msg->transactions_count; j++) {
if (memcmp(msg->inputs[i].prev_hash.bytes, prev_hashes[j], 32) == 0) { // found prev TX
if (msg->inputs[i].prev_index < msg->transactions[j].bin_outputs_count) {
to_spend += msg->transactions[j].bin_outputs[msg->inputs[i].prev_index].amount;
found = true;
break;
}
}
}
if (!found) {
fsm_sendFailure(FailureType_Failure_Other, "Invalid prevhash");
layoutHome();
return;
}
}
uint64_t spending = 0;
for (i = 0; i < msg->outputs_count; i++) {
spending += msg->outputs[i].amount;
}
if (spending > to_spend) {
fsm_sendFailure(FailureType_Failure_NotEnoughFunds, "Not enough funds");
layoutHome();
return;
}
uint64_t fee = to_spend - spending;
if (fee > (((uint64_t)tx_size + 999) / 1000) * coin->maxfee_kb) {
layoutFeeOverThreshold(coin, fee, ((uint64_t)tx_size + 999) / 1000);
if (!protectButton(ButtonRequestType_ButtonRequest_FeeOverThreshold, false)) {
fsm_sendFailure(FailureType_Failure_ActionCancelled, "Fee over threshold. Signing cancelled.");
layoutHome();
return;
}
}
// last confirmation
layoutConfirmTx(coin, to_spend - change_spend - fee, fee);
if (!protectButton(ButtonRequestType_ButtonRequest_SignTx, false)) {
fsm_sendFailure(FailureType_Failure_ActionCancelled, "Signing cancelled by user");
} else {
resp->has_request_type = true;
resp->request_type = RequestType_TXFINISHED;
resp->has_serialized = true;
resp->serialized.has_serialized_tx = true;
resp->serialized.serialized_tx.size = (uint32_t)tx_size;
msg_write(MessageType_MessageType_TxRequest, resp);
}
layoutHome();
}
void fsm_msgCancel(Cancel *msg) void fsm_msgCancel(Cancel *msg)
{ {
(void)msg; (void)msg;
@ -636,9 +511,9 @@ void fsm_msgDebugLinkGetState(DebugLinkGetState *msg)
(void)msg; (void)msg;
RESP_INIT(DebugLinkState); RESP_INIT(DebugLinkState);
// resp->has_layout = true; resp->has_layout = true;
// resp->layout.size = OLED_BUFSIZE; resp->layout.size = OLED_BUFSIZE;
// memcpy(resp->layout.bytes, oledGetBuffer(), OLED_BUFSIZE); memcpy(resp->layout.bytes, oledGetBuffer(), OLED_BUFSIZE);
if (storage.has_pin) { if (storage.has_pin) {
resp->has_pin = true; resp->has_pin = true;

View File

@ -38,7 +38,6 @@ void fsm_msgGetPublicKey(GetPublicKey *msg);
void fsm_msgLoadDevice(LoadDevice *msg); void fsm_msgLoadDevice(LoadDevice *msg);
void fsm_msgResetDevice(ResetDevice *msg); void fsm_msgResetDevice(ResetDevice *msg);
void fsm_msgSignTx(SignTx *msg); void fsm_msgSignTx(SignTx *msg);
void fsm_msgSimpleSignTx(SimpleSignTx *msg);
//void fsm_msgPinMatrixAck(PinMatrixAck *msg); //void fsm_msgPinMatrixAck(PinMatrixAck *msg);
void fsm_msgCancel(Cancel *msg); void fsm_msgCancel(Cancel *msg);
void fsm_msgTxAck(TxAck *msg); void fsm_msgTxAck(TxAck *msg);

View File

@ -29,11 +29,6 @@
#include "pb_encode.h" #include "pb_encode.h"
#include "messages.pb.h" #include "messages.pb.h"
// SimpleSignTx_size is the largest message we operate with
#if MSG_IN_SIZE < SimpleSignTx_size
#error "MSG_IN_SIZE is too small!"
#endif
struct MessagesMap_t { struct MessagesMap_t {
char type; // n = normal, d = debug char type; // n = normal, d = debug
char dir; // i = in, o = out char dir; // i = in, o = out
@ -55,7 +50,6 @@ static const struct MessagesMap_t MessagesMap[] = {
{'n', 'i', MessageType_MessageType_LoadDevice, LoadDevice_fields, (void (*)(void *))fsm_msgLoadDevice}, {'n', 'i', MessageType_MessageType_LoadDevice, LoadDevice_fields, (void (*)(void *))fsm_msgLoadDevice},
{'n', 'i', MessageType_MessageType_ResetDevice, ResetDevice_fields, (void (*)(void *))fsm_msgResetDevice}, {'n', 'i', MessageType_MessageType_ResetDevice, ResetDevice_fields, (void (*)(void *))fsm_msgResetDevice},
{'n', 'i', MessageType_MessageType_SignTx, SignTx_fields, (void (*)(void *))fsm_msgSignTx}, {'n', 'i', MessageType_MessageType_SignTx, SignTx_fields, (void (*)(void *))fsm_msgSignTx},
{'n', 'i', MessageType_MessageType_SimpleSignTx, SimpleSignTx_fields, (void (*)(void *))fsm_msgSimpleSignTx},
// {'n', 'i', MessageType_MessageType_PinMatrixAck, PinMatrixAck_fields, (void (*)(void *))fsm_msgPinMatrixAck}, // {'n', 'i', MessageType_MessageType_PinMatrixAck, PinMatrixAck_fields, (void (*)(void *))fsm_msgPinMatrixAck},
{'n', 'i', MessageType_MessageType_Cancel, Cancel_fields, (void (*)(void *))fsm_msgCancel}, {'n', 'i', MessageType_MessageType_Cancel, Cancel_fields, (void (*)(void *))fsm_msgCancel},
{'n', 'i', MessageType_MessageType_TxAck, TxAck_fields, (void (*)(void *))fsm_msgTxAck}, {'n', 'i', MessageType_MessageType_TxAck, TxAck_fields, (void (*)(void *))fsm_msgTxAck},

View File

@ -24,7 +24,7 @@
#include <stdbool.h> #include <stdbool.h>
#include "trezor.h" #include "trezor.h"
#define MSG_IN_SIZE (24*1024) #define MSG_IN_SIZE (9*1024)
#define MSG_OUT_SIZE (9*1024) #define MSG_OUT_SIZE (9*1024)
@ -34,7 +34,7 @@ uint8_t *msg_out_data(void);
#if DEBUG_LINK #if DEBUG_LINK
#define MSG_DEBUG_OUT_SIZE (2*1024) #define MSG_DEBUG_OUT_SIZE (4*1024)
#define msg_debug_read(buf, len) msg_read_common('d', (buf), (len)) #define msg_debug_read(buf, len) msg_read_common('d', (buf), (len))
#define msg_debug_write(id, ptr) msg_write_common('d', (id), (ptr)) #define msg_debug_write(id, ptr) msg_write_common('d', (id), (ptr))

View File

@ -12,6 +12,7 @@ ApplySettings.label max_size:33
Ping.message max_size:256 Ping.message max_size:256
Success.message max_size:256 Success.message max_size:256
Success.payload max_size:1024
Failure.message max_size:256 Failure.message max_size:256
@ -56,16 +57,26 @@ VerifyMessage.message max_size:256
MessageSignature.address max_size:35 MessageSignature.address max_size:35
MessageSignature.signature max_size:65 MessageSignature.signature max_size:65
EncryptKeyValue.address_n max_count:8
EncryptKeyValue.key max_size:256
EncryptKeyValue.value max_size:1024
DecryptKeyValue.address_n max_count:8
DecryptKeyValue.key max_size:256
DecryptKeyValue.value max_size:1024
EstimateTxSize.coin_name max_size:17 EstimateTxSize.coin_name max_size:17
SignTx.coin_name max_size:17 SignTx.coin_name max_size:17
SimpleSignTx.inputs max_count:4 # not used in firmware
SimpleSignTx.outputs max_count:4 SimpleSignTx.inputs max_count:0
SimpleSignTx.transactions max_count:4 SimpleSignTx.outputs max_count:0
SimpleSignTx.transactions max_count:0
SimpleSignTx.coin_name max_size:17 SimpleSignTx.coin_name max_size:17
FirmwareUpload.payload max_size:0 # not used in firmware # not used in firmware
FirmwareUpload.payload max_size:0
DebugLinkState.layout max_size:1024 DebugLinkState.layout max_size:1024
DebugLinkState.pin max_size:10 DebugLinkState.pin max_size:10

View File

@ -56,8 +56,9 @@ const pb_field_t Ping_fields[5] = {
PB_LAST_FIELD PB_LAST_FIELD
}; };
const pb_field_t Success_fields[2] = { const pb_field_t Success_fields[3] = {
PB_FIELD2( 1, STRING , OPTIONAL, STATIC , FIRST, Success, message, message, 0), PB_FIELD2( 1, STRING , OPTIONAL, STATIC , FIRST, Success, message, message, 0),
PB_FIELD2( 2, BYTES , OPTIONAL, STATIC , OTHER, Success, payload, message, 0),
PB_LAST_FIELD PB_LAST_FIELD
}; };
@ -204,6 +205,20 @@ const pb_field_t MessageSignature_fields[3] = {
PB_LAST_FIELD PB_LAST_FIELD
}; };
const pb_field_t EncryptKeyValue_fields[4] = {
PB_FIELD2( 1, UINT32 , REPEATED, STATIC , FIRST, EncryptKeyValue, address_n, address_n, 0),
PB_FIELD2( 2, STRING , OPTIONAL, STATIC , OTHER, EncryptKeyValue, key, address_n, 0),
PB_FIELD2( 3, BYTES , OPTIONAL, STATIC , OTHER, EncryptKeyValue, value, key, 0),
PB_LAST_FIELD
};
const pb_field_t DecryptKeyValue_fields[4] = {
PB_FIELD2( 1, UINT32 , REPEATED, STATIC , FIRST, DecryptKeyValue, address_n, address_n, 0),
PB_FIELD2( 2, STRING , OPTIONAL, STATIC , OTHER, DecryptKeyValue, key, address_n, 0),
PB_FIELD2( 3, BYTES , OPTIONAL, STATIC , OTHER, DecryptKeyValue, value, key, 0),
PB_LAST_FIELD
};
const pb_field_t EstimateTxSize_fields[4] = { const pb_field_t EstimateTxSize_fields[4] = {
PB_FIELD2( 1, UINT32 , REQUIRED, STATIC , FIRST, EstimateTxSize, outputs_count, outputs_count, 0), PB_FIELD2( 1, UINT32 , REQUIRED, STATIC , FIRST, EstimateTxSize, outputs_count, outputs_count, 0),
PB_FIELD2( 2, UINT32 , REQUIRED, STATIC , OTHER, EstimateTxSize, inputs_count, outputs_count, 0), PB_FIELD2( 2, UINT32 , REQUIRED, STATIC , OTHER, EstimateTxSize, inputs_count, outputs_count, 0),
@ -296,11 +311,11 @@ const pb_field_t DebugLinkLog_fields[4] = {
* numbers or field sizes that are larger than what can fit in 8 or 16 bit * numbers or field sizes that are larger than what can fit in 8 or 16 bit
* field descriptors. * field descriptors.
*/ */
STATIC_ASSERT((pb_membersize(Features, coins[0]) < 65536 && pb_membersize(PublicKey, node) < 65536 && pb_membersize(LoadDevice, node) < 65536 && pb_membersize(SimpleSignTx, inputs[0]) < 65536 && pb_membersize(SimpleSignTx, outputs[0]) < 65536 && pb_membersize(SimpleSignTx, transactions[0]) < 65536 && pb_membersize(TxRequest, details) < 65536 && pb_membersize(TxRequest, serialized) < 65536 && pb_membersize(TxAck, tx) < 65536 && pb_membersize(DebugLinkState, node) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_Initialize_Features_ApplySettings_ChangePin_Ping_Success_Failure_ButtonRequest_ButtonAck_PinMatrixRequest_PinMatrixAck_Cancel_PassphraseRequest_PassphraseAck_GetEntropy_Entropy_GetPublicKey_PublicKey_GetAddress_Address_WipeDevice_LoadDevice_ResetDevice_EntropyRequest_EntropyAck_RecoveryDevice_WordRequest_WordAck_SignMessage_VerifyMessage_MessageSignature_EstimateTxSize_TxSize_SignTx_SimpleSignTx_TxRequest_TxAck_FirmwareErase_FirmwareUpload_DebugLinkDecision_DebugLinkGetState_DebugLinkState_DebugLinkStop_DebugLinkLog) STATIC_ASSERT((pb_membersize(Features, coins[0]) < 65536 && pb_membersize(PublicKey, node) < 65536 && pb_membersize(LoadDevice, node) < 65536 && pb_membersize(SimpleSignTx, inputs[0]) < 65536 && pb_membersize(SimpleSignTx, outputs[0]) < 65536 && pb_membersize(SimpleSignTx, transactions[0]) < 65536 && pb_membersize(TxRequest, details) < 65536 && pb_membersize(TxRequest, serialized) < 65536 && pb_membersize(TxAck, tx) < 65536 && pb_membersize(DebugLinkState, node) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_Initialize_Features_ApplySettings_ChangePin_Ping_Success_Failure_ButtonRequest_ButtonAck_PinMatrixRequest_PinMatrixAck_Cancel_PassphraseRequest_PassphraseAck_GetEntropy_Entropy_GetPublicKey_PublicKey_GetAddress_Address_WipeDevice_LoadDevice_ResetDevice_EntropyRequest_EntropyAck_RecoveryDevice_WordRequest_WordAck_SignMessage_VerifyMessage_MessageSignature_EncryptKeyValue_DecryptKeyValue_EstimateTxSize_TxSize_SignTx_SimpleSignTx_TxRequest_TxAck_FirmwareErase_FirmwareUpload_DebugLinkDecision_DebugLinkGetState_DebugLinkState_DebugLinkStop_DebugLinkLog)
#endif #endif
#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) #if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
#error Field descriptor for Entropy.entropy is too large. Define PB_FIELD_16BIT to fix this. #error Field descriptor for Success.payload is too large. Define PB_FIELD_16BIT to fix this.
#endif #endif

View File

@ -34,6 +34,8 @@ typedef enum _MessageType {
MessageType_MessageType_Cancel = 20, MessageType_MessageType_Cancel = 20,
MessageType_MessageType_TxRequest = 21, MessageType_MessageType_TxRequest = 21,
MessageType_MessageType_TxAck = 22, MessageType_MessageType_TxAck = 22,
MessageType_MessageType_EncryptKeyValue = 23,
MessageType_MessageType_DecryptKeyValue = 24,
MessageType_MessageType_ApplySettings = 25, MessageType_MessageType_ApplySettings = 25,
MessageType_MessageType_ButtonRequest = 26, MessageType_MessageType_ButtonRequest = 26,
MessageType_MessageType_ButtonAck = 27, MessageType_MessageType_ButtonAck = 27,
@ -168,6 +170,34 @@ typedef struct _DebugLinkState {
uint32_t recovery_word_pos; uint32_t recovery_word_pos;
} DebugLinkState; } DebugLinkState;
typedef struct {
size_t size;
uint8_t bytes[1024];
} DecryptKeyValue_value_t;
typedef struct _DecryptKeyValue {
size_t address_n_count;
uint32_t address_n[8];
bool has_key;
char key[256];
bool has_value;
DecryptKeyValue_value_t value;
} DecryptKeyValue;
typedef struct {
size_t size;
uint8_t bytes[1024];
} EncryptKeyValue_value_t;
typedef struct _EncryptKeyValue {
size_t address_n_count;
uint32_t address_n[8];
bool has_key;
char key[256];
bool has_value;
EncryptKeyValue_value_t value;
} EncryptKeyValue;
typedef struct { typedef struct {
size_t size; size_t size;
uint8_t bytes[1024]; uint8_t bytes[1024];
@ -378,18 +408,25 @@ typedef struct _SignTx {
typedef struct _SimpleSignTx { typedef struct _SimpleSignTx {
size_t inputs_count; size_t inputs_count;
TxInputType inputs[4]; TxInputType inputs[0];
size_t outputs_count; size_t outputs_count;
TxOutputType outputs[4]; TxOutputType outputs[0];
size_t transactions_count; size_t transactions_count;
TransactionType transactions[4]; TransactionType transactions[0];
bool has_coin_name; bool has_coin_name;
char coin_name[17]; char coin_name[17];
} SimpleSignTx; } SimpleSignTx;
typedef struct {
size_t size;
uint8_t bytes[1024];
} Success_payload_t;
typedef struct _Success { typedef struct _Success {
bool has_message; bool has_message;
char message[256]; char message[256];
bool has_payload;
Success_payload_t payload;
} Success; } Success;
typedef struct _TxAck { typedef struct _TxAck {
@ -466,6 +503,12 @@ extern const char SimpleSignTx_coin_name_default[17];
#define DebugLinkState_reset_entropy_tag 8 #define DebugLinkState_reset_entropy_tag 8
#define DebugLinkState_recovery_fake_word_tag 9 #define DebugLinkState_recovery_fake_word_tag 9
#define DebugLinkState_recovery_word_pos_tag 10 #define DebugLinkState_recovery_word_pos_tag 10
#define DecryptKeyValue_address_n_tag 1
#define DecryptKeyValue_key_tag 2
#define DecryptKeyValue_value_tag 3
#define EncryptKeyValue_address_n_tag 1
#define EncryptKeyValue_key_tag 2
#define EncryptKeyValue_value_tag 3
#define Entropy_entropy_tag 1 #define Entropy_entropy_tag 1
#define EntropyAck_entropy_tag 1 #define EntropyAck_entropy_tag 1
#define EstimateTxSize_outputs_count_tag 1 #define EstimateTxSize_outputs_count_tag 1
@ -533,6 +576,7 @@ extern const char SimpleSignTx_coin_name_default[17];
#define SimpleSignTx_transactions_tag 3 #define SimpleSignTx_transactions_tag 3
#define SimpleSignTx_coin_name_tag 4 #define SimpleSignTx_coin_name_tag 4
#define Success_message_tag 1 #define Success_message_tag 1
#define Success_payload_tag 2
#define TxAck_tx_tag 1 #define TxAck_tx_tag 1
#define TxRequest_request_type_tag 1 #define TxRequest_request_type_tag 1
#define TxRequest_details_tag 2 #define TxRequest_details_tag 2
@ -549,7 +593,7 @@ extern const pb_field_t Features_fields[16];
extern const pb_field_t ApplySettings_fields[3]; extern const pb_field_t ApplySettings_fields[3];
extern const pb_field_t ChangePin_fields[2]; extern const pb_field_t ChangePin_fields[2];
extern const pb_field_t Ping_fields[5]; extern const pb_field_t Ping_fields[5];
extern const pb_field_t Success_fields[2]; extern const pb_field_t Success_fields[3];
extern const pb_field_t Failure_fields[3]; extern const pb_field_t Failure_fields[3];
extern const pb_field_t ButtonRequest_fields[3]; extern const pb_field_t ButtonRequest_fields[3];
extern const pb_field_t ButtonAck_fields[1]; extern const pb_field_t ButtonAck_fields[1];
@ -575,6 +619,8 @@ extern const pb_field_t WordAck_fields[2];
extern const pb_field_t SignMessage_fields[4]; extern const pb_field_t SignMessage_fields[4];
extern const pb_field_t VerifyMessage_fields[4]; extern const pb_field_t VerifyMessage_fields[4];
extern const pb_field_t MessageSignature_fields[3]; extern const pb_field_t MessageSignature_fields[3];
extern const pb_field_t EncryptKeyValue_fields[4];
extern const pb_field_t DecryptKeyValue_fields[4];
extern const pb_field_t EstimateTxSize_fields[4]; extern const pb_field_t EstimateTxSize_fields[4];
extern const pb_field_t TxSize_fields[2]; extern const pb_field_t TxSize_fields[2];
extern const pb_field_t SignTx_fields[4]; extern const pb_field_t SignTx_fields[4];
@ -595,7 +641,7 @@ extern const pb_field_t DebugLinkLog_fields[4];
#define ApplySettings_size 54 #define ApplySettings_size 54
#define ChangePin_size 2 #define ChangePin_size 2
#define Ping_size 265 #define Ping_size 265
#define Success_size 259 #define Success_size 1286
#define Failure_size 265 #define Failure_size 265
#define ButtonRequest_size 265 #define ButtonRequest_size 265
#define ButtonAck_size 0 #define ButtonAck_size 0
@ -621,10 +667,12 @@ extern const pb_field_t DebugLinkLog_fields[4];
#define SignMessage_size 326 #define SignMessage_size 326
#define VerifyMessage_size 363 #define VerifyMessage_size 363
#define MessageSignature_size 104 #define MessageSignature_size 104
#define EncryptKeyValue_size 1334
#define DecryptKeyValue_size 1334
#define EstimateTxSize_size 31 #define EstimateTxSize_size 31
#define TxSize_size 6 #define TxSize_size 6
#define SignTx_size 31 #define SignTx_size 31
#define SimpleSignTx_size (91 + 4*TxInputType_size + 4*TxOutputType_size + 4*TransactionType_size) #define SimpleSignTx_size (19 + 0*TxInputType_size + 0*TxOutputType_size + 0*TransactionType_size)
#define TxRequest_size (18 + TxRequestDetailsType_size + TxRequestSerializedType_size) #define TxRequest_size (18 + TxRequestDetailsType_size + TxRequestSerializedType_size)
#define TxAck_size (6 + TransactionType_size) #define TxAck_size (6 + TransactionType_size)
#define FirmwareErase_size 0 #define FirmwareErase_size 0

View File

@ -11,16 +11,19 @@ TxInputType.script_sig max_size:520
TxOutputType.address max_size:35 TxOutputType.address max_size:35
TxOutputType.address_n max_count:8 TxOutputType.address_n max_count:8
TxOutputType.script_args max_count:3
TxOutputType.script_args max_size:16
TxOutputBinType.script_pubkey max_size:256 TxOutputBinType.script_pubkey max_size:256
TransactionType.inputs max_count:8 TransactionType.inputs max_count:1
TransactionType.bin_outputs max_count:4 TransactionType.bin_outputs max_count:1
TransactionType.outputs max_count:4 TransactionType.outputs max_count:1
TxRequestDetailsType.tx_hash max_size:32 TxRequestDetailsType.tx_hash max_size:32
TxRequestSerializedType.signature max_size:80 TxRequestSerializedType.signature max_size:80
TxRequestSerializedType.serialized_tx max_size:1024 TxRequestSerializedType.serialized_tx max_size:1024
MultisigRedeemScriptType.pubkeys max_count:5
MultisigRedeemScriptType.pubkeys max_size:33
MultisigRedeemScriptType.signatures max_count:4
MultisigRedeemScriptType.signatures max_size:80

View File

@ -4,6 +4,7 @@
#include "types.pb.h" #include "types.pb.h"
const uint32_t TxInputType_sequence_default = 4294967295u; const uint32_t TxInputType_sequence_default = 4294967295u;
const InputScriptType TxInputType_script_type_default = InputScriptType_SPENDADDRESS;
const pb_field_t HDNodeType_fields[7] = { const pb_field_t HDNodeType_fields[7] = {
@ -24,21 +25,28 @@ const pb_field_t CoinType_fields[5] = {
PB_LAST_FIELD PB_LAST_FIELD
}; };
const pb_field_t TxInputType_fields[6] = { const pb_field_t MultisigRedeemScriptType_fields[3] = {
PB_FIELD2( 1, BYTES , REPEATED, STATIC , FIRST, MultisigRedeemScriptType, pubkeys, pubkeys, 0),
PB_FIELD2( 2, BYTES , REPEATED, STATIC , OTHER, MultisigRedeemScriptType, signatures, pubkeys, 0),
PB_LAST_FIELD
};
const pb_field_t TxInputType_fields[8] = {
PB_FIELD2( 1, UINT32 , REPEATED, STATIC , FIRST, TxInputType, address_n, address_n, 0), PB_FIELD2( 1, UINT32 , REPEATED, STATIC , FIRST, TxInputType, address_n, address_n, 0),
PB_FIELD2( 2, BYTES , REQUIRED, STATIC , OTHER, TxInputType, prev_hash, address_n, 0), PB_FIELD2( 2, BYTES , REQUIRED, STATIC , OTHER, TxInputType, prev_hash, address_n, 0),
PB_FIELD2( 3, UINT32 , REQUIRED, STATIC , OTHER, TxInputType, prev_index, prev_hash, 0), PB_FIELD2( 3, UINT32 , REQUIRED, STATIC , OTHER, TxInputType, prev_index, prev_hash, 0),
PB_FIELD2( 4, BYTES , OPTIONAL, STATIC , OTHER, TxInputType, script_sig, prev_index, 0), PB_FIELD2( 4, BYTES , OPTIONAL, STATIC , OTHER, TxInputType, script_sig, prev_index, 0),
PB_FIELD2( 5, UINT32 , OPTIONAL, STATIC , OTHER, TxInputType, sequence, script_sig, &TxInputType_sequence_default), PB_FIELD2( 5, UINT32 , OPTIONAL, STATIC , OTHER, TxInputType, sequence, script_sig, &TxInputType_sequence_default),
PB_FIELD2( 6, ENUM , OPTIONAL, STATIC , OTHER, TxInputType, script_type, sequence, &TxInputType_script_type_default),
PB_FIELD2( 7, MESSAGE , OPTIONAL, STATIC , OTHER, TxInputType, multisig, script_type, &MultisigRedeemScriptType_fields),
PB_LAST_FIELD PB_LAST_FIELD
}; };
const pb_field_t TxOutputType_fields[6] = { const pb_field_t TxOutputType_fields[5] = {
PB_FIELD2( 1, STRING , OPTIONAL, STATIC , FIRST, TxOutputType, address, address, 0), PB_FIELD2( 1, STRING , OPTIONAL, STATIC , FIRST, TxOutputType, address, address, 0),
PB_FIELD2( 2, UINT32 , REPEATED, STATIC , OTHER, TxOutputType, address_n, address, 0), PB_FIELD2( 2, UINT32 , REPEATED, STATIC , OTHER, TxOutputType, address_n, address, 0),
PB_FIELD2( 3, UINT64 , REQUIRED, STATIC , OTHER, TxOutputType, amount, address_n, 0), PB_FIELD2( 3, UINT64 , REQUIRED, STATIC , OTHER, TxOutputType, amount, address_n, 0),
PB_FIELD2( 4, ENUM , REQUIRED, STATIC , OTHER, TxOutputType, script_type, amount, 0), PB_FIELD2( 4, ENUM , REQUIRED, STATIC , OTHER, TxOutputType, script_type, amount, 0),
PB_FIELD2( 5, BYTES , REPEATED, STATIC , OTHER, TxOutputType, script_args, script_type, 0),
PB_LAST_FIELD PB_LAST_FIELD
}; };
@ -134,7 +142,7 @@ const pb_extension_type_t wire_debug_out = {
* numbers or field sizes that are larger than what can fit in 8 or 16 bit * numbers or field sizes that are larger than what can fit in 8 or 16 bit
* field descriptors. * field descriptors.
*/ */
STATIC_ASSERT((pb_membersize(TransactionType, inputs[0]) < 65536 && pb_membersize(TransactionType, bin_outputs[0]) < 65536 && pb_membersize(TransactionType, outputs[0]) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_HDNodeType_CoinType_TxInputType_TxOutputType_TxOutputBinType_TransactionType_TxRequestDetailsType_TxRequestSerializedType) STATIC_ASSERT((pb_membersize(TxInputType, multisig) < 65536 && pb_membersize(TransactionType, inputs[0]) < 65536 && pb_membersize(TransactionType, bin_outputs[0]) < 65536 && pb_membersize(TransactionType, outputs[0]) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_HDNodeType_CoinType_MultisigRedeemScriptType_TxInputType_TxOutputType_TxOutputBinType_TransactionType_TxRequestDetailsType_TxRequestSerializedType)
#endif #endif
#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) #if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)

View File

@ -24,10 +24,15 @@ typedef enum _FailureType {
FailureType_Failure_FirmwareError = 99 FailureType_Failure_FirmwareError = 99
} FailureType; } FailureType;
typedef enum _ScriptType { typedef enum _OutputScriptType {
ScriptType_PAYTOADDRESS = 0, OutputScriptType_PAYTOADDRESS = 0,
ScriptType_PAYTOSCRIPTHASH = 1 OutputScriptType_PAYTOSCRIPTHASH = 1
} ScriptType; } OutputScriptType;
typedef enum _InputScriptType {
InputScriptType_SPENDADDRESS = 0,
InputScriptType_SPENDMULTISIG = 1
} InputScriptType;
typedef enum _RequestType { typedef enum _RequestType {
RequestType_TXINPUT = 0, RequestType_TXINPUT = 0,
@ -93,24 +98,20 @@ typedef struct _HDNodeType {
typedef struct { typedef struct {
size_t size; size_t size;
uint8_t bytes[32]; uint8_t bytes[33];
} TxInputType_prev_hash_t; } MultisigRedeemScriptType_pubkeys_t;
typedef struct { typedef struct {
size_t size; size_t size;
uint8_t bytes[256]; uint8_t bytes[80];
} TxInputType_script_sig_t; } MultisigRedeemScriptType_signatures_t;
typedef struct _TxInputType { typedef struct _MultisigRedeemScriptType {
size_t address_n_count; size_t pubkeys_count;
uint32_t address_n[8]; MultisigRedeemScriptType_pubkeys_t pubkeys[5];
TxInputType_prev_hash_t prev_hash; size_t signatures_count;
uint32_t prev_index; MultisigRedeemScriptType_signatures_t signatures[4];
bool has_script_sig; } MultisigRedeemScriptType;
TxInputType_script_sig_t script_sig;
bool has_sequence;
uint32_t sequence;
} TxInputType;
typedef struct { typedef struct {
size_t size; size_t size;
@ -122,20 +123,13 @@ typedef struct _TxOutputBinType {
TxOutputBinType_script_pubkey_t script_pubkey; TxOutputBinType_script_pubkey_t script_pubkey;
} TxOutputBinType; } TxOutputBinType;
typedef struct {
size_t size;
uint8_t bytes[16];
} TxOutputType_script_args_t;
typedef struct _TxOutputType { typedef struct _TxOutputType {
bool has_address; bool has_address;
char address[35]; char address[35];
size_t address_n_count; size_t address_n_count;
uint32_t address_n[8]; uint32_t address_n[8];
uint64_t amount; uint64_t amount;
ScriptType script_type; OutputScriptType script_type;
size_t script_args_count;
TxOutputType_script_args_t script_args[3];
} TxOutputType; } TxOutputType;
typedef struct { typedef struct {
@ -169,17 +163,42 @@ typedef struct _TxRequestSerializedType {
TxRequestSerializedType_serialized_tx_t serialized_tx; TxRequestSerializedType_serialized_tx_t serialized_tx;
} TxRequestSerializedType; } TxRequestSerializedType;
typedef struct {
size_t size;
uint8_t bytes[32];
} TxInputType_prev_hash_t;
typedef struct {
size_t size;
uint8_t bytes[520];
} TxInputType_script_sig_t;
typedef struct _TxInputType {
size_t address_n_count;
uint32_t address_n[8];
TxInputType_prev_hash_t prev_hash;
uint32_t prev_index;
bool has_script_sig;
TxInputType_script_sig_t script_sig;
bool has_sequence;
uint32_t sequence;
bool has_script_type;
InputScriptType script_type;
bool has_multisig;
MultisigRedeemScriptType multisig;
} TxInputType;
typedef struct _TransactionType { typedef struct _TransactionType {
bool has_version; bool has_version;
uint32_t version; uint32_t version;
size_t inputs_count; size_t inputs_count;
TxInputType inputs[8]; TxInputType inputs[1];
size_t bin_outputs_count; size_t bin_outputs_count;
TxOutputBinType bin_outputs[4]; TxOutputBinType bin_outputs[1];
bool has_lock_time; bool has_lock_time;
uint32_t lock_time; uint32_t lock_time;
size_t outputs_count; size_t outputs_count;
TxOutputType outputs[4]; TxOutputType outputs[1];
bool has_inputs_cnt; bool has_inputs_cnt;
uint32_t inputs_cnt; uint32_t inputs_cnt;
bool has_outputs_cnt; bool has_outputs_cnt;
@ -194,6 +213,7 @@ extern const pb_extension_type_t wire_debug_out;
/* Default values for struct fields */ /* Default values for struct fields */
extern const uint32_t TxInputType_sequence_default; extern const uint32_t TxInputType_sequence_default;
extern const InputScriptType TxInputType_script_type_default;
/* Field tags (for use in manual encoding/decoding) */ /* Field tags (for use in manual encoding/decoding) */
#define CoinType_coin_name_tag 1 #define CoinType_coin_name_tag 1
@ -206,23 +226,26 @@ extern const uint32_t TxInputType_sequence_default;
#define HDNodeType_chain_code_tag 4 #define HDNodeType_chain_code_tag 4
#define HDNodeType_private_key_tag 5 #define HDNodeType_private_key_tag 5
#define HDNodeType_public_key_tag 6 #define HDNodeType_public_key_tag 6
#define TxInputType_address_n_tag 1 #define MultisigRedeemScriptType_pubkeys_tag 1
#define TxInputType_prev_hash_tag 2 #define MultisigRedeemScriptType_signatures_tag 2
#define TxInputType_prev_index_tag 3
#define TxInputType_script_sig_tag 4
#define TxInputType_sequence_tag 5
#define TxOutputBinType_amount_tag 1 #define TxOutputBinType_amount_tag 1
#define TxOutputBinType_script_pubkey_tag 2 #define TxOutputBinType_script_pubkey_tag 2
#define TxOutputType_address_tag 1 #define TxOutputType_address_tag 1
#define TxOutputType_address_n_tag 2 #define TxOutputType_address_n_tag 2
#define TxOutputType_amount_tag 3 #define TxOutputType_amount_tag 3
#define TxOutputType_script_type_tag 4 #define TxOutputType_script_type_tag 4
#define TxOutputType_script_args_tag 5
#define TxRequestDetailsType_request_index_tag 1 #define TxRequestDetailsType_request_index_tag 1
#define TxRequestDetailsType_tx_hash_tag 2 #define TxRequestDetailsType_tx_hash_tag 2
#define TxRequestSerializedType_signature_index_tag 1 #define TxRequestSerializedType_signature_index_tag 1
#define TxRequestSerializedType_signature_tag 2 #define TxRequestSerializedType_signature_tag 2
#define TxRequestSerializedType_serialized_tx_tag 3 #define TxRequestSerializedType_serialized_tx_tag 3
#define TxInputType_address_n_tag 1
#define TxInputType_prev_hash_tag 2
#define TxInputType_prev_index_tag 3
#define TxInputType_script_sig_tag 4
#define TxInputType_sequence_tag 5
#define TxInputType_script_type_tag 6
#define TxInputType_multisig_tag 7
#define TransactionType_version_tag 1 #define TransactionType_version_tag 1
#define TransactionType_inputs_tag 2 #define TransactionType_inputs_tag 2
#define TransactionType_bin_outputs_tag 3 #define TransactionType_bin_outputs_tag 3
@ -238,8 +261,9 @@ extern const uint32_t TxInputType_sequence_default;
/* Struct field encoding specification for nanopb */ /* Struct field encoding specification for nanopb */
extern const pb_field_t HDNodeType_fields[7]; extern const pb_field_t HDNodeType_fields[7];
extern const pb_field_t CoinType_fields[5]; extern const pb_field_t CoinType_fields[5];
extern const pb_field_t TxInputType_fields[6]; extern const pb_field_t MultisigRedeemScriptType_fields[3];
extern const pb_field_t TxOutputType_fields[6]; extern const pb_field_t TxInputType_fields[8];
extern const pb_field_t TxOutputType_fields[5];
extern const pb_field_t TxOutputBinType_fields[3]; extern const pb_field_t TxOutputBinType_fields[3];
extern const pb_field_t TransactionType_fields[8]; extern const pb_field_t TransactionType_fields[8];
extern const pb_field_t TxRequestDetailsType_fields[3]; extern const pb_field_t TxRequestDetailsType_fields[3];
@ -248,10 +272,11 @@ extern const pb_field_t TxRequestSerializedType_fields[4];
/* Maximum encoded size of messages (where known) */ /* Maximum encoded size of messages (where known) */
#define HDNodeType_size 121 #define HDNodeType_size 121
#define CoinType_size 47 #define CoinType_size 47
#define TxInputType_size 353 #define MultisigRedeemScriptType_size 503
#define TxOutputType_size 156 #define TxInputType_size 1129
#define TxOutputType_size 102
#define TxOutputBinType_size 270 #define TxOutputBinType_size 270
#define TransactionType_size 4600 #define TransactionType_size 1533
#define TxRequestDetailsType_size 40 #define TxRequestDetailsType_size 40
#define TxRequestSerializedType_size 1115 #define TxRequestSerializedType_size 1115

View File

@ -98,7 +98,7 @@ int compile_output(const CoinType *coin, const HDNode *root, TxOutputType *in, T
memset(out, 0, sizeof(TxOutputBinType)); memset(out, 0, sizeof(TxOutputBinType));
out->amount = in->amount; out->amount = in->amount;
if (in->script_type == ScriptType_PAYTOADDRESS) { if (in->script_type == OutputScriptType_PAYTOADDRESS) {
out->script_pubkey.bytes[0] = 0x76; // OP_DUP out->script_pubkey.bytes[0] = 0x76; // OP_DUP
out->script_pubkey.bytes[1] = 0xA9; // OP_HASH_160 out->script_pubkey.bytes[1] = 0xA9; // OP_HASH_160
out->script_pubkey.bytes[2] = 0x14; // pushing 20 bytes out->script_pubkey.bytes[2] = 0x14; // pushing 20 bytes
@ -113,7 +113,7 @@ int compile_output(const CoinType *coin, const HDNode *root, TxOutputType *in, T
return 25; return 25;
} }
if (in->script_type == ScriptType_PAYTOSCRIPTHASH) { if (in->script_type == OutputScriptType_PAYTOSCRIPTHASH) {
out->script_pubkey.bytes[0] = 0xA9; // OP_HASH_160 out->script_pubkey.bytes[0] = 0xA9; // OP_HASH_160
out->script_pubkey.bytes[1] = 0x14; // pushing 20 bytes out->script_pubkey.bytes[1] = 0x14; // pushing 20 bytes
uint8_t decoded[21]; uint8_t decoded[21];
@ -275,80 +275,6 @@ void tx_hash_final(TxStruct *t, uint8_t *hash, bool reverse)
} }
} }
bool transactionHash(TransactionType *tx, uint8_t *hash)
{
TxStruct t;
uint32_t i;
tx_init(&t, tx->inputs_count, tx->bin_outputs_count, tx->version, tx->lock_time, false);
for (i = 0; i < tx->inputs_count; i++) {
if (!tx_hash_input(&t, &(tx->inputs[i]))) return false;
}
for (i = 0; i < tx->bin_outputs_count; i++) {
if (!tx_hash_output(&t, &(tx->bin_outputs[i]))) return false;
}
tx_hash_final(&t, hash, true);
return true;
}
int transactionSimpleSign(const CoinType *coin, HDNode *root, TxInputType *inputs, uint32_t inputs_count, TxOutputType *outputs, uint32_t outputs_count, uint32_t version, uint32_t lock_time, uint8_t *out)
{
uint32_t idx, i, k, r = 0;
TxStruct ti, to;
uint8_t buf[512];
TxInputType input;
TxOutputBinType output;
HDNode node;
uint8_t privkey[32], pubkey[33], hash[32], sig[64];
layoutProgressSwipe("Signing", 0, 0);
tx_init(&to, inputs_count, outputs_count, version, lock_time, false);
for (idx = 0; idx < inputs_count; idx++) {
// compute inner transaction
memcpy(&input, &(inputs[idx]), sizeof(TxInputType));
tx_init(&ti, inputs_count, outputs_count, version, lock_time, true);
memset(privkey, 0, 32);
memset(pubkey, 0, 33);
for (i = 0; i < inputs_count; i++) {
if (i == idx) {
memcpy(&node, root, sizeof(HDNode));
for (k = 0; k < inputs[i].address_n_count; k++) {
hdnode_private_ckd(&node, inputs[i].address_n[k]);
}
ecdsa_get_pubkeyhash(node.public_key, hash);
inputs[i].script_sig.size = compile_script_sig(coin->address_type, hash, inputs[i].script_sig.bytes);
if (inputs[i].script_sig.size == 0) {
return 0;
}
memcpy(privkey, node.private_key, 32);
memcpy(pubkey, node.public_key, 33);
} else {
inputs[i].script_sig.size = 0;
}
if (!tx_hash_input(&ti, &(inputs[i]))) return 0;
}
for (i = 0; i < outputs_count; i++) {
int co = compile_output(coin, root, &(outputs[i]), &output, idx == 0);
if (co <= 0) {
return co;
}
if (!tx_hash_output(&ti, &output)) return 0;
}
tx_hash_final(&ti, hash, false);
ecdsa_sign_digest(privkey, hash, sig);
int der_len = ecdsa_sig_to_der(sig, buf);
input.script_sig.size = serialize_script_sig(buf, der_len, pubkey, 33, input.script_sig.bytes);
r += tx_serialize_input(&to, input.prev_hash.bytes, input.prev_index, input.script_sig.bytes, input.script_sig.size, input.sequence, out + r);
layoutProgress("Signing", 1000 * idx / inputs_count, idx);
}
for (i = 0; i < outputs_count; i++) {
if (compile_output(coin, root, &(outputs[i]), &output, false) <= 0) {
return 0;
}
r += tx_serialize_output(&to, output.amount, output.script_pubkey.bytes, output.script_pubkey.size, out + r);
}
return r;
}
uint32_t transactionEstimateSize(uint32_t inputs, uint32_t outputs) uint32_t transactionEstimateSize(uint32_t inputs, uint32_t outputs)
{ {
return 10 + inputs * 149 + outputs * 35; return 10 + inputs * 149 + outputs * 35;

View File

@ -52,10 +52,6 @@ bool tx_hash_input(TxStruct *t, TxInputType *input);
bool tx_hash_output(TxStruct *t, TxOutputBinType *output); bool tx_hash_output(TxStruct *t, TxOutputBinType *output);
void tx_hash_final(TxStruct *t, uint8_t *hash, bool reverse); void tx_hash_final(TxStruct *t, uint8_t *hash, bool reverse);
bool transactionHash(TransactionType *tx, uint8_t *hash);
int transactionSimpleSign(const CoinType *coin, HDNode *root, TxInputType *inputs, uint32_t inputs_count, TxOutputType *outputs, uint32_t outputs_count, uint32_t version, uint32_t lock_time, uint8_t *out);
uint32_t transactionEstimateSize(uint32_t inputs, uint32_t outputs); uint32_t transactionEstimateSize(uint32_t inputs, uint32_t outputs);
uint32_t transactionEstimateSizeKb(uint32_t inputs, uint32_t outputs); uint32_t transactionEstimateSizeKb(uint32_t inputs, uint32_t outputs);

@ -1 +1 @@
Subproject commit 1865a0428d1803416174f31a1d6b53b6632384a9 Subproject commit 06f4aee3fd45ec533e7e0e5a2ac06c98ae9975d6