(mostly) Lock free transactions

I don’t quite understand how this works. Could you provide a minimal example of a transaction flow the way it is done now by the wallets and how they could improve it?

Right now if I only have one output, and send out a slate to pay someone, then that “locks” my single output, and I cannot send out slates to anyone else I want to pay, until the first slate comes back and the tx gets published and confirmed.

2 Likes

Yeah, this makes sense :ok_hand: why do you think exchanges benefit from this the most? Is the assumption here that they have a few utxos that get locked up?

Exchanges may be relying on http to avoid the complexities of having many locked outputs.

2 Likes

Why does the title indicate “mostly”? Is it in regards to 3+ parties in the transaction?

I believe the wallet considers an output locked until its spending is sufficiently confirmed.

Yeastplume pointed out that i had an offset sign issue in the original post. I decided to fix it in place, as marked with an EDIT.

There is some interesting overlap here between “mostly lock free transactions” and “payjoin”.

Here both sender and recipient provide outputs and then the sender selects input(s) to complete the tx.
With payjoin both sender and recipient provide outputs and then sender and recipient pick input(s) to complete the tx. I guess at a cost of one party having their outputs locked up for longer.

Does the sender need to use a “placeholder” input here?
If the recipient sees the senders offset prior to adding the input, then the adjusted offset once the input is added, does this not leak the private excess for that individual input?

It was discussed before on keybase I think. And you`re right. The recipient should never see the prior-to-adding-their-input sender offset. In this offset scheme, the recipient should give to the sender their partial offset, and never the opposite. And the sender to finish the job themselves.
In case of PayJoin transactions, I think slightly more care should be taken, but should not have any problem.

Both sender and receiver providing inputs matters more for bitcoin where amounts & addresses are visible. In grin it shouldnt matter if the sender provides 2 inputs, right? Could even be zero value decoys on either inputs or outputs. Maybe I’m missing something.

If both sender and receiver provide an input then you no longer have any indication which “direction” funds flow in the tx.

  • 1 input -> 2 outputs suggests a change output that may possibly be linked to the original input with other analysis (maybe it subsequently gets spent alongside another output linked to the original input).
  • 2 inputs -> 2 inputs leaks far less “direction” information

But yes - sender providing both inputs would be indistinguishable from this. Obviously this would be no benefit though if the sender always provided both inputs. The benefit with payjoin is that once some subset of txs are doing this then you can no longer identify those that do vs. those that don’t.

I wonder when this becomes beneficial, it seems as if 100% of the time isnt. Maybe it can be chosen at random and the node could communicate to sender when to do it, or maybe even early stem phase nodes could do it. But it also seems as if any approach to have some % of txs do this would also be a bad idea. I am not sure how well PayJoins would work. Either way, I think it would be best to avoid another round of interaction if possible to avoid the need for the recipient to provide inputs, maybe it would be fine over tor.

Is it fair to generalize “mostly lock free” roughly along the following lines -

  1. sender and recipient agree on a fee
  2. sender and recipient interactively build the kernel (signature signs the agreed fee)
  3. recipient adds output(s), possibly input(s), partial kernel offset
  4. sender adds output(s), input(s) and partial kernel offset
  5. tx can be broadcast

No inputs are “locked” prior to (3).
The signature from (2) is potentially subject to rogue keys but (3) and (4) and the creation of a final valid tx ensures key ownership due to the presence of valid bulletproofs.

Asked another way, and I think we have had discussions about this before, can we build tx kernels “in advance” and decouple this part of tx building from the selection of outputs and inputs.

1 Like

I personally think this is correct

No; the recipient never sees the original offset.

So they pick a partial excess at random?
And then in 3), the partial kernel offset is set to sum of output blinding factors minus sum of input blinding factors minus partial excess chosen in 2).
Yes, that would be equivalent to my scheme.

1 Like

It is my understanding that currently, thanks to compact slates, inputs are not a part of the transaction building process until the finalization & posting step

If this is indeed the case, why are they locked before the final step, and what change is proposed exactly?

Would love to have somebody explain it more thoroughly.

2 Likes

When I was working on Grin-wallet contract prototype, I had to think about this a bit and would like to describe my current understanding. I think there are 2 actions every party does with respect to their inputs/output:

  1. First, it decides which inputs/outputs it will use and locks the inputs
  2. Second, it adds these to the slate

The 2. can always be done at the sign step. This means that we can do it such that the party at step2 never knows which inputs/outputs will be added by the initiator until they see the full transaction in the mempool. This is true even for the case of an early lock, because an early lock can select the inputs and lock them without adding them to slate (in grin-wallet, the inputs and outputs are added to the Context struct). At the moment, we add them to Context and Slate at the same time, but that’s not required and it would be better if we always “late add” inputs/outputs on the slate.

Let’s call this early-lock & late-add. I think this could be the default for every wallet because:

  1. If both parties contribute fees for their own inputs/outputs (as they should), then it’s impossible to make a wrong fee estimation because they locked the inputs and prepared the outputs before signing. This brings stability to transaction building and users should not be hitting fee estimation errors. Late-locking could fail on the first try and succeed a minute or two later because the wallet received new outputs that can work as inputs etc. We might want to minimize these cases and it’s best if we eliminate them completely.
  2. It hides input/output contribution of the initiator until the tx is in the mempool which means that the person at step2 can’t opt-out of a transaction because a specific input was used. This means the party at step2 can’t stop coinswap input contribution. In theory, they could RBF it once we start supporting this, but this comes at a cost.

The late-lock has its own benefits though, especially when the transaction takes a long time to make which allows us to reserve the inputs just in time.

It’s not clear to me which flow is more optimal for exchanges, it seems a bit tricky. An exchange could limit a user to 1 active withdrawal/deposit at a time meaning they can’t start another one until they either cancel or complete the ongoing one. Late-locking has some advantages, but it may result in wrong fee estimations and the exchange would need to handle these.

1 Like

Iirc, I was once told we don’t support RBF and we only support CPFP. I don’t remember why that’s the case though