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

CLI and REST rewrite #324

Closed
faboweb opened this issue Jan 11, 2018 · 39 comments
Closed

CLI and REST rewrite #324

faboweb opened this issue Jan 11, 2018 · 39 comments
Assignees

Comments

@faboweb
Copy link
Contributor

faboweb commented Jan 11, 2018

The idea is to remove a lot of unused functions from the CLI.
Additionally we want to base the CLI and the REST server around actual REST. This means basing all the calls around data-resources and using a standard set of properties to query the entities. The actual manipulation of the data and signing of the transactions is transparent to the developer using the client.

Resources:

  • Version - Version of local code
  • Status - Status of the connected node
  • Keys - Locally stored keys
  • Accounts - Nonce and balances on the blockchain
  • Blocks - All blocks in the blockchain
  • ValidatorSets - Sets of validators at a block-height
  • TXs - All TXs in the blockchain

Defined on these resources are REST actions (GET, POST, PUT, DELETE). This way we unify how developers interact with both ways and minimize the code needed to serve both ways.

GET i.e.:
REST: GET /Blocks/{block-height}
CLI: gaia client blocks {block-height}

POST i.e.:
REST: curl -x POST /keys --data {name: 'Fabos', password: '1234567890', seed: '...........'}
CLI: gaia client keys add --name='Fabos' --password='1234567890' --seed='...........'

POST TX i.e.:
REST: curl -x POST /txs/send --data {_name: 'Fabos', _password: '1234567890', ...payload}
CLI: gaia client txs send --name='Fabos' --password='1234567890' --seed='...........'

PUT/UPDATE i.e.:
REST: curl -x PUT /keys/Fabos --data {password: '1234567890', new_password: '0987654321'}
CLI: gaia client keys update Fabos --password='1234567890' --new_password='0987654321'

Querying i.e.: (search TXs by a certain tag)
REST: curl -x GET /txs?tag={tag}
CLI: gaia client txs --tag={tag}

REST: curl -x GET /txs/{hash}
CLI: gaia client txs {hash}

Limiting returned data i.e.:
REST: GET /Blocks/{height}?select="metainfo.time"
CLI: gaia client blocks {height} --select="metainfo.time"

Summing up:
Top level (gaia {x})

  • node - Entry to running a full node

    • start - Start this full node
    • init - Initialize genesis files for a blockchain
    • unsafe_reset_all - Reset all blockchain data
  • client - Entry to data gathering and manipulation

    • init - Initialize genesis files for a blockchain

    • unsafe_reset_all - Reset all blockchain data

    • actions: GET, POST, PUT, DELETE / get, add, update, remove

      /version

      • GET
        /status
      • GET
        /keys
      • GET: List all keys stored
      • POST: Create new key / Or restore from seed
        /{key_name}
        • PUT: Update password
        • DELETE: Remove key
        • GET: Get key
          /accounts/{address}
      • GET: Get account balances from ABCI app
        /blocks/{height}|'latest'
      • GET: Get block data (header, txs...)
        /validatorsets/{height}|'latest'
      • GET: Get validators for given height
        /txs?tag=string
      • GET
        /{hash}
        • GET
          /send
          /unbond
          /bond
          ...
        • POST
          // maybe use /txs with Content-Type="SendTransaction" as it is more REST

pulling in @ethanfrey

@faboweb faboweb added the API label Jan 11, 2018
@ethanfrey
Copy link
Contributor

Great start. The idea was that the rest api and the cli mirror each other very closely.
Every function is exposed on both sides with the same arguments. We first want to get public feedback on the set of functionality (we cleaned up the existing functions and consolidated duplicate functionality into one). Once there is general approval on the set and organization, we will prepare formal specs as a PR.

Pub/sub for events (new block, new tx) is needed on the rest api only and not included yet as part of this spec. We will make a second issue/proposal for it later to extend the functionality, but this should provide a solid basis to use apps.

@ethanfrey
Copy link
Contributor

ethanfrey commented Jan 11, 2018

Cli equivalents to the GET/POST commands....

gaia keys ...:

  • add <name> --password=<pass> --type=<ed25519|secp256k1|ledger|...> [--seed='...........']
  • update <name> --password=<pass> --new_password=<new_pass>
  • delete <name> --password=<pass>
  • list
  • show <name>

gaia client ...:

  • init
  • version
  • status
  • serve: start LCD, the local REST server, exposing above endpoints
  • block [height] [--select=<header|txs|results>]: This will grab the relevant information from the block at the given height (latest if no height provided). This may map to several rpc calls.
  • validatorset [height]
  • txs --tag=<tag>: search for all tx that match tag
  • tx <hash>: query tx by hash
  • tx send --name=<name> --password=<password> --to=<addr> --amount=<..> ...
  • tx bond --name=<name> --password=<password> --delegate=<addr> --amount=<..> ...
  • ...

@ethanfrey
Copy link
Contributor

ethanfrey commented Jan 11, 2018

Thought was that keys doesn't need init (all gaia client commands need gaia client init, gaia server start needs gaia server init). It also may be shared between client and server to have a robust, secure key management and support for hsms.

If this is unpopular, we can easily embed those commands under gaia client keys ...

@ebuchman
Copy link
Member

Seems like a great start.

Love the idea of the CLI and REST mirroring each other.

Seems you've left out the command to actually start the REST server. gaia lcd ?

I think we want to make sure the gaia node command mirrors tendermint node as much as possible. Granted we have extra nesting there like gaia node unsafe_reset_all and gaia node start but that seems fine.

Does this mean we'll be dropping gaia client query? Since those would be handled with GET on the REST side and we want to mirror, seems it would require us to do things like gaia client account instead. We should make sure we like the feel of that. I don't really have strong opinions either way, but I have thoroughly enjoyed using the gaia CLI :) (way to go frey!)

Will the gaia CLI still support the rpc subcommand to call the Tendermint RPC ? Or will all of that be subsumed by other commands?

@ebuchman
Copy link
Member

It might not make for the best CLI experience if all the things currently under the gaia client query just end up under gaia client. Maybe the bonding stuff will go under gaia client stake ? Not sure exactly what the design should look like there.

So while I like the idea of mirroring the REST API, it might actually make the CLI a little harder to use. Could use more outline on how some of those queries will look like, seems they've been left out above (ie. querying accounts and other application state).

@ebuchman
Copy link
Member

I also like having a pure gaia keys. We shouldn't have to do any initialization to make and list keys, so that makes sense.

@ebuchman
Copy link
Member

Finally, what should this binary actually be called? gaia has served us well for now, but maybe it's time to call it cosmos ?

@jaekwon
Copy link
Contributor

jaekwon commented Jan 11, 2018

chub? cosmos is the network...

@ebuchman
Copy link
Member

I'd go for cosmos-hub then.

But won't we want to also use this tool to access other zones? Not unreasonable for it to be called cosmos ...

@jbibla
Copy link
Contributor

jbibla commented Jan 11, 2018

chub would be really funny 😆

@ethanfrey
Copy link
Contributor

Chub is cool.

Most of these commands would be in the Sdk, so they would be similar in all zones that build on the Sdk.

@ebuchman

Gaia client serve was to start the LCD. We can name it gaia client lcd but thought serve made more sense to non-insiders

As to the queries... Fabo wanted to make them top level. It is shorter. If it is confusing, let us put them all under chub client get... account, etc

@ethanfrey
Copy link
Contributor

Proxy was removed as all needed proxy items should be exposed in the rest.

Rpc calls that we found actually useful were made top level. Block (for Block, header, and commit), validatorset, and status. If there are other rpc calls we need in the ui apps, then we can add them one by one.

Keep the interface clean, add when needed, not just a kitchen sink.

All query stuff has custom commands that can parse.

All TX Actions have custom commands.

What is left? Commits are handled internally by the LCD... Net_info???

@faboweb
Copy link
Contributor Author

faboweb commented Jan 12, 2018

Regarding RPC:
The idea was to make RPC transparent to the dev. You would only request from the endpoint or the web-socket at that path. The LCD then routes to RPC or wherever. This limits the interaction and technology to the outside to just REST and web-sockets.

Regarding CLI:
My first idea was to prefix the resources with the verbs which would mimic REST more. But Frey stated, that it would be complicated to parse the CLI this way.
Examples with prefix:

  • GET -> get gaia client get accounts {address} // "get" could also be "query" like it is right now
  • POST -> add gaia client add keys ...
  • PUT -> update gaia client update keys {key name} ...
  • DELETE -> remove gaia client remove keys {key name} ...

Regarding resources:
How much resources will exist under gaia client [prefix]? Staking will probably just have the resources candidates and bonds (or similar which could also go into txs).

Regarding doubts about special usecases: @ebuchman
If you have doubts about a certain usecase, I am gladly writing examples for you.
Querying accounts:
gaia client get accounts {address} --select="data.coins" or without verb gaia client accounts {address} --select="data.coins"

@jbibla
Copy link
Contributor

jbibla commented Jan 12, 2018

i've read through this thread a couple times and am impressed and pleased. chub is hilarious. i guess my concern is how much work may be required to complete this re-write. and also, do we want to start a re-write so close to launch? not advising for or against, just thought it was worth mentioning. i have the utmost faith in the folks in this thread.

@ebuchman
Copy link
Member

ebuchman commented Jan 12, 2018

lol chub is pretty amazing. We should actually call the hub itself that :P

The above sounds good, thanks @faboweb and @ethanfrey

Though indeed, using the REST verbs in the CLI commands would make it much harder to write, so let's not do that.

Re the re-write, we basically have to do a lot of re-writing to target the new SDK anyways, so it shouldn't be much more work to get the CLI and REST spec to match too.

@ethanfrey
Copy link
Contributor

The organization of the cli is easy, I have to implement all the logic against the new sdk. Most of the pieces are available in tendermint/lite or in cosmos-sdk/client (which needs to be ported).

The big piece is porting the integration of client from old sdk to sdk2. The reorg of cli is just a couple days on top of that.

Jae wanted to personally review all this and approve it before I start work on it. But he is busy writing code. He sorta deferred to bucky for preliminary approval, but I have no energy to start code that will be ripped apart later. I would like the spec approved before starting.

@ethanfrey
Copy link
Contributor

Also realize that without query being implemented in sdk2, no query functionality can be implemented, which while only a small part of the code, is essential to test it works.

@ethanfrey ethanfrey mentioned this issue Jan 15, 2018
16 tasks
@ebuchman
Copy link
Member

Some thoughts about init - should be more flexible: #124

@ebuchman
Copy link
Member

Can we just stick with one binary for now? No one has ever been satisfied breaking things up into multiple binaries. We've consolidated binaries multiple times. What's the reason to not use a single binary ?

Lets leave the password in RAM in the client, do crypto operations there, or use an HSM, anything but send passwords over a socket.

So how's this actually supposed to work w.r.t the UI? The UI boots and the user is prompted for a password - then what ? Obviously the best approach is for the user to use an HSM and then no password needed but some folks wont have an HSM and will need to encrypt on disk - then what ?

@ethanfrey
Copy link
Contributor

ethanfrey commented Jan 19, 2018

@jaekwon Before spec-ing anything out, I want to address the high level design decisions first. I think we may agree on much, and maybe I just don't understand your post fully. If you could respond with your thoughts on these points, it would help me clarify. The location of passwords is a bit unclear to me, but I am flexible. Point 4 below seems most essential to the usability, and I am not sure if we agree or disagree there, so it would be very helpful to see clear responses on those points.

  1. One binary or three?
    I actually slightly preferred separate binaries, and that is what I did in May with Bucky's approval. After months of usage, everyone (UI, greg, rige, bucky) was annoyed by this and gaia now uses one binary since a few months. I am quite neutral in this question, but as there was general consensus by everyone using the tool, I would go with that.

  2. Separate keystore app?
    I agree here. Even if we make one binary with a chub keys ... subcommand, we should also provide a ckeystore app separately for those who just want to use it for signing, which would duplicate the functionality.

  3. Security of passwords
    I actually made an error with the cli here, using --password command line flags. The current version accepts them from stdin without echo, which seems to be the preferred approach when I researched this. (On the command line leaves them in the history)

The REST app is designed to bind to localhost and only be used locally, providing the same functionality as the cli, but in a form more acceptable to the UI. This was a design decision since Feb/March. We also talk of using unix sockets possibly to make it more secure, which is how keybase seems to do it. If you have other ideas to increase the security of the connection between the UI and the LCD (rest daemon), we should implement them as much as possible. The REST server is the client, and I think everyone agrees it is safer to manage private keys in go than in electron.

  1. Functionality of client
    The first step is to use light client proofs to validate headers and proofs returned from a node. I think everyone agrees on this point... that the client needs to validate the rpc results. The question is what functionality we add upon that. This code is designed to run on the client as an adapter between the UI and tendermint rpc.

4.a. constructing binary bytes for the transactions
Matt originally tried to reproduce all binary encoding in the ui, but this was a large timesink and fragile when we changed the tx format during development. Since it is very easy to do json->binary converstion in golang (using the same code as on the server), this seemed to be agreed upon to do the go-wire encoding in this adapter.

4.b. signing the transactions
I was pretty sure we wanted to store private keys in the key store and add support for HSMs in golang as well, and then expose this functionality to the client. Ideally anyone with large accounts will use an HSM so the password issue is dealt with that. we could also store the private keys and do the signing in the UI if that is desired, while still performing (a) in the adapter.

4.c. parsing the key/value used and returned by ABCIQuery
Same as the tx encoding, the keys and values for ABCIQuery are app-specific and not necessarily trivial to encode/decode in the UI. For simplicity, we had designed the system to understand the data structures and parse bytes to Account object to json for use by the UI. Is there an objection to this?

4.d. exposing simplified subset of rpc
To make things nice for UI developers, I proposed to expose a modified version of some of the current rpc commands. If i understand you correctly, you propose to modify the tendermint rpc in those cases where this simplified interface makes more sense? Besides the RPC interface being un-RESTful (which was an explicit decision as I understood from past conversations, not wrong, just not the most standard interface), there are lots of hex-encoded binary bytes, which require external codecs to parse. The second part (parsing/encoding binary) is (a), (c) and more is app-specific and essential to the usability of the client.

@jaekwon
Copy link
Contributor

jaekwon commented Jan 19, 2018

Can we just stick with one binary for now? No one has ever been satisfied breaking things up into multiple binaries. We've consolidated binaries multiple times. What's the reason to not use a single binary ?

Maybe gaiap and gaiad can be merged, under a "gaiad proxy" subcommand with no further nesting of subcommands. But definitely not gaiacli or ckeystore. There's nothing wrong with multiple commands, but there is something wrong with nested subcommands.

https://en.wikipedia.org/wiki/Unix_philosophy

So how's this actually supposed to work w.r.t the UI? The UI boots and the user is prompted for a password - then what ? Obviously the best approach is for the user to use an HSM and then no password needed but some folks wont have an HSM and will need to encrypt on disk - then what ?

If the UI can write to disk, then maybe it can encrypt and store. Just don't use a network request. In the bare minimum, the user can be asked to enter their 12 words every time they need to sign something. But really, they shouldn't be entering their 12 words onto an online computer, so this would only be for the case where they're signing a transaction w/ an offline-computer -- e.g. writing a transaction to a USB drive, loading it onto another computer with the transaction and the UI (which isn't connected to the computer), signing the transaction by entering the 12 words, saving the signed tx to disk (but not the 12 words), transferring the 12 words back to the online computer via a USB drive, loading it to the online-UI, and broadcasting it.

There's never a need to transmit passwords, encrypted or not, via TCP/IP.

@jaekwon
Copy link
Contributor

jaekwon commented Jan 19, 2018

I actually slightly preferred separate binaries, and that is what I did in May with Bucky's approval. After months of usage, everyone (UI, greg, rige, bucky) was annoyed by this and gaia now uses one binary since a few months. I am quite neutral in this question, but as there was general consensus by everyone using the tool, I would go with that.

There's good reason to split these binaries. dockerd != docker. redis-server != redis-cli. We'll want/need to split it sooner or later, so lets save ourselves a lot of pain down the road by splitting them now.

Every blockchain project seems to go through the pain of realizing that they shouldn't add key/wallet management w/ the daemon binaries. Lets learn from their mistakes and not conflate functions. Lets not add them to begin with, and discourage others from adding key/wallet management to these daemons.

Good point, we shouldn't pass them in via flags for that reason.

The REST app is designed to bind to localhost and only be used locally, providing the same functionality as the cli, but in a form more acceptable to the UI. This was a design decision since Feb/March. We also talk of using unix sockets possibly to make it more secure, which is how keybase seems to do it. If you have other ideas to increase the security of the connection between the UI and the LCD (rest daemon), we should implement them as much as possible. The REST server is the client, and I think everyone agrees it is safer to manage private keys in go than in electron.

If we can use electron to create a unix socket, and we understand all the nuances of managing the security of unix sockets, then OK. Without a comprehensive analysis, we can't be confident about the security of this design. For example, what happens if the unix socket times out for any reason, and meanwhile a malicious external program swaps out the .sock file for another one which proxies the the old one? https://superuser.com/questions/484671/can-i-monitor-a-local-unix-domain-socket-like-tcpdump .

OTOH if Electron can access the filesystem, then we can have it bcrypt and store the private key if we wanted it to. It has the private key in its runtime already so I don't see any significant additional risk in signing transactions right there. Using a socket to transfer the password in plaintext, on the other hand, is introducing a new surface of vulnerability. Either we put work into understanding the full extent of this new surface of vulnerability, or we do the more conservative thing.

Even if the proxy node is malicious or gets man-in-the-middle'd, at least we have a chance of not losing our private key. The highest-priority thing to protect is the integrity of the keys. If we get double-spent because the proxy node wasn't being honest, it's (hopefully) not the end of the world.

I think everyone agrees it is safer to manage private keys in go than in electron.

Not if the private key came from the UX. It's strictly worse to send the private key to go, if it came from electron.

Matt originally tried to reproduce all binary encoding in the ui, but this was a large timesink and fragile when we changed the tx format during development. Since it is very easy to do json->binary converstion in golang (using the same code as on the server), this seemed to be agreed upon to do the go-wire encoding in this adapter.

Lets use that shim for now and replace it with js-wire in the near future.

4.b. I was pretty sure we wanted to store private keys in the key store and add support for HSMs in golang as well, and then expose this functionality to the client. Ideally anyone with large accounts will use an HSM so the password issue is dealt with that. we could also store the private keys and do the signing in the UI if that is desired, while still performing (a) in the adapter.

Wouldn't it make more sense for the HSM (ala plugnplay devices as Myetherwallet does it w/ the ledger) to interface directly with the Javascript? I don't see the point of going into the console to connect to the HSM. I mean, I do because I'm extra paranoid, but if we assume that the HSM itself is secure, then there's no need to go to golang to interface with the HSM.

4.c Same as the tx encoding, the keys and values for ABCIQuery are app-specific and not necessarily trivial to encode/decode in the UI. For simplicity, we had designed the system to understand the data structures and parse bytes to Account object to json for use by the UI. Is there an objection to this?

No, that sounds good, and seems to be the point of having gaia* in the first place. In the future maybe we'll have the option to do most of that in the client, and people can use stock tendermint w/ a containerized app.

4.d you propose to modify the tendermint rpc in those cases where this simplified interface makes more sense?

Yes, if we can refactor Tendermint RPC to improve it, I'm in favor of doing it if it's simple. We can continue to upgrade/refactor it after launch as well.

Besides the RPC interface being un-RESTful (which was an explicit decision as I understood from past conversations, not wrong, just not the most standard interface)

We just need to make broadcast_* require a PUT or POST verb. Want to do it and update the docs? Otherwise I don't think it's unrestful to allow POST/PUTs for GETs. We also do a passing job of showing all the RPC commands when you hit "http://localhost:46657/", so I'd say it's restful enough to get started. We could improve our docs and get a little more intelligent with cache response headers.

there are lots of hex-encoded binary bytes, which require external codecs to parse.

We're going to start off by requiring github.com/tendermint/go-wire to encode and decode JSON (the go-wire JSON support is coming, requires a merge from Emmanuel). Would love to discuss why (as opposed to go-wire/data or encoding/json), but that's going to require an hour or so and another issue to discuss. We also have cmn/HexBytes now, pretty much only used for go-crypto/Address at the moment, but otherwise we'll use base-64 going forward for most byte slices as per encoding/json, so that we may support encoding/json support as well in the future (though we may not, as it's got all kinds of issues given the design goals of go-wire, namely interface support). I understand that you're against forking encoding/json, but OTOH it's not uncommon to do so (see protobuf has its own encoder as well), and more importantly, transparent interface-support is incompatible with the standard encoding/json Marshaller/Unmarshaller interface (since there's no way to implement those methods without first registering interfaces & concrete types at init time to some global scope, and that is bad(tm) ).

The second part (parsing/encoding binary) is (a), (c) and more is app-specific and essential to the usability of the client.

Lets use go-wire binary and go-wire json for (a), (c).

@ethanfrey
Copy link
Contributor

Question: does the cli touch the keys? but the REST not? or we push all key handling to js?
Just wondering if we need the key management in golang at all?

@ethanfrey
Copy link
Contributor

ethanfrey commented Jan 19, 2018

Basically, is it the design of pushing so much functionality into this REST daemon that you find insecure? And if so, can you give feedback on the gaiacli spec? I mean, If I just replace chub client with gaiacli in the above examples, is that acceptable? Or are there other changes?

The REST will need a complete overhaul obviously.

@jaekwon
Copy link
Contributor

jaekwon commented Jan 20, 2018

Question: does the cli touch the keys? but the REST not? or we push all key handling to js?

How about this...

  • If it's an HSM, we connect to it directly, e.g. from the UI (javascript) if possible. From the console, we can also connect to an HSM, e.g. from Keystore (just not be a concrete PrivKey type).
  • Otherwise, the UI never asks for 12 words. It only produces a transaction as an armored-string.
  • This armored-string can be exported from the UI in many ways. QR code, save to file, copy to pastebin, and even play a tune for audio transmission.
  • We create ckeystore to be run on a second computer that never touches the internet. You import your transaction there. The armored-string encodes the bytes, which is expected to be JSON. Ckeystore won't let you sign a non-JSON transaction.

Just wondering if we need the key management in golang at all?

Ckeystore is in Golang... Maybe we can start this as a console-only tool for now and later also make it an electron app? This app would be designed with the goal that it doesn't touch the internet and is expected to run offline. (though it should still be audited etc because some people will inevitably run it online.)

Basically, is it the design of pushing so much functionality into this REST daemon that you find insecure

I'm trying to get us to avoid creating kitchen sink binaries, but the insecurity is from surface-area of attack. For example, sending sending data over a (unix) socket to another process exposes the secret to +1 extra process and +1 communication layer. Trying to create firewalls. Having a single binary with so many functions is maybe less of an issue in terms of security.

If I just replace chub client with gaiacli in the above examples, is that acceptable? Or are there other changes?

"gaiacli get accounts ..." -> "gaiacli accounts ..."

We don't need to follow the REST conventions in commands, so we can drop "get". Everything should be in <command> <subcommand> -<flags> form.

@jaekwon
Copy link
Contributor

jaekwon commented Jan 20, 2018

@jolesbi @nylira @mappum ^^ What do you think? Trying to make the UX more secure by enforcing a separate process where one enters the key. We can have another electron app. If we could check for existence of internet (not by pinging our own servers... I wonder if there's a better way, like pinging DNS servers), and quit with a warning message if internet is found.

<electron-wallet Javascript>--(USB)--<HSM>
<electron-wallet ArmorString>--(file,QR,chirp)--<electron-ckeystore>
<electron-wallet ArmorString>--(file)--<ckeystore>

ckeystore will show the transaction JSON visually so one can inspect what they are about to sign.

@ethanfrey
Copy link
Contributor

Okay, I would like to hear the response of the UI team that needs to expose this to the user.

The first design was gaiacli accounts.
I changed to gaiacli get accounts after feedback from bucky

#324 (comment)

Otherwise, it is clear feedback for the cli tools. The separation of TX generation, TX signing, and TX posting mirrors the current 0.7 design. There was the request to simplify this from the UI team.

Basically, for the cli it makes sense and is not that different than the older design I had, with some improvements.

There was lots of feedback from the UI team and they should get involved in this conversation

@ethanfrey
Copy link
Contributor

One more point:

Above:

ckeystore The Cosmos key store, another cli. Not specific to Gaia.

Later:

ckeystore will show the transaction JSON visually so one can inspect what they are about to sign.

I agree it is important to show the JSON tx before signing (or display important info on the ledger)

To show the JSON, ckeystore needs to have the specific tx structs for this application. To decode go-wire binary to json. Thus, ckeystore would have to build rebuilt for each app. This is not a major problem, just mentioning, so gaia-sign or something.

If gaia-sign now has the tx structs, the cli can output json encoding, which you can freely inspect before inputing it into gaia-sign. gaia-sign would then parse it into a struct (same result as parsing the binary) and generate a signature. It would output the signature in JSON(?).

Then you can feed the original unsigned tx json along with one or more signature files into the cli, which will combine them into a signed tx, encode them in binary, and post to the node.

I think this is the cleanest way to handle the separate app, where the communication between the two local components is go-wire JSON, and can be inspected by a user (or electron app).

@jaekwon
Copy link
Contributor

jaekwon commented Jan 21, 2018

To show the JSON, ckeystore needs to have the specific tx structs for this application. To decode go-wire binary to json. Thus, ckeystore would have to build rebuilt for each app. This is not a major problem, just mentioning, so gaia-sign or something.

How about sdk.Tx GetSignBytes() is just expected to return JSON bytes? If it doesn't then ckeystore can show the hex bytes, or otherwise try to load a codec on it.

If the first bytes of binary GetSignBytes() were to include the hash of a schema file, then ckeystore can safely convert to JSON... hmm...

@jaekwon jaekwon closed this as completed Jan 21, 2018
@jaekwon jaekwon reopened this Jan 21, 2018
@jaekwon
Copy link
Contributor

jaekwon commented Jan 21, 2018

How about, GetSignBytes() is always JSON, and for binary the convention is:

{"schema":"<base64 schema file hash bytes>","bytes":"<base64 tx bytes>"}

But otherwise for now we can punt on this by just serializing the whole Tx/Msg to JSON using go-wire MarshalJSON.

@jbibla
Copy link
Contributor

jbibla commented Jan 22, 2018

@jaekwon

Trying to make the UX more secure by enforcing a separate process where one enters the key. We can have another electron app.

this is a cool idea. and i think in the future it would be neat to experiment with this. for launch (and for UX) i think we should be comfortable with hardware support for those who are not ok with storing their seed locally... if i'm understanding correctly.

@faboweb
Copy link
Contributor Author

faboweb commented Jan 22, 2018

Multiple binaries:
Should we include the other people who where strongly opposing this in the decision? @greg-szabo @rigelrozanski

Signing transactions:
The UX of the proposed signing is horrible. The user/developer would need to do several steps even to send a small amount of coins? Do regular wallets do it that way? Wallets I used so far only ask me for a chosen password and then do all the magic in the background. This is what I want for us as well. The coupling of building, signing and sending reduces the complexity very much and will be a huge asset to developers building on the SDK as @adrianbrink already stated. People that are more concerned with their security can still use hardware signing which will be available.

UI communicating with the SDK:
This thread is huge and please forgive me if I missed sth.... We trust our own binary I think. And I think we trust inputting anything into the console regarding our binary. If we really really can't trust communicating via http requests, can we maybe just spin up a child_process for every query and read the returned output + remove any internet functionality from the electron app? What do you think @mappum @nylira?
I think the UI should in the end just be a very very very stupid visual interface to the apps build on the SDK.

Finally:
This thread is too huge for anyone to join in I think. Should we split this up in these topics?:

  • Mulitple binaries
  • CLI structure
  • Signing UX/DX
  • Electron to SDK communication

@rigelrozanski
Copy link
Contributor

Sounds like there are some compelling thought towards breaking up binaries again in this thread... I don't really care if there is a logical decision between others here to use multiple binaries. I'll leave it to the great thinkers here

@nylira
Copy link
Contributor

nylira commented Jan 23, 2018

Re: signing UX

If I'm getting this right, Jae is proposing that we release Cosmos UI as two binaries, an online one to view and create transactions -- CosmosUI, and an offline to hold keys and sign transactions -- CKeystore. This means to send coins, the user will have to:

  1. Create the transaction in CosmosUI
  2. Export the transaction to a USB drive
  3. Get access to their offline computer
  4. Insert the USB drive with the transaction data into the offline computer
  5. Import the transaction data into CKeystore
  6. Sign the transaction with their private key
  7. Export the signed transaction to the USB drive
  8. Get access to their online computer
  9. Insert the USB drive with the signed transaction into the online computer
  10. Import the signed transaction into CosmosUI
  11. Confirm sending the transaction

If that is the primary send flow for users, I think a lot of people are going to be turned off from using Cosmos due to the time investment and complexity. I understand the security advantages. But --
using physical media to transport data between computers is archaic.

  • What if they don't have another offline computer? Most people only have a laptop and a phone, both of which are internet connected.
  • Discourages end-users interested in testing the app with a few tokens they earned from a faucet
  • If they only have five bucks in the UI, they don't need this level of security
  • This will increase the complexity of implementing an automated buy/payment feature (let's say someone wants to implement Netflix on Cosmos)
  • Other major cryptos don't require this, and the average person will see this UX as a step backwards compared to the ease of entering in a password to Electrum/MetaMask and instantly sending funds.
  • Ledger provides better UX, but those are out of stock until March 26th (https://www.ledgerwallet.com/products/ledger-nano-s), which means user acquisition is going to be very slow.

Here are my ideas:

  1. Drop the extra security requirement with the two binaries and just allow password-verified sending. Requiring either the two binary flow or a ledger is going to throttle our user acquisition to hardcore believers. We can create a warning in the app about how users should really get a hardware wallet.

  2. Work with Ledger or some other hardware company to develop a Cosmos-branded HSM that we can sell for a token amount -- let's say $10, or we hand out for free at conventions, etc. This HSM needs to have some ATOMs preloaded on it so users are excited to purchase and set up this device. It's okay to sell this at a loss to increase our user base.

  3. A lot of companies are using an in-between level of security with the requirement of a code from Google Authenticator/Authy. Could we use something like this as a stop-gap between fully offline secondary computer and fully-online password-only verification? Most people are familiar with using these apps already, and almost all of them will have phones.

@jbibla
Copy link
Contributor

jbibla commented Jan 23, 2018

please include tx UID's in this ticket #318

@faboweb
Copy link
Contributor Author

faboweb commented Jan 24, 2018

I refactored this huge thread:

I tryied to add key quotes from this thread. Please forgive me, if I missed information.

I will close this thread in favor of the others. Feel free to reopen it, if you disagree.

@faboweb faboweb closed this as completed Jan 24, 2018
@jaekwon
Copy link
Contributor

jaekwon commented Jan 30, 2018

@nylira What if they don't have another offline computer? Most people only have a laptop and a phone, both of which are internet connected.

They can use a hardware HSM, which most people should be using, great. Otherwise the offline computer is the HSM. I'm maybe ok with allowing users to enter their password or whatever on an online computer, but we absolutely must provide the offline signing binary. We certainly need it. We won't necessarily be relying on an HSM.

@jaekwon
Copy link
Contributor

jaekwon commented Jan 30, 2018

A lot of companies are using an in-between level of security with the requirement of a code from Google Authenticator/Authy. Could we use something like this as a stop-gap between fully offline secondary computer and fully-online password-only verification? Most people are familiar with using these apps already, and almost all of them will have phones.

No, those don't help w/ private key management. It's possible to do more, but not something for us to tackle right now.

ParthDesai pushed a commit to ChorusOne/cosmos-sdk that referenced this issue Apr 19, 2021
rootulp referenced this issue in rootulp/cosmos-sdk Jul 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants