Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

txscript: add taproot script type #1768

Closed
wants to merge 4 commits into from

Conversation

buck54321
Copy link
Contributor

Add the WitnessV1TaprootTy script class and return it from GetScriptClass / typeOfScript.

Fix ComputePkScript, which was returning incorrect results for taproot (an probably other) scripts. ComputePkScript is now essentially useless for both v0 and v1 output witnesses.

Bump the btcutil dep to leverage new taproot address type.

Comment on lines 241 to 245
// 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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i would say that the only case we know for certain is when the number of witness elements is exactly 1. In that case we know it is p2tr keypath (for now at least. not future proof).

I dont know if we can say that that it is taproot just cause there is an annex starting with 0x50 cause surely there can be other p2w scripts (pre-taproot) that just happen to have a final witness element starting with 0x50?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let me know what you think

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont know if we can say that that it is taproot just cause there is an annex starting with 0x50 cause surely there can be other p2w scripts (pre-taproot) that just happen to have a final witness element starting with 0x50?

I guess that's true. Mkay.

i would say that the only case we know for certain is when the number of witness elements is exactly 1. In that case we know it is p2tr keypath (for now at least. not future proof).

I'm unable to verify this. Is it impossible to construct a p2wsh script spent by a length 1 witness?

Copy link
Contributor

@ellemouton ellemouton Dec 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unable to verify this. Is it impossible to construct a p2wsh script spent by a length 1 witness?

yeah indeed, you are correct. It would be a really weird anyone-can-spend p2wsh though. Since the element would have to be the redeemscript and then there is no spending script that follows...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess that's true. Mkay.

Ok, I was wrong about this. I was not super familiar with how scripts are parsed. So yeah, if it starts with 0x50 then it is the annex

Copy link
Contributor

@chappjc chappjc Dec 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry to interject as a third party, but while I found lightninglabs/neutrino#234 (comment) very enlightening, I think it would all fall apart when witness version 2 rolls around, like what happened with version 1 showed up and looked like p2wsh.
So while it sounds like much can be surmised from the witness stack, a hard fail based on the result of computeWitnessPkScript seems risky.
I think @Roasbeef has previously suggested somewhere (Slack maybe?) that multiple candidate types could be identified where there are ambiguities like the cases sipa and others have described, and I wonder if that approach is safest.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a hard fail based on the result of computeWitnessPkScript seems risky

yeah, especially when considering future witness versions like you said

@coveralls
Copy link

coveralls commented Nov 2, 2021

Pull Request Test Coverage Report for Build 1493217358

  • 53 of 73 (72.6%) changed or added relevant lines in 3 files are covered.
  • 2 unchanged lines in 1 file lost coverage.
  • Overall coverage increased (+0.02%) to 52.925%

Changes Missing Coverage Covered Lines Changed/Added Lines %
txscript/pkscript.go 2 5 40.0%
txscript/standard.go 47 64 73.44%
Files with Coverage Reduction New Missed Lines %
connmgr/connmanager.go 2 86.07%
Totals Coverage Status
Change from base Build 1469863602: 0.02%
Covered Lines: 21178
Relevant Lines: 40015

💛 - Coveralls

@philipglazman
Copy link

These new test vectors for BIP341 might be applicable. bitcoin/bips#1225

@Roasbeef
Copy link
Member

Roasbeef commented Nov 4, 2021

Thanks for the PR! Want to hold off on a bit of this till we get #1684 in since it modifies a lot w.r.t how we parse scripts in general (main goal is GC optimization).

Add the WitnessV1TaprootTy script class and return it from GetScriptClass
/ typeOfScript.

Fix ComputePkScript, which was returning incorrect results for taproot
(an probably other) scripts. ComputePkScript is now essentially useless
for both v0 and v1 output witnesses.

Bump the btcutil dep to leverage new taproot address type.
Comment on lines +802 to 805
case 1:
// https://github.com/bitcoin/bitcoin/blob/368831371d97a642beb54b5c4eb6eb0fedaa16b4/src/script/interpreter.cpp#L2090
return 0
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not certain about this.

Comment on lines +541 to 546
case 1:
switch {
case isWitnessTaprootScript(script):
return WitnessV1TaprootTy
}
}
Copy link
Contributor Author

@buck54321 buck54321 Nov 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this isn't really exercised since typeOfScript is only used in CalcScriptInfo, which is now clearly defined only for v0 scripts. Should I leave?

@benma
Copy link
Contributor

benma commented Nov 22, 2021

Thanks for the PR! Want to hold off on a bit of this till we get #1684 in since it modifies a lot w.r.t how we parse scripts in general (main goal is GC optimization).

The linked PR #1769 is merged. @buck54321 @Roasbeef would be great to get this merged soon, as it is blocking taproot support in the BitBoxApp 🙏

@benma
Copy link
Contributor

benma commented Nov 22, 2021

@buck54321 PayToAddrScript in standard.go needs to be extended by a *btcutil.AddressTaproot case.

benma added a commit to benma/bitbox-wallet-app that referenced this pull request Nov 22, 2021
We use functions from the btcd library to convert addresses to
pubKeyScripts and vice versa.

While the address type has support for Taproot addresses, the pubkey
script functions in btcd don't handle them yet. See also:
btcsuite/btcd#1768

To speed up send-to-taproot support, refactor the pubkey script
encoding/decoding into separate unit-tested functions, to which we can
easily add taproot support in the next commit.
Add taproot address handling in PayToAddrScript. Adds a test and
also some missing tests for p2wsh and p2wpkh addresses.
@gcsfred2
Copy link

gcsfred2 commented Dec 6, 2021

script.go has CalcWitnessSigHash with const scriptVersion = 0 hardcoded.

@gcsfred2
Copy link

gcsfred2 commented Dec 6, 2021

script.go has still

const (
	SigHashOld          SigHashType = 0x0

unchanged, but BIP341 redefines 0x00: "We define a new hashtype SIGHASH_DEFAULT (value 0x00)".

@buck54321
Copy link
Contributor Author

script.go has CalcWitnessSigHash with const scriptVersion = 0 hardcoded.

That gets trickier since it gets into the ScriptTokenizer and signature hash calculations. Can I call that work out of scope for this PR so that someone with more time or know-how can handle it in a separate effort? I don't want to slow you guys down.

@gcsfred2
Copy link

gcsfred2 commented Dec 6, 2021

Understood. I agree. No problem with me.

script.go has CalcWitnessSigHash with const scriptVersion = 0 hardcoded.

That gets trickier since it gets into the ScriptTokenizer and signature hash calculations. Can I call that work out of scope for this PR so that someone with more time or know-how can handle it in a separate effort? I don't want to slow you guys down.

@gdsoumya
Copy link

Hi, just checking on the status of the PR. We are using btcd in our project and this PR is necessary for us to activate support for taproot. Any update would be appreciated, thanks!

benma added a commit to benma/bitbox-wallet-app that referenced this pull request Dec 20, 2021
We use functions from the btcd library to convert addresses to
pubKeyScripts and vice versa.

While the address type has support for Taproot addresses, the pubkey
script functions in btcd don't handle them yet. See also:
btcsuite/btcd#1768

To speed up send-to-taproot support, refactor the pubkey script
encoding/decoding into separate unit-tested functions, to which we can
easily add taproot support in the next commit.
benma added a commit to benma/bitbox-wallet-app that referenced this pull request Dec 20, 2021
We use functions from the btcd library to convert addresses to
pubKeyScripts and vice versa.

While the address type has support for Taproot addresses, the pubkey
script functions in btcd don't handle them yet. See also:
btcsuite/btcd#1768

To speed up send-to-taproot support, refactor the pubkey script
encoding/decoding into separate unit-tested functions, to which we can
easily add taproot support in the next commit.
benma added a commit to benma/bitbox-wallet-app that referenced this pull request Dec 24, 2021
We use functions from the btcd library to convert addresses to
pubKeyScripts and vice versa.

While the address type has support for Taproot addresses, the pubkey
script functions in btcd don't handle them yet. See also:
btcsuite/btcd#1768

To speed up send-to-taproot support, refactor the pubkey script
encoding/decoding into separate unit-tested functions, to which we can
easily add taproot support in the next commit.
benma added a commit to benma/bitbox-wallet-app that referenced this pull request Dec 24, 2021
We use functions from the btcd library to convert addresses to
pubKeyScripts and vice versa.

While the address type has support for Taproot addresses, the pubkey
script functions in btcd don't handle them yet. See also:
btcsuite/btcd#1768

To speed up send-to-taproot support, refactor the pubkey script
encoding/decoding into separate unit-tested functions, to which we can
easily add taproot support in the next commit.
@Roasbeef
Copy link
Member

Can I call that work out of scope for this PR so that someone with more time or know-how can handle it in a separate effort? I don't want to slow you guys down.

np @buck54321, I'm building off this PR currently as a follow up to #1773 where I finish up the rest of the taproot validation logic.

@Roasbeef
Copy link
Member

Roasbeef commented Jan 7, 2022

Rolled these commits (with some modifications) into #1787, thanks for starting this @buck54321!

@Roasbeef Roasbeef closed this Jan 7, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants