mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-22 22:38:08 +00:00
multisig
This commit is contained in:
parent
a16e8c0e04
commit
91451f88b5
@ -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
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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++;
|
||||
|
@ -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)
|
||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user