It would be cool if paper’s author (h4sh3d) would review this contract here.
Thing is, child TX-es get signed before the parent. Parties only sign the parent once they verified children are signed correctly, and then the parent gets mined. With SegWit, it’s not vulnerable to 2nd party malleability, but on BCH it would be. So, I make the child TX-es signatures malleable too, so that link to parent can be updated without breaking the signature.
Also, I should have added a disclaimer: this is not intended as a production version, but as proof-of-concept to get the ball rolling.
One edge-case is malleability of fees (which could be closed with few more opcodes to tighten the TX). Bob could malleate the funding TX, and post his version of children to the mempool first and add 1 more input and output to ensure the fee will be minimum. Shouldn’t be an issue on BCH, but the possibility is there - and we can close this option, or use it as a feature, we could have these custom preimage signatures sign for the exact amount going from the input to output, and then either party could fund the TX with an extra input to pay for the fees - something not possible with BTC version
Because of malleability, it’s extra work on the app stack too, because they have to monitor for the possibility of parent’s TXID being changed and update the children accordingly.
Transaction malleability breaking the chain is. I believe 2-party Schnorr has no malleability and would be sufficient. Introspection may be another path forward.
Regarding your scripts, I don’t want to sign off on them due to their complexity, sorry. I can, immediately, note that since adaptor signature swaps leak a private key, they can’t reuse public keys. Accordingly, building a custom sighash should only require committing to bytecodes, not to values, if you want to micro-optimize this.
Yup, wrapped my head around it in the meantime. On BCH, signatures are 1st/2nd party malleable but, as demonstrated above, we can mitigate that by excluding parent TXID(s) from descendant signatures, so e.g. Bob posting a malleated funding TX can’t invalidate the pre-signed Refund path - because Alice can just update the pre-signed TX prevout ref. and Bob’s signature will continue to be valid.
2nd party maleability is still the problem - the 2nd party can roll another signature with a different random value, and post that TX instead of the agreed one, and with that invalidate any pre-signed children which would block the refund path, since, without SegWit, the signature is included in the TXID calculation.
Yes, see v2 of the contract (didn’t want to clutter by posting the code here).
Introspection enforces forwarding BCH to the correct recipient (either P2PKH constructed from either party’s key, or forwarding to Refund contract) + require a data signature to reveal the XMR share.
The covenant / introspection approach not only has significant size savings but also makes the TX chain more tight, I use it to enforce 1in-1out TX form, and commit to the fee while at it.
Yup, that’s why in the refund contract’s recovery path (if Bob diappears) we have to use another key for Alice, a non-leaking one.
Also note that in my contracts the signatures are replayable, so swap & refund keys must be considered one-time for that reason, too.
See the v2, we don’t really need to sign anything since we can enforce BCH balance flow with covenant / introspection opcodes, in which case the purpose of the data signature is just to unlock the spending path & force the party to reveal their XMR share.
The revealing signatures could really be signing whatever message, but the message needs to be known in advance for the VES to work, right? So I just make the output bytecode immutable (covenant) & require a signature of just the output’s bytecode as the message.
And I have coded a version (referred to as v3) in CashScript, too. It is slightly bigger when compiled, but the advantage is possibility of using CashScript tooling for application development.
I’ve noticed you talk about various malleability concepts online and I have yet to figure out what it is you are talking about.
Maybe I can start with what my position / understanding is.
You use “1st person malleability” sometimes, which is a term that feels acadamic or technical, but not really useful. Like you can’t call “breaking and entering” when you use your own key on your own front door.
1st person would be the owner of the private key re-signing the input. Not really malleability.
2nd person, as quoted above, as I understand the quoted part, is about an unconfirmed input being double spend, with the intention to make your transaction invalid and you need to re-sign to follow that change.
Similar to the above, this is not malleability. This is double spending.
Malleability is defined as a valid (signed) transaction being modified in a way that changes its TXID, but does NOT invalidate its signatures and thus allowing it to be mined in its new form, with the new TXID.
I am not aware of any way to malleate a normal p2sh or p2pkh transaction. Multisig is a bit tricky, but malleating without any of the signers being in on it is also as far as I know not possible.
Malleability for all the important cases has been solved years ago on BCH, no?
Yup, and on BCH we closed off 3rd party malleability.
If you and me sign a 2/2 then you’re my “2nd party” and from my PoV I’m the “1st party”. Our signatures are independent, meaning any party can reroll their own signature to change the TXID without having to get a new signature from the other party.
This means I can double-spend a 2/2 all by myself and invalidate the whole graph of descendant transactions, and that would be a problem for the original swap scheme outlined in the paper, for the same reason it would be a problem for Lightning Network: they use multisig to emulate covenants.
We can work around the issue of invalidating descendant transactions by using proper covenants - which can be coded such that they allow updating the prevout refs without breaking any signature, meaning the descendant transactions graph could be reconstructed if the parent gets double-spent, without needing updated signature from the other party.
Any other type of “malleability” you described in this thread doesn’t fall under the definition of malleability. Any TXID change that requires access to private key is not malleability.
It typically is just scamming / double spending / updating-the-tx. Whatever is appropriate.
Re-using a known term that is still active in the crypto space to mean something different doesn’t feel right. It certainly confused me, and I expect it to cause confusion in others too.
What is the exact definition in context of multisig transactions?
For P2PKH sure, there’s only 1 key and using it to create a new signature is a double spend.
For multisig, I think the term “malleability” would still apply since you can malleate the TXID without having access to any of the other keys even though they’d normally be required to change the transaction.
BIP-141 recognized this in the motivation section:
In the case of an m-of-n CHECKMULTISIG script, a transaction is malleable only with agreement of m private key holders (as opposed to only 1 private key holder with BIP62)
The paper that describes the XMR-BTC swap claims it’s not possible on BCH because of it:
The bitcoin transactions in this protocol require the fix for transaction malleability provided by the SegWit upgrade. This allows us to chain transactions without necessarily broadcasting them. This protocol is only compatible with cryptocurrencies which use a bitcoin style UTXO model and have an equivalent malleability fix such as Litecoin (i.e. Bitcoin Cash is not compatible.)
Do you believe it is possible to modify the details of the BTC XMR atomic swap protocol so they can work BCH XMR? Presumably this would use introspection and allow un-broadcast recovery transactions to be modified by a potential victim of an attempted rug pull.
In the context of protocol development and even advertising, we have no malleability there (to the best of my knowledge) as it would require private keys to make changes and thus what leaves your wallet is what gets mined.
But then we have the birthday paradox, we have the mess of needing to use p2sh instead of the script being in the prev-out and indeed private keys outside of your control.
Its not an issue in 99% of the cases, but in real life using them unconfirmed is… tricky.
Well, I don’t think it is that tricky. I could be wrong (not going to read the whole paper on my Sunday afternoon), but that sounds like BS.
BCH has Schnorr signatures, which means the needed multi-signature capability required by the two scripted transactions on the BCH chain should be transparent to the blockchain, known only by the swap code Alice and Bob run.
I am trying to thouroughly understand the BTC XMR paper before commenting further. I am wary of subtle details in the protocols, scripting, or cryptography.
That’d be 3rd party malleability, i.e. anyone being able to change a signed TX’s TXID. I think this has been closed with HF 2019-11-15 Schnorr Multisig so you’re right – changing a TXID of a TX signed with multisig would require access to a (singular!) private key. Not keys. Key, just one, any one key from the set, regardless of the required number of signatures required by the script.
This is the literal definition of 2nd party malleability: a single signer can change the TX without approval from other co-signers even when required number of signatures is > 1.
Even if the scripts of the paper were “bare” (as opposed to P2SH), the problem would still be there.
Sorry, it’s not BS. Using Bitcoin specification of 2016, or BitcoinCash specifications prior to activating HF 2018-11-15 the script had no way to work around the problem. Paper authors were probably just unaware that we had covenant through OP_CAT, OP_SPLIT and OP_CHECKDATASIG. That’s understandable, to do covenants using 2018 spec is extremely brain-twisting. Thankfully, since 2022, we have introspection opcodes – meaning it’s more straight-forward to code covenants, and above I presented such covenant-based solution.
Why is 2nd party malleability a problem for the scheme?
Let’s first observe possible flows of BTC/BCH:
[Bob's P2PKH UTXO]
|
(fund swaplock)
|
V
[SWAPLOCK UTXO] --(complete swap)--> [Alice's P2PKH UTXO, Bob gets XMR]
|
(initiate refund, option available only if timelock t_0 expired)
|
V
[REFUND UTXO] --(complete refund)--> [Bob's P2PKH UTXO, Alice gets XMR]
|
(recovery and punish Bob, option available only if timelock t_1 expired)
|
V
[Alice's P2PKH UTXO, Bob gets nothing]
During the off-chain interactive setup phase, both parties pre-sign and exchange signatures for all multisigs and construct and verify XMR key shares.
Then, Bob goes first and funds the SWAPLOCK.
Alice sees that, waits for some confirmations, and then funds the XMR output.
Then, after the XMR TX gets some confirmations, Bob reveals the hashlock secret to Alice, opening the (complete swap) path for her. If he fails to do it, Alice has to wait for timelock to initiate refund.
Then, Alice opens the hashlock and signs the (complete swap). Bob sees the signature published and from it extracts the XMR key share he needs to collect XMR – this part is the verifiably encrypted signature (VES) crypto magic.
If Bob goes missing (his fault) Alice just waits for timelocks to expire and gets Bob’s BCH and he gets nothing and XMR is stuck forever (unless he shows up later with a good excuse and Alice shows grace and reveals her XMR share to him).
But what if Alice is malicious? She could just wait for the timelock t_0 to expire and race to submit a changed (initiate refund) TX by swapping her old signature with new one (it’s 2-of-2 she can’t change the TX template without Bob, but can change TXID). That would mean the pre-signed (complete refund) TX that Bob has would be useless and he couldn’t complete the refund without Alice generating a new signature for him.
Alice could then just wait for the timelock t_1 to expire, collect her BCH, leaving Bob with nothing, punishing him out of malice.
With covenants, Bob doesn’t need Alice to go through with the refund even if parent’s TXID changes - he can update the prevout refs all by himself without invalidating the spending path.
FWIW, the paper by Gugger (h4sh3d) is not the only proposed Monero atomic swap protocol. Some others that have not been implemented in production code AFAIK:
It highlights the problem of fees on BTC and how Bob could be exposed to a draining attack because he has to go first. IMO it’s less of a problem on BCH since our fees are significantly lower (also helped by the contracts being smaller). The above paper proposes an alternative where Alice goes first by funding XMR output, but it depends on having adaptor signatures on both chains (as opposed to just on BCH/BTC in the original protocol), which is pending more research.
The 2nd paper needs capability to pre-sign XMR, which is not supported at the moment.
The 3rd paper relies on some generic crypto magic which goes over my head but it seems to be universally applicable and the transactions will look like ordinary P2PKH, so it is an improvement over HTLCs since it preserves privacy and transactions would be smaller, and also allows cyclic swaps: a multi-party chain of atomic swaps, such that either the whole chain goes through, or nothing does.
The 4th paper uses one-way payment channels to implement an interactive cross-chain swap. Parties simply update the channels in ping-pong fashion: transfer the currencies in small increments to each other until the swap is complete. This sounds promising, as we can have efficient such channels on BCH!
I understand the logic of combining those concepts into one, but inventing a new type of malleability this way is mostly just confusing…
And, the important part is that we still are in a phase where the rest of the world is unaware that Bitcoin Cash fixed transaction malleability, so reusing that word for something very different is not something I think is smart.
I’ve had various people ask what malleability is still a problem in the protocol. The knowledge that we fixed them in previous hardforks is absolutely not common knowledge (the segwit loving people are basically saying if its not segwit, you still have malleability) So… My question to you is that maybe you can come up with something less loaded there. “One of the parties re-signed the tx and changed the txid” doesn’t feel like its anywhere near the same concept as malleability fixed with segwit. Transaction malleability - Bitcoin Wiki
It is a case of “scriptSig Malleability” described there, e.g. in case of 2-of-2 multisig one of the parties can malleate the scriptSig as a whole without approval of the other party, which is why it’s called “2nd-party malleability”. In case of 2-of-3 with parties A, B, C: C could intercept a TX by A & B and replace either signature with his in order to change the TXID. This is solvable by:
SegWit (BTC)
PMv3 detached proofs (I think Radiant implemented this)
Using TX “idem” for prevout refs instead of TXID (BU was proposing this and implemented it for their new chain)
SIGHASH_NOINPUT (BCH solution, we construct the equivalent TX preimage using introspection opcodes and verify it using OP_CHECKDATASIG). This was also proposed in LN WP, pg. 57
SegWit BIP recognizes it as malleability in Motivation section:
In the case of an m-of-n CHECKMULTISIG script, a transaction is malleable only with agreement of m private key holders (as opposed to only 1 private key holder with BIP62)
We implemented BIP62, so the multisig problem persists - but it’s not really a problem for us because we have more advanced Script and can work around it by constructing SIGHASH_NOINPUT, or even better - directly use covenant to enforce particular BCH flow instead of relying on pre-signed multisig.
thanks for the detailed answer. I’m not sure how this relates to my point, I already acknowledged your logical naming makes sense, I’m not arguing that.
I hope you still understood the gist of my post and please consider it.