-
Notifications
You must be signed in to change notification settings - Fork 84
Unify the response protobuf types #165
Comments
I really like this proposal. One question I have is: How can I represent a warning or just return some log information to the app in the proposal? Let's say I want to attach a warning message to |
If we need this, we could have a log field in the result as well. If it's just for debugging with abci-cli, seems a weak reason. |
There is no warning, Debug, Info, Error. |
Hey Ethan, thank you for the proposal and writeup. BTW, So if we were to split this out, I'd rather it be:
But I'm not sure about leaving the The purpose of Here's a future use-case for response codes. Say that we have a very tiny light-client, so small that it can't keep state, but it can do everything else. Also lets say that it's so small that we want to minimize bandwidth and CPU processing to a reasonable degree. Lets call these "nano-clients". An Internet-of-Things little device could be such a nano-client. Say that this nano-client needs to scan through the transactions of a block and respond to certain events, but it doesn't care about most transactions. The slow way to do this is to just get Merkle proofs for each transaction response (e.g. the The faster way to do this in many cases is to get the whole list of tx response-codes per block, and to scan those numbers to filter. If we only have OK/error response codes, and a non-OK code meant that the transaction could be ignored, then the nano-client has to parse all OK transactions to filter, or, it's possible that there isn't enough information in the transaction bytes, and so the nano-client needs to consult the response tags to filter, and now we're back to the first problem. That's why ResponseCheckTx/ResponseDeliverTx has Query and Commit have codes because we added them a long time ago. Commit shouldn't have a code, we should remove it. SetOption has a code because we wanted a way to respond with an error. I think we want to make these changes:
Regarding errors in general, for messages that don't take user input like Flush, Info, InitChain, BeginBlock, EndBlock, and Commit.... There is no way to handle these errors gracefully, so we might as well panic. We have |
Okay, as far as I have seen, almost all the code refers to code 0 as okay, and not okay as error. I thought we wanted error codes to map to strings in the ui. Much better that way for localization than returning a string in the app. I like your split out of code and log outside of response. I would keep that but just make code int32, and consider 0 or positive a success, and negative an error. And then we can filter easily with future nano clients and also determine errors. The main reason is to unify the interface, and all calls to application can be
This unifies a lot, also the proxy app. We also have empty Request and Response structs now exactly for this symmetry. And using that nicer go Form instead of IsErr() will make code more readable and go- like. Also easier to pass generic errors that are not known tied to one response time. |
That's how it is today, but lets keep our options open since it doesn't hurt.
That's another nice benefit for error codes. Good point. Now I'm in favor of adding
I don't think code should be common for all messages for the reasons stated. Regarding logs, it first it seems like the log could go outside for all messages, but it's probably not a good idea. First, the application really ought to keep its own log in the filesystem, because in general there's a lot going on in an application and it's not always appropriate the fit them into ABCI messages. For example, the app might have more goroutines that log too, and it makes more sense to intersperse the logs resulting from transaction processing, with those other goroutine logs. Second, it helps little to make Tendermint store them... at first I thought that it might be useful to intersperse, so you know what the App did in relation to other Tendermint logging events, but on second thought I realized that it's not true, it makes logging worse. We want CheckTx logs to match up with the state of the App when the CheckTx log was produced, not when Tendermint happened to receive it from the mempool socket, which would be some unknown time after the event occurred. By delaying the writing of log entries by sending them into a channel, we've lost critical causal/synchrony information. (e.g. this CheckTx was processed before or after this DeliverTx). It's not any worse to make the App responsible for logging independently of Tendermint. The ABCI interface is designed to make the App a dead simple state machine w/ most messages called in sequential order (e.g. BeginBlock -> DeliverTx -> EndBlock -> Commit -> ...), so it's not difficult to match the lines in the Tendermint log with the App log. It's (in general) an anti-pattern to push logs from the App to Tendermint, and it's sufficient to log in the app. Ergo, we shouldn't require all ABCI messages to include logs.
That's an API to be implemented in the client. We already do that. But it doesn't make sense to reflect that in the ABCI wire, since an error in most messages should terminate Tendermint or the ABCI connection, as there is no way to recover. For the same reason why sometimes you want to panic rather than return-error, here we want to push an Exception message instead. Maybe you'd prefer that we rename |
I think it might make sense to have both |
We should take tendermint/tendermint#999 into account here - ie. we should have types at the ABCI level that delineate which components of the response are deterministic/consensus and which are not. |
types at the ABCI level?
|
See the latest SDK2: https://github.com/tendermint/abci/blob/sdk2/types/types.proto Do we have a use for SetOption right now? If we move fee handling to Tendermint and genesis state to InitChain, I'm not sure what else we'd want it for. |
Exactly. I just meant have a type in ABCI that doesn't include the non-deterministic stuff - otherwise we need one in Tendermint for computing merkle roots |
I don't have strong feelings about it |
Re sdk2 branch. Looks good. But I don't understand why you dropped data.Bytes for []byte. |
Had a convo with bucky offline. Basically, the whole point of data.Bytes was to help with hex encoding our []byte for a slight, slight benefit of improved debuggability for developers, but it's not worth it if we're going to uglify our .proto files and lord knows what other compatibility problems we'll find later esp when tying ourselves to gogoproto. So... lets simplify. So, in general, []byte in JSON will always be base64. We can make some exceptions. Like our addresses, which could still be cmn.HexBytes (renamed from cmn.Bytes). Actually go-crypto sdk2 branch does this now. So in JSON form it's an encoded string. I don't think we should do this for protobuf since nobody (sane) reads protobuf encoded bytes. So then, we can still do the gogoproto extension and use HexBytes/Bae58Bytes, but in the proto file it would be declared primarily as bytes. Thanks @odeke-em, I like your proposal now. |
I think we probably need to better distinguish the differences between ABCI messages to really clear this up. In short, only those that take user input (CheckTx/DeliverTx/Query/SetOption) can report over the quality of the execution with codes (ie. codes for OK, Not-OK-Because-X, OK-But-Y). The rest should have no possibility for error, since it's not defined what to do in those cases. Thus it seems right that eg. InitChain, BeginBlock, etc. should panic on error - we just need to make sure the panic is caught in the right place and turned into ResponseException so Tendermint can shutdown gracefully. |
Some of the changes (ie. log/info) are on develop, and will land in 0.7. Some, like introducing As for properly handling panics, see #195 |
I would like to simplify the representation of the types, make unified error handling. Write now, some types have a Code and Log field which is used to create IsErr, and IsOk.
I would prefer something more like:
To make this more concrete, now looks something like this:
I would propose something more like
The text was updated successfully, but these errors were encountered: