diff --git a/txscript/pkscript.go b/txscript/pkscript.go index 7826d21294..7c6cfc58a0 100644 --- a/txscript/pkscript.go +++ b/txscript/pkscript.go @@ -239,26 +239,11 @@ func computeNonWitnessPkScript(sigScript []byte) (PkScript, error) { // computeWitnessPkScript computes the script of an output by looking at the // spending input's witness. -// IMPORTANT: With the addition of taproot, we can no longer say for certain -// what kind of script the witness is in most cases. The only case in which we -// can say for sure is when the witness data has an annex as the last push. In -// that case, we can identify the script type, but we lack the ability to -// reconstruct the script itself. +// IMPORTANT: With the addition of taproot, we can not say for certain +// what kind of script the witness is. func computeWitnessPkScript(witness wire.TxWitness) (PkScript, error) { var pkScript PkScript - switch { - // If the last push starts with the annex flag, this is a taproot spend. - // We can set the script class, but we can't say what the pubkey script - // looks like with just the witness data. - case isAnnexedWitness(witness): - pkScript.class = WitnessV1TaprootTy - - // For any other witnesses, we can't say for certain what type it is or what - // the pubkey script will be. - default: - pkScript.class = WitnessUnknownTy - } - + pkScript.class = WitnessUnknownTy return pkScript, nil } diff --git a/txscript/standard.go b/txscript/standard.go index ae5b59b7d9..922fa5a956 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -1007,6 +1007,15 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (Script return WitnessV0ScriptHashTy, addrs, 1, nil } + if hash := extractWitnessV1ScriptHash(pkScript); hash != nil { + var addrs []btcutil.Address + addr, err := btcutil.NewAddressTaproot(hash, chainParams) + if err == nil { + addrs = append(addrs, addr) + } + return WitnessV1TaprootTy, addrs, 1, nil + } + // case WitnessV1TaprootTy: // requiredSigs = 1 // addr, err := btcutil.NewAddressTaproot(pops[1].data, diff --git a/txscript/standard_test.go b/txscript/standard_test.go index 582d30eee4..41f26d6930 100644 --- a/txscript/standard_test.go +++ b/txscript/standard_test.go @@ -71,6 +71,20 @@ func newAddressScriptHash(scriptHash []byte) btcutil.Address { return addr } +// newAddressTaproot returns a new btcutil.AddressTaproot from the +// provided hash. It panics if an error occurs. This is only used in the tests +// as a helper since the only way it can fail is if there is an error in the +// test source code. +func newAddressTaproot(scriptHash []byte) btcutil.Address { + addr, err := btcutil.NewAddressTaproot(scriptHash, + &chaincfg.MainNetParams) + if err != nil { + panic("invalid script hash in test source") + } + + return addr +} + // TestExtractPkScriptAddrs ensures that extracting the type, addresses, and // number of required signatures from PkScripts works as intended. func TestExtractPkScriptAddrs(t *testing.T) { @@ -311,8 +325,15 @@ func TestExtractPkScriptAddrs(t *testing.T) { reqSigs: 1, class: MultiSigTy, }, - // from real tx: 691dd277dc0e90a462a3d652a1171686de49cf19067cd33c7df0392833fb986a, vout 44 - // invalid public keys + { + name: "v1 p2tr witness-script-hash", + script: hexToBytes("51201a82f7457a9ba6ab1074e9f50" + + "053eefc637f8b046e389b636766bdc7d1f676f8"), + addrs: []btcutil.Address{newAddressTaproot( + hexToBytes("1a82f7457a9ba6ab1074e9f50053eefc637f8b046e389b636766bdc7d1f676f8"))}, + reqSigs: 1, + class: WitnessV1TaprootTy, + }, { name: "1 of 3 multisig with invalid pubkeys 2", script: hexToBytes("514134633365633235396337346461636" +