-
Notifications
You must be signed in to change notification settings - Fork 0
Schnorr & Taproot extension of Bitcoin Core TestFramework library #24
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
Schnorr & Taproot extension of Bitcoin Core TestFramework library #24
Conversation
d84583b to
0423cd2
Compare
f01a3df to
d55b495
Compare
|
Hi James. Thanks for removing the adaptor signature/DLC stuff. There are still a couple of things more to do before this is ready for review:
Could you also open a PR just for the Add TestFramework reset required by TestWrapper. and Reorganization of BitcoinTestFramework main method. commits please (since we'd want to get those merged into bitcoin/bitcoin). |
d55b495 to
a5e7fb6
Compare
Hi @jnewbery - Many thanks for the preliminary review. I have addressed your comments as suggested. |
a5e7fb6 to
34f3874
Compare
|
I've force pushed a change to fix some general best practices:
original branch is here: https://github.com/jnewbery/bitcoin/tree/2019-09-optech-taproot-master-original |
34f3874 to
e6b0948
Compare
|
force-pushed some more updates:
|
jnewbery
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've reviewed all the changes in key.py. I haven't reviewed script.py or the individual test scripts.
| return ret | ||
|
|
||
| def mul(self, data): | ||
| assert(self.valid) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I know this already occurs throughout this module, but in Python, assert is a statement, not a function, so this should be assert self.valid. No need to change it here, but this would be better without the parens.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a docstring commenting this function (ie that this multiplies a public key by a scalar).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a docstring commenting this function (ie that this adds two pubkeys)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you consider using the __add__ method so users can use the more natural notation:
a = ECPubKey()
b = ECPubKey()
c = a + b
than:
a = ECPubKey()
b = ECPubKey()
c = a.add(b)
(same comment for other add() and mul() functions in this commit)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. I kept add/mul for key operations for scalar bytes (e.g. tweaking a key with hash digest), but these are just wrappers for +/- to minimise code duplication.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the variable name secret is appropriate here. Perhaps summand?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: consider using a map-reduce here:
from functools import reduce
R_agg = reduce(lambda x, y: SECP256K1.add(x, y), map(lambda x: x.p, Rv))
actually, since you've already defined a way to add ECPubKeys, you don't even need the map:
R_agg = reduce(lambda x, y: x.add(y), Rv).p
If you define __add__ for ECPubKey, then this just becomes:
R_agg = sum(Rv).p
edit: since you're returning a ECPubKey object, just set R_agg as a ECPubKey:
R_agg = reduce(lambda x, y: x.add(y), Rv)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, I suggest using a reduce pattern here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment could be improved by documenting what is being returned.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
len(s) is guaranteed to be 32 by construction. It would be better to assert that len(sig) == 64 at the top.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use sum or reduce here (and for the r aggregation below)
2495575 to
16e581b
Compare
|
@jnewbery - Many thanks for your detailed review. I have incorporated all of your feedback in the latest push. |
In order to wrap the BitcoinTestFramework class in a user-defined class, which can be started and shutdown, the code in BitcoinTestFramework main has been encapsulated in respective functions. Additionally, test-run specific state in temp-directory and NetworkThread is now reset after shutdown.
These methods are required for the multiplication/tweaking of private/public key pairs. Keypairs are multiplied by a challenge factor in musig signatures. Keypairs are tweaked in both discrete log contracts and adaptor signatures.
16e581b to
2cb0009
Compare
|
I've force-pushed a branch that squashes the latest changes into the appropriate commits, and also adds the tests to |
2cb0009 to
a4dd190
Compare
jnewbery
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've pushed three commits containing nits for the add/mul commit, the schnorr commit and the musig commit.
@jachiang - can you review those commits and squash them into the preceding commits if you're happy with them?
I've also left a couple of small comments on musig.py
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is duplicating code from sign_schnorr in key.py. Can you just call through to that method to avoid the duplication?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you document what the arguments are in this docstring?
MuSig scheme is based on the interactive MuSig proposal, which is not formalized into a BIP proposal at the time of this writing.
Added miniscript class and expressions. Added subset of miniscript, which can be used to construct/satisfy scripts in a composable manner. Add miniscript to TapLeaf descriptors. TapLeaf class now deserializes/serializes descriptors with miniscript nodes. This facilitates construction of new tapleaf descriptors due to composability. New TapLeaf descriptors added containing time/hash expressions. Added TapLeaf test for pk descriptor types. Test constructs and spends scriptpaths of taptree which is constructed from various pk tapscript descriptor types containing pk, hash and time expressions. Added TapLeaf test for csa descriptor types. Test constructs and spends scriptpaths of taptree which is constructed from various csa (checksigadd) tapscript descriptor types containing pk, hash and time expressions.
a4dd190 to
18a2613
Compare
|
@jachiang - this code is still undergoing active development in the https://github.com/bitcoinops/taproot-workshop repo. I suggest we close this PR until that's settled down, and then perhaps you can re-open against https://github.com/bitcoin/bitcoin when there's a schnorr/taproot PR? |
Sounds good @jnewbery! Many thanks again for your extensive review on this PR. |
This is the Schnorr & Taproot library extension of the Bitcoin Core Python TestFramework I have been working on during my residency. Although the TestFramework is intended to provide functional test coverage for the Bitcoin Core project, it can also serve as a convenient Schnorr/Taproot prototyping tool for developers.
The goal of this project was to provide a toolkit for users to quickly prototype new Bitcoin contracting proposals with Schnorr & Taproot, so that the community can quickly get familiar and provide constructive feedback.
Schnorr extensions
Taproot output classes (Segwit V1)
Minscript classes (can be composed to (correctly) express tapscript descriptors)
For example:
pkolder(key, time) = and_v(v:pk(key),older(time))csahash(n, keys, hash) = and_v(v:thresh_csa,ripemd160)csahasholder(n,keys,hash,time) = and_v(v:thresh_csa ,and_v(v:ripemd160(hash), older(time)))Utility Classes/Methods
mainintosetupandshutdown, in order to prevent current code duplication in TestWrapper. I will also create a PR in master for this once completed.Future work
Your feedback and review is greatly appreciated.
I am currently documenting the library in form of interactive jupyter notebook files in bitcoinops/taproot.