Play Attacks and possible mitigations

Yes, that would work. The problem is that the current “cancel tx” doesn’t really cancel anything. Letting it expire is one way of having it truly canceled. If you don’t want to wait for that, and decide to build another tx to pay the same receiver, then you would have to make sure that it
shares at least one input with the canceled tx, so that there is no risk that both go through.

2 Likes

Seems like the right time to share this idea here.

Perhaps this is another possible mitigation of play attack. Let’s say that I have inputs O1, O2, O3. Given these inputs, I have a deterministic order that is based on some local random e.g. o1_hash = Hash(root_key | O1), o2_hash = Hash(root_key | O2), o3_hash = Hash(root_key | O3) (the root key is to avoid having predictable hashes just from Pedersen commitments). Let’s define the order of inputs that will be used as [o1_hash, o2_hash, o3_hash].sort(decreasing=True). If I create a tx A, then I pick the first M inputs that sum up to at least whatever I am sending out. This means that I will pick the minimum input with 100% certainty. If this tx doesn’t make it, then when I create a new tx, I will reuse the first input in queue which is also shared with the previous tx that did not make it and if this second one makes it, it means that the first one can’t be ‘played’ because they shared the same input. This might only work if we have sequential creation of txs (not parallel).

Note: If you have sequential tx creation, then it’s really only necessary to include the current “minimum” input. This way you are invalidating your previous txs if they don’t make it for whatever reason (there are likely some edge cases that need to be covered)

Rather than a concrete example of how this is still broken if 1, 2 and 3 are implemented let me try and illustrate why (1) above is not possible in the general case (only possible if there is a single “sender”).

  • Let us define a “sender” as a participant in the transaction who contributes one or more inputs to the transaction.
  • The transaction involves s participants who contribute inputs (senders).
  • At the end of the interactive transaction building process, one single participant will have possession of the finalized transaction. This participant can choose to withhold the transaction, refusing to broadcast it to the network.
  • If s > 1 then by definition we have at least 1 “sender” who contributed inputs to the transaction but with no ability to broadcast the transaction. Their output is “spent” in the context of their wallet but they do not know when (or if ever) it will be accepted and confirmed on-chain.

Given this, it is impossible to guarantee (1) “Receiver never learns partial offset of sender during tx process.” replacing “Receiver” with “participant in possession of final transaction” in the general case.

The partial offsets are not the issue here. The problem is related to who is in possession of the finalized transaction (and has sole discretion over broadcasting it or withholding it).

Do you disagree that possession (and withholding) of the finalized transaction is the problem here?
It is irrelevant whether participants see the partial offsets of other participants, possession of the finalized transaction is sufficient.

If slatepack address/tor address is apart of the tx building process, wouldnt it be trivial to send each iteration of the process to all online users? I am not sure if that is a security risk, but it should be trivial to do. Certainly a malicious user could block this but then you’d know.

@antioch I haven’t read through all of the previous messages, but as long as the person who ends up with fewer coins than they contribute (smaller outputs than inputs contributed) is the person who ends up with the final transaction, I don’t see the issue. They have no incentive to pretend it failed and perform a “play attack” later. Am I missing something?

1 Like

Here’s my proposal for preventing “Play attacks” in the invoice workflow:

Stop supporting a special workflow for invoices. Instead, an invoice should just simply be a file/blob/json/whatever (like a BIP70 PaymentRequest) that indicates the receiver address, amount owed, and potentially a message of some sort. Then, accepting (ie. paying) the invoice should just follow the normal send workflow. Then, the sender is always the one who sees the final transaction, and is responsible for broadcasting it. Failure to broadcast means the invoice is unpaid.

3 Likes

Thanks for the effort of describing your idea.

There is absolutely no problem here.
There is only one guy in the group that is supposed to publish the transaction, and if he or she doesn’t want to publish it then it won’t be published. And that’s why I also explained you the kernel offset protocol because if there is flaw for it then you can play some partys output by using the partial offset you learned in the tx offset exchange protocol and its corresponding partial excess, which is a critical vulnerability. So it was not irrelevant at all to describe this unlike what you said. It is precisely a synequanum condition that would enable to do secure interactive coinjoin in Grin without the possibility of play attacks.

Anyways, so, if the person that is supposed to publish the tx doesn’t publish it, there is no security problem arising. Either the others can remove him from the coinjoin tx and do another round without him, or they can send individual transactions to send their fund anyway.

As I said, play attacks are a possible consequence of someone censoring the spend of a tx. Typically it is the receiver in the case of 1-1 txs, and any other parties in case of multiparty txs, without the sender (1-1 txs) or the attacked party in the group (multi party txs) noticed the real issue that was happening (receiver learned sender’s spend information in the process of his attack in the case of 1-1 txs).

What you describe is not a play attack, it is just a normal and harmless event in blockchain. To use the same term as you used: it is irrelevant.

I don’t think this is possible to determine in anything but the simple case.
Take payjoin for example (regardless of personal opinions around payjoin itself).
2 senders, neither participant knows how much the other contributes.

:+1: This makes a lot of sense to avoid the “play attack” scenario in the invoice workflow.
With hindsight this is probably a good example of why special cases end up being problematic…

Edit: Just saw both of these have been discussed on keybase.

Not sure I follow. I’m 99% sure my example is along the exact same lines as the OP in this thread.

I do think we are actually in agreement here. The solution is to create a new tx. And do so in such a way as to ensure the original cancelled tx cannot be subsequently broadcast.

As OP states -

Again, It is not a play attack. Your just doing blockchain 101 here. And even if you spend nothing, there is no security issue!

There is absolutely no care to have. If you do nothing and that you receive the tx in one week, who cares. The sender didn’t leak tx information to you in the tx building process due to doing a proper and secure partial offset exchange.

That’s what you need to understand when speaking of play attacks. There is a leak of Spend information that sender didn’t notice and the tx didnt make it to blockchain, somehow censored by an attack or just the sender not sending the tx for some reason (but you need to have leakage of spend information). Please instead of referring to OP, try to understand the concrete instances and the description i formulated in my previous posts.

It’s clear, even when using PayJoin, which party is receiving funds. If I want to send you 2 grins, and we agree to use PayJoin, you still end up receiving 2 grins more than you contribute, regardless of how much the individual inputs and outputs are worth.

Hmm yeah of course, that’s a good point. I thought payjoin was an example of this but it is not, payjoin is still 1 party transferring funds to the other party, just obfuscated somewhat.

If we can determine the overall “sender” then yes agreed - this can simply be avoided by ensuring possession of the final tx ends up in the right hands. :+1:

Based on the OP and the title of the thread, this is an example of a “play attack”.
I suspect your redefinition is the source of a lot of confusion here. I think you are redefining “play attack” as a specific cases of this where a partial offset is leaked during tx construction. This is not the only way to set the conditions up though.

What are you talking about.
I recall you that I discovered them.
Your stuff has no security issue. Please think rationally :slight_smile: There is no attack in what you describe.

Your not doing yourself justice with this constant irrational denials that you have on things.

An additional benefit with this approach is that it means “invoices” also would support payment proofs, as they would technically be regular sends.

4 Likes