Grin Transactions User Interactivity

There was a discussion on keybase regarding transaction interactivity so I’ve decided to explain my concerns here as well. From my understanding, Grin transactions require interactivity only at the “wallet address exchange” level. Once this step is done, the actual transaction building process does not require interactivity (except if you’re exchanging slatepack strings).

Disclaimer: I could be misusing the terminology, but I think that the points still stand and this should be discussed.

PayJoin transactions open an attack vector where the sender could perform a UTXO spoofing attack on the receiver. This means that the sender could ask the receiver to contribute an input, but then never publish the transaction. This could be done N times and the sender could find out all the outputs that the receiver owns.

There’s another variant of a UTXO spoofing attack that is possible today which is a dusting attack. This is done by the sender spamming small value outputs to the receiver. If such a spam is successful then the sender could learn the receiver’s outputs over time because they get used with other real outputs - which is why I say it’s a variant of UTXO spoofing attack.

So a PayJoin on its own only makes it simpler, it doesn’t introduce something that is impossible right now. The underlying issue to me seems the fact that the receiver has no control over what they are receiving. As soon as the interactive step of exchanging the wallet address is done, they trust the sender with everything that follows because the steps are automated.

My opinion is that the receiver should have complete control over what they receive in their wallet. This means that they should not only control from whom they receive but also what they receive. This seems only possible by having a manual confirmation step for the values they are receiving - which to my knowledge is not possible at this stage (except for slatepack strings). We would of course need a way to somehow support receive-only wallets to allow users to have donation addresses and similar.

I don’t see this as horrible as some other people do. This is very similar to how we use cash today - we count the coins we receive and the coins we give out.

TLDR; UTXO spoofing seems a problem that is not inherent to PayJoin transactions. It’s present in the current transaction scheme, payjoins just make it simpler. We might want to address this vector to avoid having these attacks possible.

P.S.: @Paouky pointed out that if the wallet address becomes public at some point, it’s possible that they can’t even control from whom they receive.

P.S.2: Another possible mitigation might be if a wallet blocked a receive from the same wallet address twice

1 Like

Let me just add that dust attacks are definitely an issue in Bitcoin, they’re a legitimate tactic to diminish user privacy. To avoid it, most wallets have an advanced settings option that instructs the wallet to ignore these dust outputs, but it’s rarely used. Still every Bitcoin user is prone to these attacks. They even simplify chain analysis on Monero.

The same solution could be applied to Grin, however, unlike in other chains, simply ignoring those outputs bloat the chain. On the other hand, consolidating them would mostly reduce user privacy.

If we use to our advantage the fact that interactivity is already required for transactions, we can solve this problem completely, by choosing which transactions we’d like to receive even if done via TOR.

This works especially well for UX if finalize step is eliminated per the recent proposal; The receiving user would click confirm to receive a transaction and it would straight up be posted to the chain. This is a superb user experience, identical to the flow of many popular fiat payment apps (send coins -> receiver confirms -> coins received).

That would make Grin the only chain completely safe from dust attacks.

2 Likes

It’s impossible to guard against with Payjoins though. There are a number of solutions, OTOH, to resolve dust attacks - just don’t spend coins you don’t recognize being a simple one. But there has not been a solution to the input leakage for PayJoins. That is, unless we eliminate the finalize step[1]. Then, PayJoins don’t have the same privacy concerns, since the receiver only adds the inputs at the time of broadcasting a transaction that will presumably make it to a block.

[1] https://github.com/mimblewimble/grin-rfcs/pull/59#issuecomment-675991756

I think it’s possible to solve both utxo spoofing attacks (dusting and payjoin inputs) with the idea I shared in the first post which boils down to “the receiver should know what they sign”. The root cause of both problems is that with the current transaction building implementation only the sender really agrees with what will be sent. The receiver naively trusts the sender what kind of partial tx they will send them because the transaction building process is automated on the receiver side. Having the receiver actually confirm what they are about to receiver should eliminate dusting attacks because you simply don’t accept to receive what you don’t expect. Similarly, you don’t repeatedly confirm payjoins that would leak your inputs - at most 1 could be leaked if the sender is dishonest but this would be a rare case and can be handled easily.

I know some people don’t like this idea, but I’d compare it with the same ‘dance’ we do when we buy something with cash at the store:

  1. the cashier (receiver) says the would want to be paid X
  2. the payee (sender) gives Y coins to the cashier
  3. the cashier (receiver) confirms that Y >= X and returns Y - X as change

There are a couple of differences in our current flow:

  1. the step 2. is augmented such that payee also says “I’m paying Z for the goods”
  2. there is no step 3 in our interactive transactions because the receiver’s flow is automated. We simply let the sender tell us how much they are paying and then we automatically say “ok” and accept Z coins.

So the sender can actually override the agreement. In order to make the steps the same, the receiver would need to confirm that Z == X. Which imo makes sense because you should always check whether the contract you sign on chain matches the real world agreement.

Sorry, I meant it seems impossible to guard against for automated wallet receives of course.

Your general idea is that users should be more involved in the receiving process, while as you know, the general consensus among users is that they want to be less involved. Receiving should be easier, not harder, though I appreciate that you’re talking about an optional choice, not a mandatory requirement.

1 Like

Ah I see. Yeah, I’m not sure automated receives can work with payjoins regardless of the scheme if the sender can initiate multiple sends and they can go through. The only ways I see to really prevent this is by either having use once address where a wallet would refuse another tx using the same address or with a manual confirmation step from the user.

I have no clue what the community thinks with regards to this - I’ve not seen anyone raise this concern apart from me a couple of times on keybase. I can’t even estimate how many people have even thought of the problem I’m describing above. I personally would prefer to review what I’m receiving in the same way that I count the money I get when I buy/sell stuff with cash - it feels safer to do that when handling money (this is just my view though).

1 Like

I actually think it should be interactive by default (you are required to confirm that you want to get a tx) with an option to auto-receive from a selected group of people (somehow through generation of extended public keys, eg. you would have a list of extended public keys and if a slatepack address is generated with one of those keys then you auto-receive). I think it’s important that the user has control of this, even if it’s not interactive by default then at least an option to switch to interactive. Another option could be auto-receive above some value