-
Notifications
You must be signed in to change notification settings - Fork 38.7k
[WIP] HTLC implementation in the wallet #7601
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
|
Interesting! |
|
@jonasschnelli All P2SH is already standard.
|
|
@sipa: Ah. Right. Then – I guess – the |
|
@jonasschnelli To be clear: this indeed does make the HTLC type transaction standard in non-P2SH setting; it's however still smaller and cheaper than the largest raw multisig that is allowed. Perhaps that indeed shouldn't happen. |
|
Concept ACK. |
|
concept ACK |
|
Interestingly, this is useful for Paypub, as well as ZKCP, among other things. Concept ACK |
|
@sipa For Paypub, having the payments be visible in the blockchain for the receiver is extremely useful; w/o the ability to do so in scriptPubKey you'd likely implement it with an extra OP_RETURN output (maybe until we have a better Bitmessage to use instead). Not necessarily an argument either for or against doing so, but worth noting. |
|
Concept ACK |
|
Some tests fail with: I can't reproduce locally 8) |
|
Concept ACK |
|
Concept ACK. 1.) Not sure if this requires a BIP, I guess we don't need a BIP for every contract template and I can't find the other template matching params (like I also concept ACK the IsStandard rule for HTLC to allow blockchain-visible HTLC, though, this might require a BIP. |
|
OP_ANYDATA is just local wallet logic, it uses a range of script opcodes
that are disabled in execution, and is only used inside the matching
templates (I think it's a bad idea to mix them in the same CScript
type...), so I disagree with needing a BIP for that.
IsStandard changes so far have also been done without a BIP, but maybe we
can postpone making raw HTLC standard for now.
Certainly agree we need tests.
|
|
I agree IsStandard changes do not need a BIP, but it seems any transaction type supported by the reference implementation necessarily involves coordination with other software/people, and therefore should have a BIP written describing how it works. Is there a benefit to bare HTLC over P2SH (or SegWit) HTLC? If not, it seems pointless to expand the policy to allow for it. Note that many users do not enable bare multisig (and it should probably be disabled by default). |
|
I don't think initially we should make this standard outside P2SH (yet), so that's definitely a change that should be made to this PR. This work so far allows you to "import" a preimage into CWallet (so that you can redeem the atomic swap branch of the script) but it does not persist this to disk, and I'm curious if others think it should. (I'm skeptical of making bitcoind store secrets, especially if for some use cases they are ephemeral.) |
|
As an example of what this was written to enable: https://bitcoincore.org/en/2016/02/26/zero-knowledge-contingent-payments-announcement/ |
|
Wow, concept ACK. |
|
We should probably also wait until CSV is in, and add support for it in the constructed scripts here. |
src/rpc/rawtransaction.cpp
Outdated
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 new line?
|
@sipa CSV is almost in, but I don't think we should be deploying enabled generation for them until the softfork is good and settled. Maybe behind a hidden option or testnet only? |
|
Additionally, supporting RIPEMD160 for ZKCPs is a must. I will try to find some time to write an arithmetic circuit for it. |
|
After segwit lands (?) I will try to rebase and clean this PR up. |
|
@ebfull segwit has been merged to master and is also activated on testnet. |
|
CSV is active on mainnet! |
|
Rebased this on to master. Now supports RIPEMD160. Switched to CSV (block denominated mode). Added some RPC tests. It can be trivially extended to use CLTV in the RPC, I just need to come up with a solid UX for it. The same goes for "relative" time strings like "10h" or "5d." Also, still need to bring over the "preimage" display that showed in I'll try to work alongside #7534 for the remaining work, including submitting a BIP. |
src/script/standard.cpp
Outdated
| BOOST_FOREACH(opcodetype hasher, accepted_hashers) { | ||
| BOOST_FOREACH(opcodetype timeout_op, accepted_timeout_ops) { | ||
| mTemplates.insert(make_pair(TX_HTLC, CScript() | ||
| << hasher << OP_ANYDATA << OP_EQUAL |
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.
In the "ELSE" case any relay node may replace the top stack with anything without invalidating the tx. See related discussion at https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-August/013036.html
|
Needs rebase |
|
Still needs rebase. |
|
Before I rebase, I need to understand the consensus regarding preventing malleability of these scripts. Multiple suggestions were made and I'm not personally qualified to pick from them. |
|
@ebfull: I'd suggest this one. But you may want to discuss it on mailing list to make sure it is compatible with other implementations (if any)
|
|
@ebfull, this looks very interesting to me and many others. Would be wonderful for you can find the time to have a second look at this pull request since v0.14 has been forked off. |
|
I will be rebasing using @jl2012's script as the foundation, and update my BIP draft. |
| if (m < 1 || m > n) | ||
| return false; | ||
| } else if (whichType == TX_HTLC) { | ||
| return false; |
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 looks like you're assuming all TX_HTLC transactions are DOS attacks?
Why reject them all?
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.
@arielgabizon Would this actually reject all TX_HTLC items? I had the impression or understand that there was a design such that these would actually be completed in most instances. In lnd, a description of this was given as follows: "If payment/htlc amount is too small, than such output is called dust. If for some reason channel have been force closed during payment, and dust htlc/payment haven't been settled (both sides haven't agreed to remove the htlc and change the balances accordingly), th(e)n we (do) not include it in commitment transaction (thereby giv(ing it) as a fee to miners) in order to make it valid." For reference to this comment (from a contributor in lnd) see: lightningnetwork/lnd#115 (comment)
With that said, I'm not sure of how the differences will play out between how bitcoin core is planning on handling it vs. how it is handled presently in the lnd development process.
cc @ebfull
JeremyRubin
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.
Concept Ack.
I did some code review, overall looks very clean and concise.
I was slightly concerned with the use of new template parameters, but I think that the proposed new ones are reasonable & general purpose.
I think that the preimage map should persist entries; but perhaps that can be done as a later PR. I would also suggest adding a Lock/Unlock feature in RPC, because I think that that would ensure safer use of entries stored in the preimage map for users.
| case TX_HTLC: | ||
| { | ||
| std::vector<unsigned char> image(vSolutions[0]); | ||
| std::vector<unsigned char> preimage; |
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 reserve preimage.
| { | ||
| // Only consider HTLC's "mine" if we own ALL the keys | ||
| // involved. | ||
| vector<valtype> keys; |
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.
Please reserve keys.
| }; | ||
| const opcodetype accepted_timeout_ops[] = {OP_CHECKLOCKTIMEVERIFY, OP_CHECKSEQUENCEVERIFY}; | ||
|
|
||
| BOOST_FOREACH(auto hasher, accepted_hashers) { |
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.
Please don't introduce any new BOOST_FOREACH
|
|
||
|
|
||
| // template matching params | ||
| OP_BLOB20 = 0xf7, |
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.
Prefer to not make any new template matching parameters, but I see how it would be inconvenient to otherwise.
| opcodetype timeout_type) | ||
| { | ||
| CScript script; | ||
|
|
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.
Check that hasher_type and image.size() match?
| "\nArguments:\n" | ||
| "1. seller_key (string, required) The public key of the possessor of the preimage.\n" | ||
| "2. refund_key (string, required) The public key of the recipient of the refund.\n" | ||
| "3. hash (string, required) SHA256 or RIPEMD160 hash of the preimage.\n" |
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.
Maybe hash should be optional, and if not supplied a GetRandHash preimage should be selected and returned to the caller.
| std::vector<unsigned char>& preimage | ||
| ) const; | ||
|
|
||
| bool AddPreimage( |
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 that you should persist the PreimageMap to disk.
| const std::vector<unsigned char>& image, | ||
| const std::vector<unsigned char>& preimage | ||
| ); | ||
|
|
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.
Maybe add a RemovePreimage, LockPreimage, and UnlockPreimage call, which could be used to ensure that a node no longer has the ability to solve a particular HTLC or does not until explicitly allowed. These should also go to disk.
| if (request.fHelp || request.params.size() != 1) | ||
| throw runtime_error( | ||
| "importpreimage \"data\"\n" | ||
| "\nImports a preimage for use in HTLC transactions. Only remains in memory.\n" |
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.
If you add persistence, be sure to update here.
| // Only consider HTLC's "mine" if we own ALL the keys | ||
| // involved. | ||
| vector<valtype> keys; | ||
| keys.push_back(vSolutions[1]); |
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.
Maybe just for safety, assert(vSolutions.size() > 3)
|
Thanks for the reviews @arielg and @JeremyRubin. I intend to rebase this again and clean it up. Also, BIP199 has been submitted to start standardizing what is in this PR. |
|
@ebfull Thanks for mentioning... that was my question, regarding BIP 199, when reading this thread. A few questions actually -
|
|
This still alive? |
|
Unfortunately I'm too busy to carry the torch on this PR. :( |
|
I'll close this then. If someone wants to restart/pickup this work they can cherry pick/reference and open a new PR. |
| # activation should happen at block height 432 (3 periods) | ||
| min_activation_height = 432 | ||
| height = self.nodes[0].getblockcount() | ||
| assert(height < 432) |
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 we use assert(height < min_activation_height) here instead?
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 we can.
This adds support for timelocked contracts which can be used to atomically
swap hash preimages over the blockchain. It is very similar to the script
used by the lightning network.
Written in collaboration with Pieter Wuille.