1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-01-29 08:40:57 +00:00

refactor(legacy): Move compile_output() to signing.c.

This commit is contained in:
Andrew Kozlik 2023-01-02 11:24:46 +01:00 committed by matejcik
parent 7cbcb25a75
commit 0262842da2
3 changed files with 106 additions and 129 deletions

View File

@ -194,6 +194,9 @@ static Hasher coinjoin_request_hasher;
transaction disables replace-by-fee opt-in. */
#define MAX_BIP125_RBF_SEQUENCE 0xFFFFFFFD
/* supported version of Decred script_version */
#define DECRED_SCRIPT_VERSION 0
enum {
DECRED_SERIALIZE_FULL = 0,
DECRED_SERIALIZE_NO_WITNESS = 1,
@ -1925,6 +1928,85 @@ static bool signing_check_prevtx_hash(void) {
return true;
}
static bool compile_output(TxOutputType *in, TxOutputBinType *out,
bool needs_confirm) {
memzero(out, sizeof(TxOutputBinType));
out->amount = in->amount;
out->decred_script_version = DECRED_SCRIPT_VERSION;
if (in->script_type == OutputScriptType_PAYTOOPRETURN) {
// only 0 satoshi allowed for OP_RETURN
if (in->amount != 0 || in->has_address || (in->address_n_count > 0) ||
in->has_multisig) {
fsm_sendFailure(FailureType_Failure_ProcessError,
_("Failed to compile output"));
signing_abort();
return false;
}
if (needs_confirm) {
if (in->op_return_data.size >= 8 &&
memcmp(in->op_return_data.bytes, "omni", 4) ==
0) { // OMNI transaction
layoutConfirmOmni(in->op_return_data.bytes, in->op_return_data.size);
} else {
layoutConfirmOpReturn(in->op_return_data.bytes,
in->op_return_data.size);
}
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput,
false)) {
fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL);
signing_abort();
return false;
}
}
op_return_to_script_pubkey(
in->op_return_data.bytes, in->op_return_data.size,
out->script_pubkey.bytes, &out->script_pubkey.size);
return true;
}
if (in->address_n_count > 0) {
InputScriptType input_script_type = 0;
if (!change_output_to_input_script_type(in->script_type,
&input_script_type) ||
hdnode_private_ckd_cached(&node, in->address_n, in->address_n_count,
NULL) == 0 ||
hdnode_fill_public_key(&node) != 0 ||
!compute_address(coin, input_script_type, &node, in->has_multisig,
&in->multisig, in->address)) {
fsm_sendFailure(FailureType_Failure_ProcessError,
_("Failed to compile output"));
signing_abort();
return false;
}
} else if (!in->has_address) {
fsm_sendFailure(FailureType_Failure_ProcessError,
_("Failed to compile output"));
signing_abort();
return false;
}
if (!address_to_script_pubkey(coin, in->address, out->script_pubkey.bytes,
&out->script_pubkey.size)) {
fsm_sendFailure(FailureType_Failure_ProcessError,
_("Failed to compile output"));
signing_abort();
return false;
}
if (needs_confirm) {
layoutConfirmOutput(coin, amount_unit, in);
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL);
signing_abort();
return false;
}
}
return true;
}
static bool is_change_output(const TxInfo *tx_info,
const TxOutputType *txoutput) {
if (!is_change_output_script_type(txoutput->script_type)) {
@ -1992,21 +2074,12 @@ static bool signing_add_output(TxOutputType *txoutput) {
// Skip confirmation of change-outputs and skip output confirmation altogether
// in replacement transactions.
bool skip_confirm = is_change || is_replacement || (is_coinjoin == sectrue);
int co = compile_output(coin, amount_unit, &root, txoutput, &bin_output,
!skip_confirm);
if (!compile_output(txoutput, &bin_output, !skip_confirm)) {
return false;
}
if (!skip_confirm) {
report_progress(true);
}
if (co < 0) {
fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL);
signing_abort();
return false;
} else if (co == 0) {
fsm_sendFailure(FailureType_Failure_ProcessError,
_("Failed to compile output"));
signing_abort();
return false;
}
#if !BITCOIN_ONLY
if (coin->decred) {
if (serialize) {
@ -2144,11 +2217,7 @@ static bool signing_add_orig_input(TxInputType *orig_input) {
static bool signing_add_orig_output(TxOutputType *orig_output) {
// Compute scriptPubKey.
TxOutputBinType orig_bin_output;
if (compile_output(coin, amount_unit, &root, orig_output, &orig_bin_output,
false) <= 0) {
fsm_sendFailure(FailureType_Failure_ProcessError,
_("Failed to compile output"));
signing_abort();
if (!compile_output(orig_output, &orig_bin_output, false)) {
return false;
}
@ -2854,11 +2923,7 @@ static bool signing_hash_orig_input(TxInputType *orig_input) {
}
static bool signing_hash_orig_output(TxOutputType *orig_output) {
if (compile_output(coin, amount_unit, &root, orig_output, &bin_output,
false) <= 0) {
fsm_sendFailure(FailureType_Failure_ProcessError,
_("Failed to compile output"));
signing_abort();
if (!compile_output(orig_output, &bin_output, false)) {
return false;
}
@ -3821,11 +3886,7 @@ void signing_txack(TransactionType *tx) {
}
progress_step++;
if (compile_output(coin, amount_unit, &root, tx->outputs, &bin_output,
false) <= 0) {
fsm_sendFailure(FailureType_Failure_ProcessError,
_("Failed to compile output"));
signing_abort();
if (!compile_output(tx->outputs, &bin_output, false)) {
return;
}
// check hashOutputs
@ -3971,11 +4032,7 @@ void signing_txack(TransactionType *tx) {
}
progress_step++;
if (compile_output(coin, amount_unit, &root, tx->outputs, &bin_output,
false) <= 0) {
fsm_sendFailure(FailureType_Failure_ProcessError,
_("Failed to compile output"));
signing_abort();
if (!compile_output(tx->outputs, &bin_output, false)) {
return;
}
resp.has_serialized = true;

View File

@ -74,8 +74,6 @@
/* size of a Decred witness (without script): 8 amount, 4 block height, 4 block
* index */
#define TXSIZE_DECRED_WITNESS 16
/* support version of Decred script_version */
#define DECRED_SCRIPT_VERSION 0
static const uint8_t segwit_header[2] = {0, 1};
@ -235,8 +233,8 @@ bool compute_address(const CoinInfo *coin, InputScriptType script_type,
return 1;
}
static int address_to_script_pubkey(const CoinInfo *coin, const char *address,
uint8_t *script_pubkey, pb_size_t *size) {
int address_to_script_pubkey(const CoinInfo *coin, const char *address,
uint8_t *script_pubkey, pb_size_t *size) {
uint8_t addr_raw[MAX_ADDR_RAW_SIZE] = {0};
size_t addr_raw_len = base58_decode_check(address, coin->curve->hasher_base58,
addr_raw, MAX_ADDR_RAW_SIZE);
@ -323,96 +321,16 @@ static int address_to_script_pubkey(const CoinInfo *coin, const char *address,
return 0;
}
int compile_output(const CoinInfo *coin, AmountUnit amount_unit,
const HDNode *root, TxOutputType *in, TxOutputBinType *out,
bool needs_confirm) {
memzero(out, sizeof(TxOutputBinType));
out->amount = in->amount;
out->decred_script_version = DECRED_SCRIPT_VERSION;
if (in->script_type == OutputScriptType_PAYTOOPRETURN) {
// only 0 satoshi allowed for OP_RETURN
if (in->amount != 0 || in->has_address || (in->address_n_count > 0) ||
in->has_multisig) {
return 0; // failed to compile output
}
if (needs_confirm) {
if (in->op_return_data.size >= 8 &&
memcmp(in->op_return_data.bytes, "omni", 4) ==
0) { // OMNI transaction
layoutConfirmOmni(in->op_return_data.bytes, in->op_return_data.size);
} else {
layoutConfirmOpReturn(in->op_return_data.bytes,
in->op_return_data.size);
}
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput,
false)) {
return -1; // user aborted
}
}
uint32_t r = 0;
out->script_pubkey.bytes[0] = 0x6A;
r++; // OP_RETURN
r += op_push(in->op_return_data.size, out->script_pubkey.bytes + r);
memcpy(out->script_pubkey.bytes + r, in->op_return_data.bytes,
in->op_return_data.size);
r += in->op_return_data.size;
out->script_pubkey.size = r;
return r;
}
if (in->address_n_count > 0) {
static CONFIDENTIAL HDNode node;
InputScriptType input_script_type = 0;
switch (in->script_type) {
case OutputScriptType_PAYTOADDRESS:
input_script_type = InputScriptType_SPENDADDRESS;
break;
case OutputScriptType_PAYTOMULTISIG:
input_script_type = InputScriptType_SPENDMULTISIG;
break;
case OutputScriptType_PAYTOWITNESS:
input_script_type = InputScriptType_SPENDWITNESS;
break;
case OutputScriptType_PAYTOP2SHWITNESS:
input_script_type = InputScriptType_SPENDP2SHWITNESS;
break;
case OutputScriptType_PAYTOTAPROOT:
input_script_type = InputScriptType_SPENDTAPROOT;
break;
default:
return 0; // failed to compile output
}
memcpy(&node, root, sizeof(HDNode));
if (hdnode_private_ckd_cached(&node, in->address_n, in->address_n_count,
NULL) == 0) {
return 0; // failed to compile output
}
if (hdnode_fill_public_key(&node) != 0) {
return 0; // failed to compile output
}
if (!compute_address(coin, input_script_type, &node, in->has_multisig,
&in->multisig, in->address)) {
return 0; // failed to compile output
}
} else if (!in->has_address) {
return 0; // failed to compile output
}
if (!address_to_script_pubkey(coin, in->address, out->script_pubkey.bytes,
&out->script_pubkey.size)) {
return 0;
}
if (needs_confirm) {
layoutConfirmOutput(coin, amount_unit, in);
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
return -1; // user aborted
}
}
return out->script_pubkey.size;
void op_return_to_script_pubkey(const uint8_t *op_return_data,
size_t op_return_size, uint8_t *script_pubkey,
pb_size_t *script_pubkey_size) {
uint32_t r = 0;
script_pubkey[0] = 0x6A;
r++; // OP_RETURN
r += op_push(op_return_size, script_pubkey + r);
memcpy(script_pubkey + r, op_return_data, op_return_size);
r += op_return_size;
*script_pubkey_size = r;
}
bool get_script_pubkey(const CoinInfo *coin, HDNode *node, bool has_multisig,

View File

@ -75,6 +75,8 @@ bool compute_address(const CoinInfo *coin, InputScriptType script_type,
const HDNode *node, bool has_multisig,
const MultisigRedeemScriptType *multisig,
char address[MAX_ADDR_SIZE]);
int address_to_script_pubkey(const CoinInfo *coin, const char *address,
uint8_t *script_pubkey, pb_size_t *size);
uint32_t compile_script_sig(uint32_t address_type, const uint8_t *pubkeyhash,
uint8_t *out);
uint32_t compile_script_multisig(const CoinInfo *coin,
@ -101,9 +103,9 @@ bool tx_sign_ecdsa(const ecdsa_curve *curve, const uint8_t *private_key,
const uint8_t *hash, uint8_t *out, pb_size_t *size);
bool tx_sign_bip340(const uint8_t *private_key, const uint8_t *hash,
uint8_t *out, pb_size_t *size);
int compile_output(const CoinInfo *coin, AmountUnit amount_unit,
const HDNode *root, TxOutputType *in, TxOutputBinType *out,
bool needs_confirm);
void op_return_to_script_pubkey(const uint8_t *op_return_data,
size_t op_return_size, uint8_t *script_pubkey,
pb_size_t *script_pubkey_size);
bool get_script_pubkey(const CoinInfo *coin, HDNode *node, bool has_multisig,
const MultisigRedeemScriptType *multisig,
InputScriptType script_type, uint8_t *script_pubkey,