-
Notifications
You must be signed in to change notification settings - Fork 672
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
OnRecv changes to revert state on failed acknowledgement #91
Comments
I agree with the general design and am more in line with the 2nd case. One thing I am grappling with is that in Go, if a function returns This choice has been made over and over again in the SDK. For example, defining a standard set of AnteHandlers, which run before the contract and the rollback logic in base app. This is far less flexible and powerful than the approach I had suggested, but is much more obvious for external devs just to use it. |
I also am in favor of the second approach. I don't believe there's a reason for an error returned in I think limiting developer choice here is worthwhile for simplicity unless there's a very strong reason that we might want to support this case 1 possibility: |
One thing I realized about the second approach that is slightly odd is that the error returned to core IBC is never logged (it is likely logged in the failed ack by the app developer) Any thoughts about just replacing the error with the boolean? return result, failedAck, revert One nice side benefit of removing the error is that the return signature loses conventional golang notions of what an error means. It is a little more explicit to the app developer in indicating that something different happens in this callback |
I would actually take another approach, by having the error actually carry the failed acknowledgement packet. So you get: return result, successAck, nil or err := failingAckError(failedAck)
return nil, nil, err Passing thing info via the error requires a special interface like: type AckFailure interface {
error
Acknowledgement() []byte
} I would even go father (making this dev-friendly) that if the error doesn't implement var ack []byte
if ackErr, ok := err.(AckFailure); ok {
ack = ackErr.Acknowledgement()
} else {
resp := channeltypes.Acknowledgement{Error: err.String()}
// FIXME: handle error here
ack, _ = json.Marshal(resp)
} |
I like the proposal in general, but two things strike me as odd.
type Acknowledgement interface {
Success() bool
Acknowledgement() []byte
}
If we used an acknowledgement interface to specify success or failure, we could end up with just returning the acknowledgement itself (The result return value is currently discarded and should be removed var ack channel.Acknowledgement
if err != nil {
ack = MyFailedAck{err}
} else {
ack = MySuccessAck{}
}
return ack in core ibc if ack.Success() {
// write state changes
writeFn()
}
WriteAcknowledgement(ack.Acknowledgement()) |
I like this idea. And since you can no longer return []byte, it forces devs to explicitly mark it as a success or failure |
* Change go package name * Rename links * Use up to date Tendermint instead of lazyledger-core * Switch to plain Tendermint v0.34.13 * update mempool code in mempool directory * update go.mod * lazyledger-core => tendermint * lazyledger/lazyledger-app => celestiaorg/celestia-app (with replace directive) * lazyledger/cosmos-sdk => cosmos-sdk * re-generated mock App * code updated because of changes in Tendermint * Rename Data Availability Layer Client
Summary
Currently if partial application logic occurs in the
OnRecvPacket
callback and a failed acknowledgement is returned, these partial state changes persist. See #68There are two potential solutions:
Adding a 4th argument allows the most flexibility since the application developer can revert application state on a failed acknowledgement and still decide to revert the entire transaction in a unique situation.
Reverting all application logic on an error returned makes the most sense if there exists no use case to revert the entire transaction. Note, a panic in the callback will result in a reverted transaction. Returning an error which results in a successful SDK transaction is semantically different than the other callbacks. Returning an error in all the other callbacks results in the entire transaction failing
The 1st case might look like this at the application level
or
or
where true indicates to revert the application state and the error indicates if the transaction should be reverted.
The 2nd case might look like this at the application level
or
NOTE: using the following is a non-atomic failed callback, this could be potentially dangerous if the developer is not aware of these concerns.
For Admin Use
The text was updated successfully, but these errors were encountered: