1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-22 22:38:08 +00:00
This commit is contained in:
Pavol Rusnak 2014-12-06 19:12:55 +01:00
parent a16e8c0e04
commit 91451f88b5
6 changed files with 90 additions and 13 deletions

View File

@ -29,9 +29,10 @@ const pb_field_t CoinType_fields[5] = {
PB_LAST_FIELD
};
const pb_field_t MultisigRedeemScriptType_fields[3] = {
const pb_field_t MultisigRedeemScriptType_fields[4] = {
PB_FIELD( 1, BYTES , REPEATED, STATIC , FIRST, MultisigRedeemScriptType, pubkeys, pubkeys, 0),
PB_FIELD( 2, BYTES , REPEATED, STATIC , OTHER, MultisigRedeemScriptType, signatures, pubkeys, 0),
PB_FIELD( 3, UINT32 , OPTIONAL, STATIC , OTHER, MultisigRedeemScriptType, m, signatures, 0),
PB_LAST_FIELD
};

View File

@ -102,6 +102,8 @@ typedef struct _MultisigRedeemScriptType {
MultisigRedeemScriptType_pubkeys_t pubkeys[5];
pb_size_t signatures_count;
MultisigRedeemScriptType_signatures_t signatures[4];
bool has_m;
uint32_t m;
} MultisigRedeemScriptType;
typedef PB_BYTES_ARRAY_T(520) TxOutputBinType_script_pubkey_t;
@ -191,7 +193,7 @@ extern const InputScriptType TxInputType_script_type_default;
/* Initializer values for message structs */
#define HDNodeType_init_default {0, 0, 0, {0, {0}}, false, {0, {0}}, false, {0, {0}}}
#define CoinType_init_default {false, "", false, "", false, 0, false, 0}
#define MultisigRedeemScriptType_init_default {0, {{0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}}, 0, {{0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}}}
#define MultisigRedeemScriptType_init_default {0, {{0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}}, 0, {{0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}}, false, 0}
#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}
#define TxOutputType_init_default {false, "", 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, (OutputScriptType)0}
#define TxOutputBinType_init_default {0, {0, {0}}}
@ -200,7 +202,7 @@ extern const InputScriptType TxInputType_script_type_default;
#define TxRequestSerializedType_init_default {false, 0, false, {0, {0}}, false, {0, {0}}}
#define HDNodeType_init_zero {0, 0, 0, {0, {0}}, false, {0, {0}}, false, {0, {0}}}
#define CoinType_init_zero {false, "", false, "", false, 0, false, 0}
#define MultisigRedeemScriptType_init_zero {0, {{0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}}, 0, {{0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}}}
#define MultisigRedeemScriptType_init_zero {0, {{0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}}, 0, {{0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}}, false, 0}
#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}
#define TxOutputType_init_zero {false, "", 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, (OutputScriptType)0}
#define TxOutputBinType_init_zero {0, {0, {0}}}
@ -221,6 +223,7 @@ extern const InputScriptType TxInputType_script_type_default;
#define HDNodeType_public_key_tag 6
#define MultisigRedeemScriptType_pubkeys_tag 1
#define MultisigRedeemScriptType_signatures_tag 2
#define MultisigRedeemScriptType_m_tag 3
#define TxOutputBinType_amount_tag 1
#define TxOutputBinType_script_pubkey_tag 2
#define TxOutputType_address_tag 1
@ -254,7 +257,7 @@ extern const InputScriptType TxInputType_script_type_default;
/* Struct field encoding specification for nanopb */
extern const pb_field_t HDNodeType_fields[7];
extern const pb_field_t CoinType_fields[5];
extern const pb_field_t MultisigRedeemScriptType_fields[3];
extern const pb_field_t MultisigRedeemScriptType_fields[4];
extern const pb_field_t TxInputType_fields[8];
extern const pb_field_t TxOutputType_fields[5];
extern const pb_field_t TxOutputBinType_fields[3];
@ -265,11 +268,11 @@ extern const pb_field_t TxRequestSerializedType_fields[4];
/* Maximum encoded size of messages (where known) */
#define HDNodeType_size 121
#define CoinType_size 47
#define MultisigRedeemScriptType_size 663
#define TxInputType_size 1289
#define MultisigRedeemScriptType_size 669
#define TxInputType_size 1295
#define TxOutputType_size 102
#define TxOutputBinType_size 534
#define TransactionType_size 1957
#define TransactionType_size 1963
#define TxRequestDetailsType_size 40
#define TxRequestSerializedType_size 1115

View File

@ -282,8 +282,12 @@ void signing_txack(TransactionType *tx)
for (k = 0; k < tx->inputs[0].address_n_count; k++) {
hdnode_private_ckd(&node, tx->inputs[0].address_n[k]);
}
ecdsa_get_pubkeyhash(node.public_key, hash);
tx->inputs[0].script_sig.size = compile_script_sig(coin->address_type, hash, tx->inputs[0].script_sig.bytes);
if (tx->inputs[0].has_multisig) {
tx->inputs[0].script_sig.size = compile_script_multisig(&(tx->inputs[0].multisig), tx->inputs[0].script_sig.bytes);
} else {
ecdsa_get_pubkeyhash(node.public_key, hash);
tx->inputs[0].script_sig.size = compile_script_sig(coin->address_type, hash, tx->inputs[0].script_sig.bytes);
}
if (tx->inputs[0].script_sig.size == 0) {
fsm_sendFailure(FailureType_Failure_Other, "Failed to compile input");
signing_abort();
@ -362,7 +366,26 @@ void signing_txack(TransactionType *tx)
resp.serialized.has_serialized_tx = true;
ecdsa_sign_digest(privkey, hash, sig);
resp.serialized.signature.size = ecdsa_sig_to_der(sig, resp.serialized.signature.bytes);
input.script_sig.size = serialize_script_sig(resp.serialized.signature.bytes, resp.serialized.signature.size, pubkey, 33, input.script_sig.bytes);
if (input.has_multisig) {
// fill in the signature
int i, pubkey_idx = -1;
for (i = 0; i < input.multisig.pubkeys_count; i++) {
if (input.multisig.pubkeys[i].size == 33 && memcmp(input.multisig.pubkeys[i].bytes, pubkey, 33) == 0) {
pubkey_idx = i;
break;
}
}
if (pubkey_idx == -1) {
fsm_sendFailure(FailureType_Failure_Other, "Pubkey not found in multisig script");
signing_abort();
return;
}
memcpy(input.multisig.signatures[pubkey_idx].bytes, resp.serialized.signature.bytes, resp.serialized.signature.size);
input.multisig.signatures[pubkey_idx].size = resp.serialized.signature.size;
input.script_sig.size = serialize_script_multisig(&(input.multisig), input.script_sig.bytes);
} else {
input.script_sig.size = serialize_script_sig(resp.serialized.signature.bytes, resp.serialized.signature.size, pubkey, 33, input.script_sig.bytes);
}
resp.serialized.serialized_tx.size = tx_serialize_input(&to, input.prev_hash.bytes, input.prev_index, input.script_sig.bytes, input.script_sig.size, input.sequence, resp.serialized.serialized_tx.bytes);
if (idx1i < inputs_count - 1) {
idx1i++;

View File

@ -130,7 +130,37 @@ uint32_t compile_script_sig(uint8_t address_type, const uint8_t *pubkeyhash, uin
}
}
int serialize_script_sig(uint8_t *signature, uint32_t signature_len, uint8_t *pubkey, uint32_t pubkey_len, uint8_t *out)
// if out == NULL just compute the length
uint32_t compile_script_multisig(const MultisigRedeemScriptType *multisig, uint8_t *out)
{
if (!multisig->has_m) return 0;
uint32_t m = multisig->m;
uint32_t n = multisig->pubkeys_count;
if (m < 2 || m > 3) return 0;
if (n < 2 || n > 3) return 0;
uint32_t i, r = 0;
if (out) {
out[r] = 0x50 + m; r++;
for (i = 0; i < n; i++) {
r += op_push(multisig->pubkeys[i].size, out + r);
memcpy(out + r, multisig->pubkeys[i].bytes, multisig->pubkeys[i].size); r += multisig->pubkeys[i].size;
}
out[r] = 0x50 + n; r++;
out[r] = 0xAE; r++; // OP_CHECKMULTISIG
} else {
r++;
for (i = 0; i < n; i++) {
uint8_t dummy[8];
r += op_push(multisig->pubkeys[i].size, dummy);
r += multisig->pubkeys[i].size;
}
r++;
r++;
}
return r;
}
uint32_t serialize_script_sig(const uint8_t *signature, uint32_t signature_len, const uint8_t *pubkey, uint32_t pubkey_len, uint8_t *out)
{
uint32_t r = 0;
r += op_push(signature_len + 1, out + r);
@ -141,6 +171,24 @@ int serialize_script_sig(uint8_t *signature, uint32_t signature_len, uint8_t *pu
return r;
}
uint32_t serialize_script_multisig(const MultisigRedeemScriptType *multisig, uint8_t *out)
{
uint32_t i, r = 0;
out[r] = 0x00; r++;
for (i = 0; i < multisig->signatures_count; i++) {
if (multisig->signatures[i].size == 0) {
continue;
}
r += op_push(multisig->signatures[i].size + 1, out + r);
memcpy(out + r, multisig->signatures[i].bytes, multisig->signatures[i].size); r += multisig->signatures[i].size;
out[r] = 0x01; r++;
}
uint32_t script_len = compile_script_multisig(multisig, 0);
r += op_push(script_len, out + r);
r += compile_script_multisig(multisig, out + r);
return r;
}
// tx methods
uint32_t tx_serialize_header(TxStruct *tx, uint8_t *out)

View File

@ -42,7 +42,9 @@ typedef struct {
} TxStruct;
uint32_t compile_script_sig(uint8_t address_type, const uint8_t *pubkeyhash, uint8_t *out);
int serialize_script_sig(uint8_t *signature, uint32_t signature_len, uint8_t *pubkey, uint32_t pubkey_len, uint8_t *out);
uint32_t compile_script_multisig(const MultisigRedeemScriptType *multisig, uint8_t *out);
uint32_t serialize_script_sig(const uint8_t *signature, uint32_t signature_len, const uint8_t *pubkey, uint32_t pubkey_len, uint8_t *out);
uint32_t serialize_script_multisig(const MultisigRedeemScriptType *multisig, uint8_t *out);
int compile_output(const CoinType *coin, const HDNode *root, TxOutputType *in, TxOutputBinType *out, bool needs_confirm);
uint32_t tx_serialize_input(TxStruct *tx, uint8_t *prev_hash, uint32_t prev_index, uint8_t *script_sig, uint32_t script_sig_len, uint32_t sequence, uint8_t *out);
uint32_t tx_serialize_output(TxStruct *tx, uint64_t amount, uint8_t *script_pubkey, uint32_t script_pubkey_len, uint8_t *out);

@ -1 +1 @@
Subproject commit e675d5fd7684e437bb35fb24330234d43ee2e4db
Subproject commit 3670728fd205ccfc75571ec3a49bfc7d07d11b17