mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-17 21:22:10 +00:00
refactor(legacy): Extract segwit signing code.
This commit is contained in:
parent
1ecb0f0c1c
commit
9732f6524a
@ -179,20 +179,6 @@ static uint8_t orig_hash[32]; // TXID of the original transaction.
|
||||
transaction disables replace-by-fee opt-in. */
|
||||
#define MAX_BIP125_RBF_SEQUENCE 0xFFFFFFFD
|
||||
|
||||
enum {
|
||||
// Signature hash type with the same semantics as SIGHASH_ALL, but instead of
|
||||
// having to include the byte in the signature, it is implied.
|
||||
SIGHASH_ALL_TAPROOT = 0,
|
||||
|
||||
// Default signature hash type in Bitcoin which signs all inputs and all
|
||||
// outputs of the transaction.
|
||||
SIGHASH_ALL = 1,
|
||||
|
||||
// Signature hash flag used in some Bitcoin-like altcoins for replay
|
||||
// protection.
|
||||
SIGHASH_FORKID = 0x40,
|
||||
};
|
||||
|
||||
enum {
|
||||
DECRED_SERIALIZE_FULL = 0,
|
||||
DECRED_SERIALIZE_NO_WITNESS = 1,
|
||||
@ -2542,26 +2528,14 @@ static bool signing_sign_ecdsa(TxInputType *txinput, const uint8_t *private_key,
|
||||
resp.serialized.signature_index = idx1;
|
||||
resp.serialized.has_signature = true;
|
||||
|
||||
int ret = 0;
|
||||
#ifdef USE_SECP256K1_ZKP_ECDSA
|
||||
if (coin->curve->params == &secp256k1) {
|
||||
ret = zkp_ecdsa_sign_digest(coin->curve->params, private_key, hash, sig,
|
||||
NULL, NULL);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
ret = ecdsa_sign_digest(coin->curve->params, private_key, hash, sig, NULL,
|
||||
NULL);
|
||||
}
|
||||
if (ret != 0) {
|
||||
if (!tx_sign_ecdsa(coin->curve->params, private_key, hash,
|
||||
resp.serialized.signature.bytes,
|
||||
&resp.serialized.signature.size)) {
|
||||
fsm_sendFailure(FailureType_Failure_ProcessError, _("Signing failed"));
|
||||
signing_abort();
|
||||
return false;
|
||||
}
|
||||
|
||||
resp.serialized.signature.size =
|
||||
ecdsa_sig_to_der(sig, resp.serialized.signature.bytes);
|
||||
|
||||
uint8_t sighash = signing_hash_type(txinput) & 0xff;
|
||||
if (txinput->has_multisig) {
|
||||
// fill in the signature
|
||||
@ -2599,22 +2573,15 @@ static bool signing_sign_bip340(const uint8_t *private_key,
|
||||
resp.serialized.has_signature_index = true;
|
||||
resp.serialized.signature_index = idx1;
|
||||
resp.serialized.has_signature = true;
|
||||
resp.serialized.signature.size = 64;
|
||||
|
||||
uint8_t output_private_key[32] = {0};
|
||||
bool ret = (zkp_bip340_tweak_private_key(private_key, NULL,
|
||||
output_private_key) == 0);
|
||||
ret = ret &&
|
||||
(zkp_bip340_sign_digest(output_private_key, hash,
|
||||
resp.serialized.signature.bytes, NULL) == 0);
|
||||
memzero(output_private_key, sizeof(output_private_key));
|
||||
|
||||
if (!ret) {
|
||||
if (!tx_sign_bip340(private_key, hash, resp.serialized.signature.bytes,
|
||||
&resp.serialized.signature.size)) {
|
||||
fsm_sendFailure(FailureType_Failure_ProcessError, _("Signing failed"));
|
||||
signing_abort();
|
||||
return false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool signing_sign_legacy_input(void) {
|
||||
@ -2658,13 +2625,9 @@ static bool signing_sign_segwit_input(TxInputType *txinput) {
|
||||
if (serialize) {
|
||||
resp.has_serialized = true;
|
||||
resp.serialized.has_serialized_tx = true;
|
||||
uint32_t r = 0;
|
||||
// write witness (number of stack items followed by signature)
|
||||
r += ser_length(1, resp.serialized.serialized_tx.bytes + r);
|
||||
r += tx_serialize_script(resp.serialized.signature.size,
|
||||
resp.serialized.signature.bytes,
|
||||
resp.serialized.serialized_tx.bytes + r);
|
||||
resp.serialized.serialized_tx.size = r;
|
||||
resp.serialized.serialized_tx.size = serialize_p2tr_witness(
|
||||
resp.serialized.signature.bytes, resp.serialized.signature.size, 0,
|
||||
resp.serialized.serialized_tx.bytes);
|
||||
}
|
||||
} else if (txinput->script_type == InputScriptType_SPENDP2SHWITNESS ||
|
||||
txinput->script_type == InputScriptType_SPENDWITNESS) {
|
||||
@ -2720,16 +2683,9 @@ static bool signing_sign_segwit_input(TxInputType *txinput) {
|
||||
resp.serialized.serialized_tx.bytes[0] = nwitnesses;
|
||||
resp.serialized.serialized_tx.size = r;
|
||||
} else { // single signature
|
||||
uint32_t r = 0;
|
||||
r += ser_length(2, resp.serialized.serialized_tx.bytes + r);
|
||||
resp.serialized.signature.bytes[resp.serialized.signature.size] =
|
||||
sighash;
|
||||
r += tx_serialize_script(resp.serialized.signature.size + 1,
|
||||
resp.serialized.signature.bytes,
|
||||
resp.serialized.serialized_tx.bytes + r);
|
||||
r += tx_serialize_script(33, node.public_key,
|
||||
resp.serialized.serialized_tx.bytes + r);
|
||||
resp.serialized.serialized_tx.size = r;
|
||||
resp.serialized.serialized_tx.size = serialize_p2wpkh_witness(
|
||||
resp.serialized.signature.bytes, resp.serialized.signature.size,
|
||||
node.public_key, 33, sighash, resp.serialized.serialized_tx.bytes);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -30,9 +30,13 @@
|
||||
#include "messages.pb.h"
|
||||
#include "protect.h"
|
||||
#include "ripemd160.h"
|
||||
#include "secp256k1.h"
|
||||
#include "segwit_addr.h"
|
||||
#include "util.h"
|
||||
#include "zkp_bip340.h"
|
||||
#ifdef USE_SECP256K1_ZKP_ECDSA
|
||||
#include "zkp_ecdsa.h"
|
||||
#endif
|
||||
|
||||
#if !BITCOIN_ONLY
|
||||
#include "cash_addr.h"
|
||||
@ -555,6 +559,82 @@ uint32_t serialize_script_multisig(const CoinInfo *coin,
|
||||
return r;
|
||||
}
|
||||
|
||||
uint32_t serialize_p2wpkh_witness(const uint8_t *signature,
|
||||
uint32_t signature_len,
|
||||
const uint8_t *public_key,
|
||||
uint32_t public_key_len, uint8_t sighash,
|
||||
uint8_t *out) {
|
||||
uint32_t r = 0;
|
||||
|
||||
// 2 stack items
|
||||
r += ser_length(2, out + r);
|
||||
|
||||
// length-prefixed signature with sighash type
|
||||
r += ser_length(signature_len + 1, out + r);
|
||||
memcpy(out + r, signature, signature_len);
|
||||
r += signature_len;
|
||||
out[r] = sighash;
|
||||
r += 1;
|
||||
|
||||
// length-prefixed public key
|
||||
r += tx_serialize_script(public_key_len, public_key, out + r);
|
||||
return r;
|
||||
}
|
||||
|
||||
uint32_t serialize_p2tr_witness(const uint8_t *signature,
|
||||
uint32_t signature_len, uint8_t sighash,
|
||||
uint8_t *out) {
|
||||
uint32_t r = 0;
|
||||
|
||||
// 1 stack item
|
||||
r += ser_length(1, out + r);
|
||||
|
||||
// length-prefixed signature with optional sighash type
|
||||
uint32_t sighash_len = sighash ? 1 : 0;
|
||||
r += ser_length(signature_len + sighash_len, out + r);
|
||||
memcpy(out + r, signature, signature_len);
|
||||
r += signature_len;
|
||||
if (sighash) {
|
||||
out[r] = sighash;
|
||||
r += 1;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
bool tx_sign_ecdsa(const ecdsa_curve *curve, const uint8_t *private_key,
|
||||
const uint8_t *hash, uint8_t *out, pb_size_t *size) {
|
||||
int ret = 0;
|
||||
uint8_t signature[64] = {0};
|
||||
#ifdef USE_SECP256K1_ZKP_ECDSA
|
||||
if (curve == &secp256k1) {
|
||||
ret =
|
||||
zkp_ecdsa_sign_digest(curve, private_key, hash, signature, NULL, NULL);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
ret = ecdsa_sign_digest(curve, private_key, hash, signature, NULL, NULL);
|
||||
}
|
||||
if (ret != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*size = ecdsa_sig_to_der(signature, out);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tx_sign_bip340(const uint8_t *private_key, const uint8_t *hash,
|
||||
uint8_t *out, pb_size_t *size) {
|
||||
static CONFIDENTIAL uint8_t output_private_key[32] = {0};
|
||||
bool ret = (zkp_bip340_tweak_private_key(private_key, NULL,
|
||||
output_private_key) == 0);
|
||||
ret =
|
||||
ret && (zkp_bip340_sign_digest(output_private_key, hash, out, NULL) == 0);
|
||||
*size = ret ? 64 : 0;
|
||||
memzero(output_private_key, sizeof(output_private_key));
|
||||
return ret;
|
||||
}
|
||||
|
||||
// tx methods
|
||||
bool tx_input_check_hash(Hasher *hasher, const TxInputType *input) {
|
||||
hasher_Update(hasher, (const uint8_t *)&input->address_n_count,
|
||||
|
@ -30,6 +30,20 @@
|
||||
|
||||
#define TX_OVERWINTERED 0x80000000
|
||||
|
||||
enum {
|
||||
// Signature hash type with the same semantics as SIGHASH_ALL, but instead of
|
||||
// having to include the byte in the signature, it is implied.
|
||||
SIGHASH_ALL_TAPROOT = 0,
|
||||
|
||||
// Default signature hash type in Bitcoin which signs all inputs and all
|
||||
// outputs of the transaction.
|
||||
SIGHASH_ALL = 1,
|
||||
|
||||
// Signature hash flag used in some Bitcoin-like altcoins for replay
|
||||
// protection.
|
||||
SIGHASH_FORKID = 0x40,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t inputs_len;
|
||||
uint32_t outputs_len;
|
||||
@ -73,6 +87,18 @@ uint32_t serialize_script_sig(const uint8_t *signature, uint32_t signature_len,
|
||||
uint32_t serialize_script_multisig(const CoinInfo *coin,
|
||||
const MultisigRedeemScriptType *multisig,
|
||||
uint8_t sighash, uint8_t *out);
|
||||
uint32_t serialize_p2wpkh_witness(const uint8_t *signature,
|
||||
uint32_t signature_len,
|
||||
const uint8_t *public_key,
|
||||
uint32_t public_key_len, uint8_t sighash,
|
||||
uint8_t *out);
|
||||
uint32_t serialize_p2tr_witness(const uint8_t *signature,
|
||||
uint32_t signature_len, uint8_t sighash,
|
||||
uint8_t *out);
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user