Summary
VerifyTapscriptSigs in pkg/ark-lib/txutils/utils.go hardcodes txscript.SigHashDefault when computing the sighash for signature verification. This means any tapscript input signed with a non-default sighash type (e.g. SIGHASH_ALL, SIGHASH_SINGLE, SIGHASH_NONE, or their ANYONECANPAY variants) will fail verification even when the sighash type is correctly encoded in the PSBT.
Current Behavior
In pkg/ark-lib/txutils/utils.go:
sighash, err = txscript.CalcTapscriptSignaturehash(
txSigHashes,
txscript.SigHashDefault, // ← hardcoded
tx.UnsignedTx,
inputIndex,
prevoutFetcher,
leaf,
)
The sighash type embedded in each TaprootScriptSpendSig entry is ignored.
Expected Behavior
The sighash type should be read from the PSBT sig entry (tapscriptSig.SigHash), exactly as the forfeit tx verification path does in internal/infrastructure/tx-builder/covenantless/builder.go:
preimage, err := txscript.CalcTapscriptSignaturehash(
txSigHashes,
tapScriptSig.SigHash, // ← reads from PSBT sig
ptx.UnsignedTx,
index,
prevoutFetcher,
txscript.NewBaseTapLeaf(tapLeaf.Script),
)
The signing path in pkg/arkd-wallet/core/application/wallet/service.go already respects input.SighashType from the PSBT when producing signatures, so the signing and verification halves are inconsistent.
Motivation
This is needed to support closures (e.g. smart contract scripts, complex spending conditions) that require non-default sighash semantics — the same flexibility the forfeit tx path already has. Without it, any future closure type that commits to a specific sighash flag cannot be verified through the general VerifyTapscriptSigs utility.
Fix
In pkg/ark-lib/txutils/utils.go, replace the hardcoded txscript.SigHashDefault with tapscriptSig.SigHash:
sighash, err = txscript.CalcTapscriptSignaturehash(
txSigHashes,
tapscriptSig.SigHash,
tx.UnsignedTx,
inputIndex,
prevoutFetcher,
leaf,
)
Relevant Files
pkg/ark-lib/txutils/utils.go — VerifyTapscriptSigs (needs fix)
internal/infrastructure/tx-builder/covenantless/builder.go — verifyTapscriptPartialSigs (reference implementation)
pkg/arkd-wallet/core/application/wallet/service.go — signing already handles custom sighash types
pkg/ark-lib/script/closure.go — closure types currently document SIGHASH_DEFAULT assumption in comments (should be updated)
Summary
VerifyTapscriptSigsinpkg/ark-lib/txutils/utils.gohardcodestxscript.SigHashDefaultwhen computing the sighash for signature verification. This means any tapscript input signed with a non-default sighash type (e.g.SIGHASH_ALL,SIGHASH_SINGLE,SIGHASH_NONE, or theirANYONECANPAYvariants) will fail verification even when the sighash type is correctly encoded in the PSBT.Current Behavior
In
pkg/ark-lib/txutils/utils.go:The sighash type embedded in each
TaprootScriptSpendSigentry is ignored.Expected Behavior
The sighash type should be read from the PSBT sig entry (
tapscriptSig.SigHash), exactly as the forfeit tx verification path does ininternal/infrastructure/tx-builder/covenantless/builder.go:The signing path in
pkg/arkd-wallet/core/application/wallet/service.goalready respectsinput.SighashTypefrom the PSBT when producing signatures, so the signing and verification halves are inconsistent.Motivation
This is needed to support closures (e.g. smart contract scripts, complex spending conditions) that require non-default sighash semantics — the same flexibility the forfeit tx path already has. Without it, any future closure type that commits to a specific sighash flag cannot be verified through the general
VerifyTapscriptSigsutility.Fix
In
pkg/ark-lib/txutils/utils.go, replace the hardcodedtxscript.SigHashDefaultwithtapscriptSig.SigHash:Relevant Files
pkg/ark-lib/txutils/utils.go—VerifyTapscriptSigs(needs fix)internal/infrastructure/tx-builder/covenantless/builder.go—verifyTapscriptPartialSigs(reference implementation)pkg/arkd-wallet/core/application/wallet/service.go— signing already handles custom sighash typespkg/ark-lib/script/closure.go— closure types currently documentSIGHASH_DEFAULTassumption in comments (should be updated)