Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions include/wally_psbt_members.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ WALLY_CORE_API int wally_psbt_get_input_unknown(const struct wally_psbt *psbt, s
WALLY_CORE_API int wally_psbt_get_input_unknown_len(const struct wally_psbt *psbt, size_t index, size_t subindex, size_t *written);
WALLY_CORE_API int wally_psbt_get_input_sighash(const struct wally_psbt *psbt, size_t index, size_t *written);

/**
* Return the signature type of a PSBT input.
*
* :param psbt: The PSBT to get the signature type from.
* :param index: The zero-based index of the input to get the signature type from.
* :param value_out: Destination for the :ref:`tx-sig-type` of the input.
*/
WALLY_CORE_API int wally_psbt_get_input_signature_type(const struct wally_psbt *psbt, size_t index, uint32_t *value_out);

/**
* FIXED_SIZED_OUTPUT(len, bytes_out, WALLY_TXHASH_LEN)
*/
Expand Down
6 changes: 3 additions & 3 deletions include/wally_transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ extern "C" {
#define WALLY_SIGHASH_MASK 0x1f /* Mask for determining ALL/NONE/SINGLE */
#define WALLY_SIGHASH_TR_IN_MASK 0xc0 /* Taproot mask for determining input hash type */

/*** tx-sighash-type Transaction signature hash flags */
/*** tx-sig-type Transaction signature type flags */
#define WALLY_SIGTYPE_PRE_SW 0x1 /* Pre-segwit signature hash */
#define WALLY_SIGTYPE_SW_V0 0x2 /* Segwit v0 signature hash */
#define WALLY_SIGTYPE_SW_V1 0x3 /* Segwit v1 (taproot) signature hash */
#define WALLY_SIGTYPE_MASK 0xf /* Mask for signature hash in signature hash flags */
#define WALLY_SIGTYPE_MASK 0xf /* Mask for signature type in flags */

#define WALLY_TX_ASSET_CT_EMPTY_PREFIX 0x00
#define WALLY_TX_ASSET_CT_EXPLICIT_PREFIX 0x01
Expand Down Expand Up @@ -910,7 +910,7 @@ WALLY_CORE_API int wally_tx_get_signature_hash(
*| be `SHA256_LEN` or 0.
* :param sighash: ``WALLY_SIGHASH_`` flags specifying the sighash flags
*| to sign with.
* :param flags: :ref:`tx-sighash-type` controlling signature hash generation.
* :param flags: :ref:`tx-sig-type` controlling signature hash generation.
* :param cache: An opaque cache for faster generation, or NULL to disable
*| caching. Must be empty on the first call to this function for a given
*| transaction, and only used for signing the inputs of the same ``tx``.
Expand Down
83 changes: 35 additions & 48 deletions src/psbt.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,34 +155,32 @@ static const struct wally_tx_output *utxo_from_input(const struct wally_psbt *ps
return NULL;
}

/* Try to determine if a PSBT input is taproot.
* TODO: We could verify that the script and field checks are in sync
* here, i.e. that an input with taproot fields has a taproot script,
* and return an error otherwise.
*/
static bool is_taproot_input(const struct wally_psbt *psbt,
const struct wally_psbt_input *inp)
struct wally_psbt_input *psbt_get_input_signature_type(const struct wally_psbt *psbt,
size_t index, uint32_t *value_out)
{
if (!inp)
return false;
else {
const struct wally_tx_output *utxo = utxo_from_input(psbt, inp);
if (utxo) {
/* Determine from the scriptpubkey if possible */
size_t script_type;
int ret = wally_scriptpubkey_get_type(utxo->script, utxo->script_len,
&script_type);
if (ret == WALLY_OK)
return script_type == WALLY_SCRIPT_TYPE_P2TR;
}
/* No usable UTXO/script for this input, check for taproot fields */
return inp->taproot_leaf_hashes.num_items ||
inp->taproot_leaf_scripts.num_items ||
inp->taproot_leaf_signatures.num_items ||
wally_map_get_integer(&inp->psbt_fields, PSBT_IN_TAP_INTERNAL_KEY) ||
wally_map_get_integer(&inp->psbt_fields, PSBT_IN_TAP_MERKLE_ROOT) ||
wally_map_get_integer(&inp->psbt_fields, PSBT_IN_TAP_KEY_SIG);
struct wally_psbt_input *inp = psbt_get_input(psbt, index);
const struct wally_tx_output *utxo = utxo_from_input(psbt, inp);

if (value_out)
*value_out = 0;
if (!utxo || !value_out)
return NULL;

if (scriptpubkey_is_p2tr(utxo->script, utxo->script_len)) {
*value_out = WALLY_SIGTYPE_SW_V1;
return inp;
}

/* Otherwise, follow core and use whether a witness utxo is present */
*value_out = inp->witness_utxo ? WALLY_SIGTYPE_SW_V0 : WALLY_SIGTYPE_PRE_SW;
return inp;
}

int wally_psbt_get_input_signature_type(const struct wally_psbt *psbt,
size_t index, uint32_t *value_out)
{
struct wally_psbt_input *inp = psbt_get_input_signature_type(psbt, index, value_out);
return inp ? WALLY_OK : WALLY_EINVAL;
}

/* Set a struct member on a parent struct */
Expand Down Expand Up @@ -4579,12 +4577,10 @@ int wally_psbt_get_input_signature_hash(struct wally_psbt *psbt, size_t index,
unsigned char *bytes_out, size_t len)
{
struct wally_map scripts, assets, values, *assets_p;
const struct wally_psbt_input *inp = psbt_get_input(psbt, index);
size_t is_pset;
uint32_t sighash, sighash_type;
const bool is_taproot = is_taproot_input(psbt, inp);
/* FIXME: Determine segwitness in a smarter way (e.g. prevout script */
const bool is_segwit = inp && inp->witness_utxo != NULL;
const struct wally_psbt_input *inp = psbt_get_input_signature_type(psbt, index, &sighash_type);
const bool is_taproot = sighash_type == WALLY_SIGTYPE_SW_V1;
int ret;

if (!tx || !inp || flags)
Expand All @@ -4608,11 +4604,7 @@ int wally_psbt_get_input_signature_hash(struct wally_psbt *psbt, size_t index,
/* FIXME: Support script path spends */
script = NULL;
script_len = 0;
sighash_type = WALLY_SIGTYPE_SW_V1;
} else if (is_segwit)
sighash_type = WALLY_SIGTYPE_SW_V0;
else
sighash_type = WALLY_SIGTYPE_PRE_SW;
}

ret = get_signing_data(psbt, &scripts, assets_p, &values);
if (ret == WALLY_OK)
Expand Down Expand Up @@ -4640,29 +4632,24 @@ int wally_psbt_sign_input_bip32(struct wally_psbt *psbt,
unsigned char sig[EC_SIGNATURE_LEN + 1], der[EC_SIGNATURE_DER_MAX_LEN + 1];
unsigned char signing_key[EC_PRIVATE_KEY_LEN];
size_t sig_len = EC_SIGNATURE_LEN, der_len, pubkey_idx;
uint32_t sighash;
struct wally_psbt_input *inp = psbt_get_input(psbt, index);
const bool is_taproot = is_taproot_input(psbt, inp);
uint32_t sighash, sighash_type;
struct wally_psbt_input *inp = psbt_get_input_signature_type(psbt, index, &sighash_type);
const bool is_taproot = sighash_type == WALLY_SIGTYPE_SW_V1;
int ret;

if (!inp || !hdkey || hdkey->priv_key[0] != BIP32_FLAG_KEY_PRIVATE ||
(flags & ~(EC_FLAG_GRIND_R|EC_FLAG_ELEMENTS)))
return WALLY_EINVAL;

/* Find the public key this signature is for */
ret = wally_map_find_bip32_public_key_from(&inp->keypaths, subindex,
hdkey, &pubkey_idx);
if (ret != WALLY_OK || !pubkey_idx) {
/* Try again with the taproot public key */
if (is_taproot)
ret = wally_map_find_bip32_public_key_from(&inp->taproot_leaf_hashes,
subindex, hdkey,
&pubkey_idx);
if (ret == WALLY_OK && pubkey_idx && !is_taproot)
return WALLY_EINVAL; /* Must be tr if we have a tr key */
} else if (ret == WALLY_OK && pubkey_idx && is_taproot) {
return WALLY_EINVAL; /* Must not be tr if we have a non-tr key */
}

else
ret = wally_map_find_bip32_public_key_from(&inp->keypaths,
subindex, hdkey,
&pubkey_idx);
if (ret != WALLY_OK || !pubkey_idx)
return WALLY_EINVAL; /* Signing pubkey key not found */

Expand Down
1 change: 1 addition & 0 deletions src/swig_java/swig.i
Original file line number Diff line number Diff line change
Expand Up @@ -809,6 +809,7 @@ static jobjectArray create_jstringArray(JNIEnv *jenv, char **p, size_t len) {
%returns_size_t(wally_psbt_get_input_required_locktime);
%returns_size_t(wally_psbt_get_input_scriptcode);
%returns_size_t(wally_psbt_get_input_scriptcode_len);
%returns_size_t(wally_psbt_get_input_signature_type);
%returns_size_t(wally_psbt_get_input_signing_script);
%returns_size_t(wally_psbt_get_input_signing_script_len);
%returns_size_t(wally_psbt_get_input_sequence);
Expand Down
1 change: 1 addition & 0 deletions src/test/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,7 @@ class wally_psbt(Structure):
('wally_psbt_get_input_sighash', c_int, [POINTER(wally_psbt), c_size_t, c_size_t_p]),
('wally_psbt_get_input_signature', c_int, [POINTER(wally_psbt), c_size_t, c_size_t, c_void_p, c_size_t, c_size_t_p]),
('wally_psbt_get_input_signature_len', c_int, [POINTER(wally_psbt), c_size_t, c_size_t, c_size_t_p]),
('wally_psbt_get_input_signature_type', c_int, [POINTER(wally_psbt), c_size_t, c_uint32_p]),
('wally_psbt_get_input_signatures_size', c_int, [POINTER(wally_psbt), c_size_t, c_size_t_p]),
('wally_psbt_get_input_taproot_internal_key', c_int, [POINTER(wally_psbt), c_size_t, c_void_p, c_size_t, c_size_t_p]),
('wally_psbt_get_input_taproot_internal_key_len', c_int, [POINTER(wally_psbt), c_size_t, c_size_t_p]),
Expand Down
2 changes: 1 addition & 1 deletion src/wasm_package/src/const.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ export const WALLY_SIGHASH_NONE = 0x02;
export const WALLY_SIGHASH_RANGEPROOF = 0x40 ; /* Liquid/Elements only */
export const WALLY_SIGHASH_SINGLE = 0x03;
export const WALLY_SIGHASH_TR_IN_MASK = 0xc0; /* Taproot mask for determining input hash type */
export const WALLY_SIGTYPE_MASK = 0xf; /* Mask for signature hash in signature hash flags */
export const WALLY_SIGTYPE_MASK = 0xf; /* Mask for signature type in in flags */
export const WALLY_SIGTYPE_PRE_SW = 0x1; /* Pre-segwit signature hash */
export const WALLY_SIGTYPE_SW_V0 = 0x2; /* Segwit v0 signature hash */
export const WALLY_SIGTYPE_SW_V1 = 0x3; /* Segwit v1 (taproot) signature hash */
Expand Down
1 change: 1 addition & 0 deletions src/wasm_package/src/functions.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/wasm_package/src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ export function psbt_get_input_sequence(psbt: Ref_wally_psbt, index: number): nu
export function psbt_get_input_sighash(psbt: Ref_wally_psbt, index: number): number;
export function psbt_get_input_signature_hash(psbt: Ref_wally_psbt, index: number, tx: Ref_wally_tx, script: Buffer|Uint8Array, flags: number): Buffer;
export function psbt_get_input_signature_len(psbt: Ref_wally_psbt, index: number, subindex: number): number;
export function psbt_get_input_signature_type(psbt: Ref_wally_psbt, index: number): number;
export function psbt_get_input_signatures_size(psbt: Ref_wally_psbt, index: number): number;
export function psbt_get_input_signing_script_len(psbt: Ref_wally_psbt, index: number): number;
export function psbt_get_input_taproot_internal_key_len(psbt: Ref_wally_psbt, index: number): number;
Expand Down
1 change: 1 addition & 0 deletions tools/wasm_exports.sh
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ EXPORTED_FUNCTIONS="['_malloc','_free','_bip32_key_free' \
,'_wally_psbt_get_input_signature' \
,'_wally_psbt_get_input_signature_hash' \
,'_wally_psbt_get_input_signature_len' \
,'_wally_psbt_get_input_signature_type' \
,'_wally_psbt_get_input_signatures_size' \
,'_wally_psbt_get_input_signing_script' \
,'_wally_psbt_get_input_signing_script_len' \
Expand Down