sign_psbt: check and provide genesis blockhash for psets per ELIP-0101
What changed, and why it matters
This commit adds checks for the Liquid network's 'genesis blockhash' in a Bitcoin hardware wallet signing flow. It ensures the PSBT (Partially Signed Bitcoin Transaction) includes the correct network identifier before signing, and fills it in if missing. Without this, a specially crafted transaction could potentially trick the device into signing for the wrong Liquid network or into producing invalid Taproot signatures. The change is defensive and aligns with the ELIP-0101 specification.
Review the complete function to confirm the genesis mismatch error actually aborts signing (the diff only shows errmsg being set, not a return). Consider adding an explicit early return or audit existing error-handling pattern. Otherwise, this is a standards-compliance hardening change that should be included in the next release.
Security signals we found
Adds network/genesis-blockhash validation for Liquid PSBTs
Adds missing genesis blockhash injection when signing Liquid PSBTs
References ELIP-0101, which standardizes genesis blockhash handling
Prevents potential cross-network signing confusion on Liquid
Required for correct Taproot signing on Liquid per commit message
Evidence from the diff
In main/process/sign_psbt.c, the patch adds logic around ELIP-0101’s global genesis_blockhash field for Elements/Liquid PSBTs. Before signing, it calls wally_psbt_has_global_genesis_blockhash(); if present, it compares psbt->genesis_blockhash against the expected hash derived from the active network_id. A mismatch sets an error message (‘Network/pset genesis mismatch’) but does not immediately return an error code in the shown diff. Later, if signing_flags is set, the transaction is for Liquid, and no genesis blockhash was present, the code writes the correct network genesis hash into psbt->genesis_blockhash before invoking wally_psbt_signing_cache_enable() and signing inputs. The commit message notes this field is required for Taproot signing.
Changed components
main/process/sign_psbt.cLiquid/Elements PSBT signing flowTaproot signing on LiquidInspect captured patch +19 / −0
diff --git a/main/process/sign_psbt.c b/main/process/sign_psbt.c
index 6b938e4..efda455 100644
--- a/main/process/sign_psbt.c
+++ b/main/process/sign_psbt.c
@@ -668,6 +668,20 @@ int sign_psbt(jade_process_t* process, CborValue* params, const network_t networ
return CBOR_RPC_BAD_PARAMETERS;
}
const bool for_liquid = is_elements;
+ bool has_genesis_blockhash = false;
+ if (for_liquid) {
+ // Liquid: Check ELIP-0101 genesis blockhash
+ size_t has_genesis = 0;
+ JADE_WALLY_VERIFY(wally_psbt_has_global_genesis_blockhash(psbt, &has_genesis));
+ has_genesis_blockhash = has_genesis;
+ if (has_genesis_blockhash) {
+ uint8_t genesis[SHA256_LEN];
+ network_to_genesis_hash(network_id, genesis, sizeof(genesis));
+ if (memcmp(psbt->genesis_blockhash, genesis, sizeof(genesis))) {
+ *errmsg = "Network/pset genesis mismatch";
+ }
+ }
+ }
uint64_t explicit_fee = 0; // Liquid: Value of the explicit fee output
struct wally_tx* tx = NULL; // Holds the extracted tx
@@ -953,6 +967,11 @@ int sign_psbt(jade_process_t* process, CborValue* params, const network_t networ
display_processing_message_activity();
// Sign our inputs
+ if (signing_flags && for_liquid && !has_genesis_blockhash) {
+ // Liquid: Provide the ELIP-0101 genesis blockhash when signing
+ network_to_genesis_hash(network_id, psbt->genesis_blockhash, sizeof(psbt->genesis_blockhash));
+ }
+
JADE_WALLY_VERIFY(wally_psbt_signing_cache_enable(psbt, 0));
for (size_t index = 0; index < psbt->num_inputs; ++index) {
Why this scored 43/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.