-
Notifications
You must be signed in to change notification settings - Fork 871
Support Miniscript (with C#) #684
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
Conversation
1491607 to
2901351
Compare
|
Let me know when it is ready to review. I will probably use miniscript in NBXplorer so users can't have their own way to make arbitrary scripts. |
|
I think I can finish it in three days or so. |
|
I have quickly checked. I think you do way too complicated for GetHashCode/Equal implementations. |
|
@NicolasDorier Thanks for review. |
b30723d to
cf3cce2
Compare
|
Ready for review. |
|
Wow so F# just do this by default? cool. |
Yes! |
|
The error in CI seems nothing to do with my code.
In fact, it does more than this. IEquatable and IStructuralEquatable and IComparable by default. |
|
448d5cf to
ec0b258
Compare
joemphilips
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 did some simple self review.
| @@ -0,0 +1,41 @@ | |||
|
|
|||
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 class contains a method used to to be in transaction_test .
Some functions (e.g. RandomCoin ) is quite reusable so I've moved it to here.
| [Fact] | ||
| [Trait("UnitTest", "UnitTest")] | ||
|
|
||
| public void ShouldPlayWellWithTransactionBuilder_2() |
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.
See this test for how TransactionBuilder Supports HTLC by Miniscript
|
|
||
| public bool IsFinalized() => final_script_sig != null || final_script_witness != null; | ||
|
|
||
| /// <summary> |
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.
Removing this method has nothing to do with Miniscript. But I noticed that it is legacy code from my version of PSBT. So I removed it.
| } | ||
| if (ageS.LockType == SequenceLockType.Time) | ||
| { | ||
| errors.Add(new SatisfyError(SatisfyErrorCode.UnSupportedRelativeLockTimeType, this)); |
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.
Currently, I decided to support only block-height based lock for time (which is OP_CSV )
so in DSL "time(0) ~ time(65535)" is allowed.
I don't know this will be standard among other Miniscript implementation. So it might change in the future.
NBitcoin/TransactionBuilder.cs
Outdated
| } | ||
|
|
||
| Sequence? _Sequence; | ||
| public TransactionBuilder SetRelativeLockTime(int lockHeight) |
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 think you can just use SetSequence(Sequence).
My only problem with this is that sequence is a per input concept, not a global tx concept.
But I guess this is still useful if a wallet has several keys depending on the same miniscript with same expiration?
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 think the api to take int blockHeight or TimeSpan period is better than taking Sequence because we must assure tx nVersion is bigger than 1.
users are not interested into how the rule is encoded. they just want to use the relative locktime feature.
What about
SetRelativeLockTimeTo(ICoin whichCoin, int lockHeight)
and hold the info as Dictionary<ICoin, Sequence> ? In this way, we can assure that it will affect only specific input.
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.
Tell me if the current implementation is not good. I decided to use Dictionary<OutPoint, Sequence> since Coins does not support GetHashCode
| var scriptSig1 = extension.GenerateScriptSig(scriptPubKey, keyRepo, signer); | ||
| var scriptSig2 = extension.GenerateScriptSig(scriptPubKey, signer2, signer2); | ||
| var scriptSig1 = extension.GenerateScriptSig(scriptPubKey, keyRepo, signer, preimageRepo, txIn.TxIn.Sequence); | ||
| var scriptSig2 = extension.GenerateScriptSig(scriptPubKey, signer2, signer2, preimageRepo, txIn.TxIn.Sequence); |
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 that txIn.TxIn.Sequence can ever be useful to an extension.
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.
It is not necessary, but I think it is useful in the case of Miniscript extension
because txbuilder fails to sign when
- script contains OP_CSV. and
- user forgets to set Sequence appropriately.
without this, users will notice that they have signed to the invalid tx when they try to broadcast.
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.
(To make me clear, the user does not have to set nSequence even if OP_CSV is in the script if he tries to redeem through non-timelocked path)
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.
But don't you have this problem in all case anyway? The transaction might still not be broadcastable depending on the Sequence, and the only way to know is to have the previous UTXOs's height.
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.
Yes, TX might be un-broadcastable anyway, difference is that if the user signs to nSequence which is not suitable to pass OP_CSV (e.g. disable flag is set) that signature will be useless for redeeming through timelocked redeem condition. so the tx wont be valid forever.
|
Unrelated to this PR, but it makes me think that a BIP should be proposed for PSBT to support adding preimages. |
Indeed, I was quite surprised that no one has written yet. |
f7079cf to
59df0c0
Compare
|
@joemphilips if you feel motivated to do the BIP, you can ask to people on #bitcoin-dev on IRC about it. If nobody did, do your own, publish on the mailing list. |
6b0dbf8 to
fcb6e72
Compare
|
Hey, so I just created the type If it get possible to finalize any miniscript then I can move this to NBXplorer then BTCpayServer. BTCPayServer now support the signature of arbitrary PSBT, so as long as we have the finalizer... it will work! |
|
Ah thanks for mentioning. I've just realized that the spec for output descriptor in bitcoin core has been much detailed and broad than last time I've read. I will update parsers and its tests in this weekend. (And finalizer afterwords) BTW, I've been using |
|
@joemphilips I did an object model to build a OutputDescriptor, but it does not support parsing. Maybe |
* Remove useless methods from PSBT. * Introduce ISha256PreimageRepsitory for TransacitonBuilder * Fix sum bug in * SatisfyException * MiniscriptScriptParser
* Add tests for SatisfyCSV * Fix bug when instantiating AbstractPolicy.Time * Support only blockheight-based relative locktime in Minsicript. * Add null check when instantiating OutputDescriptor
7d99209 to
0cb0e0a
Compare
* Preparet test vectors from bitcoin core. * Allow to parse private keys * Inject ISigningRepository to pickup private key info when parsing * Prevent parsing Uncompressed pubkey when it is in witness context.
|
lol this PR is massive, can you break it down into 2 PR, like one with only the output descriptor stuff and the other one with miniscript? |
|
OK. I should have created separate PR in the first place ... Miniscript and OutputDescriptor is quite different beast. |
Previous attempt is in #675
I'e been rewriting from F# to C# for following reason.