Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop a gas slot based settlement_timeout definition #383

Open
3 tasks
konradkonrad opened this issue Feb 8, 2017 · 6 comments
Open
3 tasks

Develop a gas slot based settlement_timeout definition #383

konradkonrad opened this issue Feb 8, 2017 · 6 comments

Comments

@konradkonrad
Copy link
Contributor

konradkonrad commented Feb 8, 2017

Problem Definition

Currently we have a fixed block number "settlement_timeout" (ST) that needs to pass after close was called in the Channel. The number is a guess with some safety margins to allow both participants to get all pre-settlement transactions confirmed (claiming locks and updating/disputing the courtesy balance).
However, there can be situations where this timeout is not long enough, because there wasn't enough gas available in the last ST blocks (e.g. because of deliberate attacks or just high gas usage/saturation). So a situation can arise where Bob calls settle before Alice could claim all locks and Alice would lose asset.

Solution

One potential solution to this is to require a "proof of available gas" in the settle call. It would roughly look like this:

After close the amount of potential transactions is bound by the number of open locks + a potential call to update the non-closing-party's balance. I assume we can predict the gas cost for each of these operations. I will call these gas costs "required gas slots".

The caller of settle must provide a number of block headers since the call to close. The contract will check the block header's available gas (block.gas_limit - block.gas_used) and match the required gas slots with the available gas slots.

The settlement will only proceed if this proof, available_gas_slots >= required_gas_slots, is successful. Yet we may still want to keep a minimum fixed settlement_timeout as a lower bound, because we need it for lock timeouts in transfers.

This will prevent situations where a channel participant loses asset just due to full blocks.

Tasklist

  • compute the required gas slots in solidity
  • compute the available gas slots in solidity (see maybe https://github.com/mhhf/sol-rlp https://github.com/androlo/standard-contracts/blob/master/contracts/src/codec/RLP.sol)
  • assess implications for transfer/lock timeouts: it may make sense to move away from fixed defaults for most/all transfer/lock timeouts. These timeouts provide safety margins for how long to hold on to an in-flight hashlock/secret without enforcing the payout on-chain. Having contracted guarantees that the actual settlement_timeout period will have been usable for lock claiming transactions may either allow to reduce the safety margins or allow for better estimates for these margins. At this point in time it is over my head what the implications are.
@LefterisJP
Copy link
Contributor

LefterisJP commented Feb 8, 2017

The caller of settle must provide a number of block headers since the call to close. The contract will check the block header's available gas (block.gas_limit - block.gas_used) and match the required gas slots with the available gas slots.

Do you mean that the caller of settle() should provide all block headers since close() as arguments to the settle() function? And then settle() should have logic to decode each header and get the gas_used out of them?

@hackaugusto
Copy link
Contributor

hackaugusto commented Feb 8, 2017

Do you mean that the caller of settle() should provide all block headers since close() as arguments to the settle() function?

I don't think the idea is to provide all block headers since close, but a sufficient number of headers where the sum of available_gas from these is enough for the other counter party to call unlock on all pending locks, proving that there was enough time to unlock any pending locks.

My 2 cents:

Ideally the gas slots proof would be in relation to the lock's expiration block instead of the channel's close block, since after the close block there could be lots of gas slots that couldn't be used with a given lock, because the secret is not revealed yet and it may be learned up to the lock's expiration. The meaning of the proof would be "for each of the pending locks, this is a proof of the first available gas slot since the lock expiration".

The above sort of implies that a "out of gas slot proof" should be added to the unlock function, the unlock transaction would contain a proof that it slipped after the expiration block because of the lack of gas slots, effectively extending the lock's expiration.

With that said, I think it's best to keep this complexity in the choice of the settlement period and lock's expiration instead of shifting it to the smart contract, the gas slot strategy basically allows for a smaller expiration value since the participants can provide a proof to extend the expiration period, instead of using a large expiration that accounts for the worst case (I'm assuming the out of gas slot thing), but I think the larger expiration periods is easier to implement and to reason about.

@konradkonrad
Copy link
Contributor Author

a sufficient number of headers where the sum of available_gas from these is enough for the other counter party to call unlock on all pending locks, proving that there was enough time to unlock any pending locks.

well I am afraid that just the sum wouldn't be enough, instead we would need to show that there would have been enough "slots" for complete unlock transactions (if we need 1000 gas to call unlock once and there were 10 blocks with 100 available_gas the transaction would not have been possible).

The above sort of implies that a "out of gas slot proof" should be added to the unlock function, the unlock transaction would contain a proof that it slipped after the expiration block because of the lack of gas slots, effectively extending the lock's expiration.

Yeah, I think that's right: unlock should allow for a delay_justification. But that sounds terrible to prove just in time: Alice tries to unlock lock A (with expiration=X) in block X; block X is full. Now Alice needs to provide the proof and retry in block X+1.

I think it's best to keep this complexity in the choice of the settlement period and lock's expiration instead of shifting it to the smart contract, the gas slot strategy basically allows for a smaller expiration value since the participants can provide a proof to extend the expiration period, instead of using a large expiration that accounts for the worst case (I'm assuming the out of gas slot thing), but I think the larger expiration periods is easier to implement and to reason about

I agree in regards to complexity, but this proposal aims to address the congestion/flood issue [see also https://lightning.network/lightning-network-paper.pdf 3.3.1/Timestop] in a way that does not require wild ass guesses for a "safe" timeout.
Note, that a safe large timeout would also need to be set ever higher with higher usage of the network, because if more closing channels have to wait until the very end of their settlement_timeout for unlocking because of congestion, they will compete for the few last slots, thereby making the problem worse. This proposal aims to avoid such cascading failure, by allowing for a timestop proof (to use the LN lingo here) in the smart contracts.
Noted though, that the lock expiry is independent of the closing block and makes things pretty complex. This will need some research.

@LefterisJP
Copy link
Contributor

So the idea would be to provide a sufficient amount of headers since close where there would have been enough gas to facilitate the unlock function?

I understand the problem we are trying to solve (congested block spam blocking in-time settlements), but this sounds like a really complex thing to move into the smart contract logic. Providing a sufficient amount of block headers to the contract and having RLP-decoding logic (we can use something like this) would be quite complex and expensive as far as gas is concerned.

Let's put some thought into it and see what we come up with, but after the MVP as it's not a priority right now and for the purposes of the MVP a high enough settlement_timeout is considered sufficient.

@heikoheiko
Copy link
Contributor

heikoheiko commented Jun 13, 2017

Right, not highest priority atm.
Please open an EIP to track gas usage of old blocks similar to ethereum/EIPs#210

This is needed for all state channel based apps. Vitalik is aware of the issue and in support of supporting it.

@konradkonrad
Copy link
Contributor Author

The above sort of implies that a "out of gas slot proof" should be added to the unlock function, the unlock transaction would contain a proof that it slipped after the expiration block because of the lack of gas slots, effectively extending the lock's expiration.

Yeah, I think that's right: unlock should allow for a delay_justification. But that sounds terrible to prove just in time: Alice tries to unlock lock A (with expiration=X) in block X; block X is full. Now Alice needs to provide the proof and retry in block X+1.

Btw: I do not consider this "right" anymore. I think the only reasonable mode is provide proof, that other parties had a chance to respond in time, which is to be measured in available gas slots.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants