-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
R4R: CoreContext Refactor #1741
Conversation
client/utils/utils.go
Outdated
// signed transaction to a node. | ||
func SendTx(txCtx authctx.TxContext, queryCtx context.QueryContext, from []byte, name string, msgs []sdk.Msg) error { | ||
if txCtx.AccountNumber == 0 { | ||
accNum, err := queryCtx.GetAccountNumber(from) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When rebasing, can you be sure to add the "EnsureAccountExists" function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ValarDragon why is that? SendTx
does what EnsureAccountExists
virtually did. Do you want me to rip that out and call it EnsureAccountExists
which SendTx
would call?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally I'd like the more user-friendly error message which EnsureAccountExists
provides before checking the account number / sequence. If the account doesn't exist, then we shouldn't be printing messages for updating account num / sequence, and we should never get to the point where it signs. (Then we're asking for password, and only get returned with an unfriendly ABCI error)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see what you mean. Yeah I think I can leverage something similar 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll add a method to QueryContext#EnsureAccountExists
. This will get called before the any signing even happens.
Edit: nvm, I already have GetAccount
. I'll just use this.
type KeyType uint | ||
|
||
// Info KeyTypes | ||
const ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think key types is a great idea!
In the future, hopefully we can offload more code onto the key type, rather than have switch statements everyhere!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe KeyType should be a string?
@ValarDragon @cwgoes would love some initial/high-level feedback if this is a good way to approach things. If so, then all that's left is updating all the internal CLI run functions. |
Anything else you're looking for feedback on, other than what I commented on? |
@ValarDragon, nope! I updated the |
Maybe i'm misunderstanding. I thought |
c8d8e17
to
c746e31
Compare
c746e31
to
9fce3cf
Compare
9fce3cf
to
05832e5
Compare
6e9f11a
to
afdec83
Compare
afdec83
to
ff5439a
Compare
ff5439a
to
cd8e0df
Compare
4828e0c
to
7312475
Compare
Codecov Report
@@ Coverage Diff @@
## develop #1741 +/- ##
===========================================
+ Coverage 63.55% 64.68% +1.13%
===========================================
Files 119 114 -5
Lines 7062 6782 -280
===========================================
- Hits 4488 4387 -101
+ Misses 2314 2115 -199
- Partials 260 280 +20 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First pass (apologies for the delay in review) - definitely progress, this is still rife with conditionals but I guess that can't really be avoided.
Also I know @sunnya97 was working on integrating the keepers into the context somehow (so that gaiacli
could just call keeper functions to query, which would be super convenient) - not sure exactly what the implementation plan is there but worth touching base.
This also needs a rebase/merge with develop.
client/context/context.go
Outdated
rpcclient "github.com/tendermint/tendermint/rpc/client" | ||
) | ||
|
||
const ctxAccStoreName = "acc" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm should this be a constant? Why not a QueryContext
field in case we want to change it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact we have QueryContext.AccountStore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, indeed it is already a field in the QueryContext
, however:
- There is no path (from what I can tell) where this is actually configurable or desirable (i.e. everywhere in the code uses
acc
) - Since there is no CLI flag for it, a user can just do
queryCtx.WithAccountStore(...)
.
I'm happy to revert it to being hard-coded.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks fine for now.
client/context/context.go
Outdated
func (ctx QueryContext) WithUseLedger(useLedger bool) QueryContext { | ||
ctx.UseLedger = useLedger | ||
return ctx | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are some fields in QueryContext
without WithXYZ
functions, although I guess if you didn't need to use them it doesn't matter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I'll leave as is for now 👍
client/context/query.go
Outdated
return res, err | ||
} | ||
|
||
if res.CheckTx.Code != uint32(0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we reference some constant here - sdk.ABCICodeOK
in types/
IIRC?
client/context/query.go
Outdated
res.CheckTx.Log) | ||
} | ||
|
||
if res.DeliverTx.Code != uint32(0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto on using a constant.
client/context/query.go
Outdated
} | ||
|
||
resp := result.Response | ||
if resp.Code != uint32(0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sdk.ABCICodeOK
client/utils/utils.go
Outdated
return err | ||
} | ||
|
||
if txCtx.AccountNumber == 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This really isn't the right check - what if the account number was intentionally tried as 0
? I think we want to check whether or not the user passed the --account-number
flag at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, it seems to be identical to the logic that currently exists (unless I'm missing something?):
https://github.com/cosmos/cosmos-sdk/blob/develop/client/context/viper.go#L105-L122
If the client does indeed intentionally pass 0
, then it'll look it up automatically -- kind of quirky, I understand.
If, as you're suggesting, we want to check if the client passed 0
and actually go with that, then'll be need to introduce the dependency of viper here. Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't we just change the default value to like -1
to mean automatic?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, but then the UX will be a little weird cause the CLI description will have the default in there of -1
.
Let me think on this a bit more -- I can probably come up with a cleaner way outside the scope of utils
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good! I'd actually recommend just putting a "TODO: " above the relevant lines / moving this to a new issue (since this isn't a performance regression). We can do these UI nice to haves
until later! (I doubt practically anyone will be doing --sequence=0 for the next month)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, fair point! I'll do this :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, it seems to be identical to the logic that currently exists (unless I'm missing something?):
It is; the current logic is wrong. Unfortunately IIRC it's wrong due to a bug in Viper which we couldn't fix without forking the upstream.
I guess it's fine to leave as-is (with a comment) for now.
client/utils/utils.go
Outdated
txCtx = txCtx.WithAccountNumber(accNum) | ||
} | ||
|
||
if txCtx.Sequence == 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above, with --sequence
instead of --account-number
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above.
crypto/keys/types.go
Outdated
|
||
// String implements the stringer interface for KeyType. | ||
func (kt KeyType) String() string { | ||
keyTypes := map[KeyType]string{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be a constant? No need to recreate a map every time .String()
is called.
} | ||
|
||
ctx.Logger.Write(bz) | ||
io.WriteString(ctx.Logger, "\n") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be better to use the logger here instead of just io.WriteString
and fmt.Printf
in various places? Although I guess we want machine-readable output and the logger adds extra info - maybe we could have a json
logger and a human-readable
logger though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm not sure I follow? The io.WriteString
is just a convenience method for writing a newline. I can easily just append a newline byte to bz
. The actual logger here is os.Stdout
. I also don't see any fmt.Printf
s.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, you're right, I misread - never mind.
356574c
to
aa7a016
Compare
aa7a016
to
debbf0d
Compare
@alexanderbez while we're still reviewing, could you hold off on squashing? It makes it harder to to check if a fix was resolved as intended. I think we should actually update the PR template to not encourage squashing, and only have the merger squash when merging the PR. (Unless specific commit history is requested, or if review is complete) |
@ValarDragon sorry, I squashed already (to resolve rebasing). I won't squash from here on out until approved 👍 |
@cwgoes, @ValarDragon I believe I addressed majority of your concerns and comments. Regarding some aspects being rife with conditionals, if you could point them out, I'd be happy to improve! But generally I found there is little way around it just due to the nature of the way the context is used. Regarding @sunnya97's proposed integration of keepers -- great idea, but let's address that in a separate PR that uses this as the basis 👍 |
client/context/query.go
Outdated
// queryStore performs a query from a Tendermint node with the provided a store | ||
// name and path. | ||
func (ctx QueryContext) queryStore(key cmn.HexBytes, storeName, endPath string) ([]byte, error) { | ||
path := fmt.Sprintf("/store/%s/%s", storeName, endPath) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe "store" here should likewise be parameterized
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That prefix (/store
for store queries) is hardcoded in baseapp
client/keys/utils.go
Outdated
|
||
// we only need a passphrase for locally stored keys | ||
if keyInfo.GetType() == keys.TypeLocal { | ||
passphrase, err = ReadPassphraseFromStdin(name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: Make Issue to address this before launch
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(we shouldn't be passing around passphrases even in memory)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There already is an issue for this. #864
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would we avoid storing the passphrase (transiently) in memory? We need to decrypt the encrypted keyfile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
client/tx/broadcast.go
Outdated
@@ -13,7 +13,7 @@ type BroadcastTxBody struct { | |||
} | |||
|
|||
// BroadcastTx REST Handler | |||
func BroadcastTxRequestHandlerFn(ctx context.CoreContext) http.HandlerFunc { | |||
func BroadcastTxRequestHandlerFn(queryTx context.QueryContext) http.HandlerFunc { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
queryTx?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
errr typo. gracias.
client/tx/search.go
Outdated
@@ -53,19 +57,22 @@ func SearchTxCmd(cdc *wire.Codec) *cobra.Command { | |||
return cmd | |||
} | |||
|
|||
func searchTxs(ctx context.CoreContext, cdc *wire.Codec, tags []string) ([]txInfo, error) { | |||
func searchTxs(queryTx context.QueryContext, cdc *wire.Codec, tags []string) ([]txInfo, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
queryTx?
) | ||
|
||
// TxContext implements a transaction context created in SDK modules. | ||
type TxContext struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TxBuilder?
x/auth/client/context/utils.go
Outdated
|
||
// defaultChainID returns the chain ID from the genesis file if present. An | ||
// error is returned if the file cannot be read or parsed. | ||
func defaultChainID() (string, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems kinda weird to define this here... should it be defined in tendermint/commands?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if so maybe a NOTE is enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll add a note because I do not have enough context here. Honestly, I think we should remove it all together and require that the user always provide the correct chainID
.
@@ -68,3 +69,14 @@ BUG FIXES | |||
* \#1828 Force user to specify amount on create-validator command by removing default | |||
* \#1839 Fixed bug where intra-tx counter wasn't set correctly for genesis validators | |||
* [tests] \#1675 Fix non-deterministic `test_cover` | |||
* [client] \#1551: Refactored `CoreContext` | |||
* Renamed `CoreContext` to `QueryContext` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
propose: QueryContext -> CliContext. Since Query isn't the only thing we're doing there.
Overall great refactor for splitting the piece into two. Have a few items commented, like renaming QueryContext to CliContext. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK
Agree with Jae on the renaming but not strongly opinionated; my previous comments have all been addressed.
- Rename QueryContext - Add a few TODOs
ChangeLog
CoreContext
.QueryContext
now facilitates querying and sending txs andTxContext
facilitates building and signing txs.GetKeyInfo
andGetPassphrase
as a general helper as I saw the same logic being used a lotkey.Info
opposed to checking just stringsI've updated the
democoin
cool cmd to show how the new contexts would be used. One thing I came across and am not sure if it's the best approach is theutils.SendTx
. That is whatEnsureSignBuildBroadcast
used to handle, but now that the logic and concerns have been split, not sure where to place that. Maybeutils
is fine?docs/
)CHANGELOG.md
cmd/gaia
andexamples/
closes: #1551
For Admin Use: