Open hackaugusto opened 5 years ago
max
in max(R', E)
looks weird to me. You don't care about the value of R'
when you have lots of expired locks?
The biggest question that I have with the above is that if a locksroot is also required, or if just a returned amount is sufficient.
I think a locksroot is required. Say two transfers with two different secret hashes were refunded. And say only one of the secrets has been revealed. Now it matters a lot which lock was refunded and which lock is alive.
max in max(R', E) looks weird to me. You don't care about the value of R' when you have lots of expired locks?
I don't understand. How does max(R', E)
mean that expired locks are ignored? (I'm assuming that is what you meant by don't care).
The core idea here is that both participants will be changing the same value. To avoid synchronization among the parties the value is made monotonic and max
is used, otherwise we would require some sort of synchronization among the nodes to change this value. The next thing is to make sure the result of max(R', E)
is semantically correct and not exploitable.
max(0,100)
is equal to max(20,100)
. So when E
is 100
, you don't care whether R'
is 0
or 20
.
That's weird. When the channel is very young, E
is still zero, so every change in R'
matters. When the channel is very old after many expired locks of some value, E
would be big, and you don't care about small R'
s anymore.
I think E
can grow big while R'
can stay at zero.
max(0,100) is equal to max(20,100). So when E is 100, you don't care whether R' is 0 or 20.
Yes, that is intentional.
It has to possibilities, R' < E
or E < R'
. The value of R'
is controlled by the partner node, while the value of E
is controlled by the local node. For the case R' < E
the result would be E
, this means the local node does not have to wait for the partner to send a RemovedExpiredLock
message. E < R'
is the opposite, the partner does not have to wait for the local node to send a RefundTransfer
@hackaugusto
I send locked transfers but never reveal secrets. So E == 100
or something.
I send a payment through this channel but the routing fails, so I get a refund R' == 20
.
The max computation kills my refund.
@pirapira That would be an invalid message, it does not refund anything, the correct value for R'
is the previous E
in addition to the new refund amount, so it should be 120
.
Refunds include expired locks?
With this definition, yes. Pretty much a refund message would be the partner node saying it's okay for the local node to use the tokens from a given lock, because the partner is "anticipating" the expiration.
Edit: Perhaps refund is a bad name for this approach, but I didn't think much about alternative names and this is a proposal for a new approach to refunds after all.
I see definitions:
R' = refund
E = expired
but I see no equations between refund
and expired
.
Are they somehow related?
Is it intentional that
U' = unlock
Has unlock
instead of unlocked
?
Are they somehow related?
Yes, they are "the same value" from the settlement algorithm perspective. This happens because the max
is used in formula P = L - max(R', E) - U
.
So, R'
and E
supposed to be equal in a completely synchronous world?
Still max
is weird.
Let's say we have an event 1 that inceases R'
. And event 2 that increases E
. Both events increase the value by 10. In total the increase should be 20.
Event 1 happened on the peer's side so I see R' == 10
. Event 2 happened on my side so I see E == 10
. These two ten's come from different causes so the perfectly synchronous world I should see 20 already, but the max
calculation only gives me 10.
Yes, they are "the same value" from the settlement algorithm perspective. This happens because the max is used in formula P = L - max(R', E) - U.
Now you've put me in a loop. I asked why max
and you answered it's because the same value. It's the same value because the max is used?
I need to see what kind of event increases which variable.
Here are two examples:
A -> B; LockedTransfer; locked_amount = 10 B -> A; Refund; refund_amount = 10
With the above, there is nothing pending, so P = L - max(R', E) - U
would be P = 0 - max(10, 0) - 0
, and there is not transfer of value. Which means the partner did a refund without locking additional funds.
Let's add some interaction:
A -> B; LockedTransfer; locked_amount = 10 A -> B; LockedTransfer; locked_amount = 20 B -> A; Refund; refund_amount = 10 A -> B; Unlock; unlocked_amount = 10
In this case, there is nothing pending P = L - max(R', E) - U
would be P = 20 - max(10, 0) - 10
, and the partner get the 10 tokens, because it had a net positive of 10 token from the formula N = D - W - U' + U
, which would be N = D - 0 - 0 + 10
(Note: I had to fix the net formula)
This is a hard case for me:
I don't really know how to fix that race.
A -> B; LockedTransfer; locked_amount = 10 A -> B; LockedTransfer; locked_amount = 20 B -> A; Refund; refund_amount = 10 A -> B; Unlock; unlocked_amount = 10
So the two parties disagree on the first lock, whether it's refunded or unlocked?
When you send RemoveExpiredLock, do you write a bigger E
?
When you receive Refund, do you expect a bigger R'
?
1. A->B; LockedTransfer
2. A->B; LockedTransfer
3. Time passes
4. B->A; RefundTransfer for 1
5. A->B; RemoveExpiredLock for 2
What's hard about this? I see no conflicting information.
So the two parties disagree on the first lock, whether it's refunded or unlocked?
No, the values are monotonic, so a locked_amount
of 20
means a second lock of 10
. I didn't specify which lock was unlocked an which was refunded in the example for simplicity's sake.
When you send RemoveExpiredLock, do you write a bigger E? When you receive Refund, do you expect a bigger R'?
Yes
Then why do E
and R'
grow together?
Then why do E and R' grow together?
They are changed by different computers separated by a network in between.
Edit: By "together", do you mean atomically?
I heard E
and R'
are "the same value" (in the synchronous world).
What's hard about this? I see no conflicting information.
One of the messages will be invalid, and then we have to reprocess the queue of messages. The whole point of using monotonically increasing values is to avoid synchronization, we need a policy on how to move forward even if that happens without having to synchronize.
Is there a rule like, "When you receive Refund, you have to send RemoveExpiredLock"?
There has to be some connection between E
and R'
?
1. A->B; LockedTransfer
2. A->B; LockedTransfer
3. Time passes
4. B->A; RefundTransfer for 1
5. A->B; RemoveExpiredLock for 2
I can see all messages being valid. What kind of assumption am I missing?
Maybe the locks must be removed in the same order as they are created?
Maybe it's easier to start with the lifecycle of a hashtime lock.
So a hashtime lock can have these states. a. hasn't been created b. A added it in A-->B side of the channel state c. B saw it in A-->B side of the channel state d. expired e. unlocked f. refunded
And a lock can move
Right?
Is there a rule like, "When you receive Refund, you have to send RemoveExpiredLock"?
Unless the current rules don't work (as in, send the remove expired lock after the lock expires), I wouldn't change it. But I did not think it in detail to see if there is a corner case that breaks this proposal.
There has to be some connection between E and R'?
Yes:
Effectively the defined values are saying that for the life time of the channel "X tokens were locked in this direction" locked_amount
. "X tokens were moved to the partner" unlocked_amount
. "X tokens were returned because the transfer failed" (refund_amount
and expired_amount
).
Maybe the locks must be removed in the same order as they are created?
That would be bad for refunds, either only the first or last lock would be refundable.
"X tokens were returned because the transfer failed" (refund_amount and expired_amount).
Isn't expired_amount
about the current block number moving ahead and the expiration block has passed?
Maybe refund and expiration are two ways that the transaction fails?
Then I'm imagining now: E
is about the expired locks from me to the peer. R'
is about the refunded locks from me to the peer.
Isn't expired_amount about the current block number moving ahead and the expiration block has passed?
The block being larger than the lock expiration is a requirement from the sender perspective. But the value itself only increases when the sender sends a balance proof with it. (I have the feeling I didn't get what you meant with this one)
But the expired locks are counted towards the sender's balance, so E
should be about the locks from the peer to me, that has expired.
Maybe refund and expiration are two ways that the transaction fails? Then I'm imagining now: E is about the expired locks from me to the peer. R' is about the refunded locks from me to the peer.
yes (edit: almost, it should be R' is about the refunded locks from the peer to me.
)
If E
and R'
are about locks in different directions, why are they financially the same value?
I miss the table with :arrow_up: and :arrow_down: filled for all messages and all variables.
If E and R' are about locks in different directions, why are they financially the same value?
expired -> used by the sender refund -> used by the receiver
They both have the end effect of returning locked tokens to the sender.
I miss the table with arrow_up and arrow_down filled for all messages and all variables.
All values are monotonically increasing, what changes up or down is the balance (which is computed from the monotonic values).
Edit: With this proposal, the effect of a refund and a expired lock from the local view will return tokens to the sender, but from the partner's view it may not make a difference if the complementary message has been sent ... so I guess we also need a =
entry in such a table.
I still don't get it.
E
.R'
.Why do these values need to be equal?
Why do I take the max
of the amount of lock A and the amount of lock B?
Why do these values need to be equal?
In you example they are not, the values are mixed. This would make sense:
I send a lock A to the peer. This lock expires. That's counted in E. I send a lock B to the peer. The peer refunds this lock. That's counted in R'.
I'm confused. You wrote
yes (edit: almost, it should be R' is about the refunded locks from the peer to me.)
So I thought R'
is about a lock that the peer sends.
I send a lock A to the peer. This lock expires. That's counted in E.
Now the lock is expired, and removed from the state. So a refund cannot happen, right?
So I thought R' is about a lock that the peer sends.
Sorry, I misinterpreted your sentence. I read R' is about the refunded locks from me to the peer.
as R' is about the refund_amount for all locks sent from my peer to me.
and not as R' is the total amount of tokens returned from my peer as refunds
I see, the message direction vs lock direction.
This is a rough sketch, it is by no means correct. I'm opening the issue so that we don't lose this proposal:
The idea here is: For a channel A-B, the above definition would allow B to send a balance proof that changes the locked amount of A, with this balance proof A could prove to the smart contract that the tokens have been returned by B to A, so no backwards transfer would be required.
The biggest question that I have with the above is that if a locksroot is also required, or if just a returned amount is sufficient.